1

我想将内核函数的参数作为给定的结构传递,例如

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

为此,我需要初始化一个设备指针,cudaMalloc()但我该如何初始化。这个函数的这样一个结构,包括我打算传递的这些参数。还是我必须单独通过它们?

4

2 回答 2

5

只需像任何其他参数一样将结构按值传递给内核:

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

等等

于 2013-02-03T17:52:09.697 回答
2

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

因此,您必须使用 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);
于 2013-02-03T15:37:16.417 回答