如何将嵌套结构的成员复制到 CUDA 设备的内存空间?

Posted

技术标签:

【中文标题】如何将嵌套结构的成员复制到 CUDA 设备的内存空间?【英文标题】:How can I copy the members of nested structs to a CUDA device's memory space? 【发布时间】:2011-10-10 07:12:56 【问题描述】:

我正在尝试将一些嵌套结构复制到设备内存中,以便在 CUDA 加速神经网络模拟器中使用内核。此代码链接并运行,但会引发一些异常和 CUDA 错误:

typedef struct rdLayer

    long NeuronQty ;
    long DendriteQty ;

    cuDoubleComplex *gpuWeights ;
    cuDoubleComplex *gpuZOutputs ;
    cuDoubleComplex *gpuDeltas ;
    cuDoubleComplex *gpuUnWeights ;
 rdLayer;

typedef struct rdNetwork

    long SectorQty;
    double K_DIV_TWO_PI;
    double two_pi_div_sect_qty;
    cuDoubleComplex *gpuSectorBdry;
    long LayerQty;
    rdLayer *rLayer;
 rdNetwork;

struct rdLearningSet 

    long EvalMode ;
    long SampleQty ;
    long InputQty ;
    long OutputQty ;
    long ContOutputs ;
    long SampleIdxReq ;

    cuDoubleComplex *gpuXInputs ;
    cuDoubleComplex *gpuDOutputs ;
    cuDoubleComplex *gpuYOutputs ;
    double *gpudSE1024 ;
    cuDoubleComplex *gpuOutScalar ;
;

[...]
    struct rdLearningSet * rdLearn;
    struct rdNetwork * rdNet;
[...]
    cudaMalloc(&rdNet, sizeof(rdNetwork));
    cudaMalloc(&rdLearn, sizeof(rdLearningSet));
[...]
    cuDoubleComplex * dummy;
    struct rdLayer rdlSource, * rdldummy;
[...]
    //rdLayer *rLayer;
    cudaMalloc(&rdldummy, sizeof(rdLayer)*rSes.rNet->LayerQty);
    cudaMemcpy( &rdNet->rLayer, &rdldummy, sizeof(rdLayer*), cudaMemcpyHostToDevice);
    for (int L=1; L<rSes.rNet->LayerQty; L++)
            // construct layer to be copied
            rdlSource.NeuronQty=rSes.rNet->rLayer[L].iNeuronQty 
            rdlSource.DendriteQty=rSes.rNet->rLayer[L].iDendriteQty 
            cudaMalloc( &rdlSource.gpuWeights, sizeof(cuDoubleComplex) * (rSes.rNet->rLayer[L].DendriteQty+1) * (rSes.rNet->rLayer[L].NeuronQty+1) ) 
                    mCheckCudaWorked
            cudaMalloc( &rdlSource.gpuZOutputs, sizeof(cuDoubleComplex) * (rSes.rNet->rLayer[L].DendriteQty+1) * (rSes.rNet->rLayer[L].NeuronQty+1) ) 
                    mCheckCudaWorked
            cudaMalloc( &rdlSource.gpuDeltas, sizeof(cuDoubleComplex) * (rSes.rNet->rLayer[L].iDendriteQty+1) * (rSes.rNet->rLayer[L].iNeuronQty+1) ) 
                    mCheckCudaWorked
            cudaMalloc( &rdlSource.gpuUnWeights, sizeof(cuDoubleComplex) * (rSes.rNet->rLayer[L].iDendriteQty+1) * (rSes.rNet->rLayer[L].iNeuronQty+1) ) 
                    mCheckCudaWorked
            //copy layer sructure to Device mem
            cudaMemcpyToSymbol( "rdNet->rLayer", &rdlSource, sizeof(rdLayer), sizeof(rdLayer) * L, cudaMemcpyHostToDevice );/*! 2D neuron cx weight matrix on GPU */
                    mCheckCudaWorked
    
[...]   
    cudaMalloc(&dummy, sizeof(cuDoubleComplex) * (rSes.rLearn->SampleQty) * (rSes.rLearn->InputQty+1) ); /*! 2D complex input tuples in GPU. */
            cudaMemcpy( &rdLearn->gpuXInputs, &dummy, sizeof(cuDoubleComplex*), cudaMemcpyHostToDevice );
                    cudaMemcpy( &dummy, &rSes.rLearn->gpuXInputs, sizeof(cuDoubleComplex) * (rSes.rLearn->SampleQty) * (rSes.rLearn->InputQty+1), cudaMemcpyHostToDevice); 
                    mCheckCudaWorked        
    cudaMalloc(&dummy, sizeof(cuDoubleComplex) * (rSes.rLearn->SampleQty) * (rSes.rLearn->OutputQty+1) ); /*! 2D desired complex outputs in GPU. */
            cudaMemcpy( &rdLearn->gpuDOutputs, &dummy, sizeof(cuDoubleComplex*), cudaMemcpyHostToDevice );
                    cudaMemcpy( &dummy, &rSes.rLearn->gpuDOutputs, sizeof(cuDoubleComplex) * (rSes.rLearn->SampleQty) * (rSes.rLearn->OutputQty+1), cudaMemcpyHostToDevice); 
                    mCheckCudaWorked
[...]

不幸的是,cudaMemcpyToSymbol 调用返回一个错误,mCheckCudaWorked 宏说是“无效的设备符号”,而最后一个 (cudaMemcpy( &dummy, &rSes.rLearn->gpuDOutputs...) 和倒数第三个 (cudaMemcpy( &dummy, &rSes.rLearn->gpuXInputs...) cudaMemcpy 调用返回“无效参数”。

我不知道如何继续将这些项目复制到设备内存并从内核代码中寻址。 &dummy 和 &rdldummy 正作为指向分配内存等待的设备内存地址的指针返回,我可以将这些指针写入设备内存,但我无法哄骗大部分成员值被复制到指向的位置分配。帮助?

【问题讨论】:

【参考方案1】:

gpuXInputs 这样的字段需要指向已分配有cudaMalloc 的内存,以便它们是指向设备内存的有效指针。

通常,您需要数据结构的主机版本,您的分配使用malloc 等,然后是设备上这些数据结构的镜像,这些数据结构已通过cudaMalloc 分配。这些数据结构中的任何指针都需要指向正确的内存类型——你不能“混合和匹配”。

【讨论】:

这就是我正在尝试的;我 cudaMalloc 为 rdLearningSet 结构分配了足够的设备内存,并将指向该结构的指针存储在 rdLEarn 中。然后我 cudaMalloc 有足够的设备内存来保存这么多组输入坐标,并将指向该坐标的指针存储在设备内存位置 rdLrean->gpuXInputs 中。这似乎工作正常。但是,当我尝试将该坐标集块复制到存储为 rdLearn->gpuXInputs 的指针的目的地时,不行! rdlSource 是我构建复制结构的地方。我看不出我在哪里混合了结构中的指针类型,你能指出来吗? 仅从这些代码片段进行调试并不容易 - 我建议您采取“分而治之”的方法,直到遇到更小的问题 我注意到 CUDA C PDF 中提供的示例使用 cudaMalloc ((void**)&varname, ... 但是 cudaMemcpy(varname, ... 在复制时使用。删除地址运算符在上面代码的问题行中,让我复制值的数组。奇怪的是,奇异值仍然可以通过 & 来验证地来回复制。

以上是关于如何将嵌套结构的成员复制到 CUDA 设备的内存空间?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用推力和 CUDA 流将内存从主机异步复制到设备

Cuda - 从设备全局内存复制到纹理内存

CUDA中常量内存的动态分配

分配给设备内存的 CUDA 全局(如 C 语言)动态数组

将主机内存复制到 cuda __device__ 变量

如何将结构传递到 CUDA 设备?