你的方法应该是可行的。当您按值传递对象作为内核参数时(正如您所指出的),实际上不需要进行太多与从主机到设备的传输相关的设置。
您需要在主机和设备上正确分配数据,并使用cudaMemcpy
在适当的点键入操作来移动数据,就像在普通 CUDA 程序中一样。
在全局范围内声明对象时需要注意的一件事是,建议这样做not在对象的构造函数或析构函数中使用 CUDA API 调用。原因已涵盖here https://stackoverflow.com/questions/24869167/trouble-launching-cuda-kernels-from-static-initialization-code,我这里就不重复了。尽管这种处理主要集中在 main 之前启动的内核,但 CUDA 延迟初始化也会影响在 main 之外执行的任何 CUDA API 调用main
范围,适用于在全局范围内实例化的对象的构造函数和析构函数。
以下是您所展示的一个充实的示例。我基本上没有更改您已经编写的代码,只是为您没有添加的代码添加了一些方法定义。显然这里有很多不同的可能方法。有关更多示例,您可能需要查看CUDA C++集成示例代码 http://docs.nvidia.com/cuda/cuda-samples/index.html#cpp-integration.
这是围绕您所展示的内容的一个有效示例:
$ cat t1236.cu
#include <cstdio>
class myClass
{
public:
bool bool_var; // Set from host and readable from device
int data_size; // Set from host
__host__ myClass();
__host__ ~myClass();
__host__ void setValues(bool iftrue, int size);
__device__ void dosomething(int device_parameter);
__host__ void export_data();
// completely unknown methods
__host__ void prepareDeviceObj();
__host__ void retrieveDataToHost();
private:
int *data; // Filled in device, shared between threads, at the end copied back to host for data output
int *h_data;
};
__host__ myClass::myClass()
{
}
__host__ myClass::~myClass()
{
}
__host__ void myClass::prepareDeviceObj(){
cudaMemcpy(data, h_data, data_size*sizeof(h_data[0]), cudaMemcpyHostToDevice);
}
__host__ void myClass::retrieveDataToHost(){
cudaMemcpy(h_data, data, data_size*sizeof(h_data[0]), cudaMemcpyDeviceToHost);
}
__host__ void myClass::setValues(bool iftrue, int size)
{
bool_var = iftrue;
data_size = size;
cudaMalloc(&data, data_size*sizeof(data[0]));
h_data = (int *)malloc(data_size*sizeof(h_data[0]));
memset(h_data, 0, data_size*sizeof(h_data[0]));
}
__device__ void myClass::dosomething(int idx)
{
int toadd = idx+data_size;
atomicAdd(&(data[idx]), toadd); // data should be unique among threads
}
__host__ void myClass::export_data(){
for (int i = 0; i < data_size; i++) printf("%d ", h_data[i]);
printf("\n");
cudaFree(data);
free(h_data);
}
__global__ void myKernel(myClass obj)
{
const int idx = blockIdx.x*blockDim.x + threadIdx.x;
if(idx < obj.data_size)
{
if(!obj.bool_var)
printf("Object is not up to any task here!");
else
{
//printf("Object is ready!");
obj.dosomething(idx);
}
}
}
myClass globalInstance;
int main(int argc, char** argv)
{
int some_number = 40;
globalInstance.setValues(true, some_number);
globalInstance.prepareDeviceObj();
myKernel<<<1,some_number>>>(globalInstance);
globalInstance.retrieveDataToHost();
globalInstance.export_data();
exit(EXIT_SUCCESS);
}
$ nvcc -o t1236 t1236.cu
$ cuda-memcheck ./t1236
========= CUDA-MEMCHECK
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
========= ERROR SUMMARY: 0 errors
$