将内核函数的参数作为C ++结构传递?

时间:2013-02-03 14:58:44

标签: c++ struct cuda parameter-passing

我想将内核函数的参数作为结构给出,如

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

出于此目的,我需要使用cudaMalloc()初始化设备指针,但我怎么能初始化。这个函数的结构包括我想要通过的这些参数。或者我必须单独传递它们吗?

2 个答案:

答案 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);

答案 1 :(得分:2)

您可以通过复制将此结构传递给内核。 请记住,传送到内核的参数总大小不得超过Fermi上4KB的前费米卡上的256B。

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

我强烈建议您避免在C ++代码中使用此struc。 而不是

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);