2013-02-03 69 views
0

我想与结构类似将内核函数的参数作为C++结构体?

struct kernel_data { 
    double *A; 
    double *B; 
    double *C; 
    const int *A_dims; 
    const int *B_dims; 
    int C_dims[2]; 
}; 

为宗旨,我需要初始化设备,终场前cudaMalloc()给出传递内核函数的参数,但我怎么能初始化。这个函数包含这些参数,我打算通过这些参数。或者我必须单独传递它们?

回答

2

你可以通过拷贝内核来传递这个结构。 请记住,在Fermi上的前费米卡4KB上传递给内核的参数的总大小不得超过256B。

因此,您必须使用cudaMalloc来分配设备内存,而不是您在结构中设置指向设备内存的指针。最后,你通过拷贝将你的结构传递给内核。

我强烈建议您避免在C++代码中使用此结构。取而代之的

struct kernel_data { 
    double *A; 
    double *B; 
    double *C; 
    const int *A_dims; 
    const int *B_dims; 
    int C_dims[2]; 
}; 

你应该做这样的事情

class DeviceData{ 
public: 
    DeviceData(...){//Do cudaMalloc here} 
    ~DeviceData(...){//Do cudaFree here} 
private: 
    double *_A; 
    int _dims;  
}; 

这个类将保持设备上可用的数据,这是异常安全。 比你可以实现一个包装,可以传递给内核

class DeviceDataWrapper{ 
public: 
    __host__ DeviceDataWrapper(DeviceData& device): 
     _A(device._A), 
     _dims(device._dims) 
     {} 

    __forceinline__ __device__ double* data(){return _A;} 
    __forceinline__ __device__ int dims()const{return _dims;} 

private: 
    double *_A; 
    int _dims; 
} 

,然后调用内核以这种方式

__global__ void myKernel(DeviceDataWrapper a, DeviceDataWrapper b, DeviceData2Wrapper c){ 
//do something like a.data()[0] = 1; 
} 

DeviceData A,B; 
DeviceData2 C; 
myKernel<<< >>>(A,B,C); 
+0

该结构的副本将太大,更不用说256个字节的尺寸(以及限制只适用于计算1.x能力的硬件)。 – talonmies

+0

这只是一个提醒,如果你建立的分层结构,可以经常达到限制。 –

3

通过价值结构就传递给内核,就像任何其他参数:

struct kernel_data args; 

cudaMalloc(&(args.A), sizeof(double)*.....); 
cudaMalloc(&(args.B), sizeof(double)*.....); 
cudaMalloc(&(args.C), sizeof(double)*.....); 
cudaMalloc(&(args.A_dims), sizeof(int)*.....); 
cudaMalloc(&(args.B_dims), sizeof(int)*.....); 

kernel<<<....>>>(args); 

有一个理论上的限制参数列表大小从256个字节到4KB,这取决于你用什么硬件,如果你曾经超过它,复制任何东西将args结构转换为设备分配并将其作为指针传递,或者将其复制到常量内存指针。

从主机初始化阵列,只需使用标准cudaMemcpy呼叫:

cudaMemcpy(args.A, hostA, sizeof(double)*....., cudaMemcpyHostToDevice);