struct - CUDA:在结构中分配结构数组

标签 struct cuda deep-linking

我有这些结构:

typedef struct neuron
{
float*  weights;
int n_weights;
}Neuron;


typedef struct neurallayer
{
Neuron *neurons;
int    n_neurons;
int    act_function;
}NLayer;

“NLayer”结构可以包含任意数量的“神经元”

我试图以这种方式从主机分配一个带有 5 个“神经元”的“NLayer”结构:
NLayer* nL;
int i;
int tmp=9;
cudaMalloc((void**)&nL,sizeof(NLayer));
cudaMalloc((void**)&nL->neurons,6*sizeof(Neuron));
for(i=0;i<5;i++)
    cudaMemcpy(&nL->neurons[i].n_weights,&tmp,sizeof(int),cudaMemcpyHostToDevice);

...然后我尝试使用该内核修改“nL->neurons[0].n_weights”变量:
__global__ void test(NLayer* n)
           {
              n->neurons[0].n_weights=121;
           }

但是在编译时 nvcc 返回与内核唯一行相关的“警告”:
Warning: Cannot tell what pointer points to, assuming global memory space

当内核完成其工作时,结构开始无法访问。

很可能我在分配过程中做错了什么......有人可以帮助我吗?
非常感谢,对不起我的英语! :)

更新:

感谢 aland,我修改了我的代码来创建这个函数,它应该分配一个结构体“NLayer”的实例:
NLayer* setNLayer(int numNeurons,int weightsPerNeuron,int act_fun)
{
    int i;
    NLayer  h_layer;
    NLayer* d_layer;
    float*  d_weights;

    //SET THE LAYER VARIABLE OF THE HOST NLAYER
    h_layer.act_function=act_fun;
    h_layer.n_neurons=numNeurons;
    //ALLOCATING THE DEVICE NLAYER
    if(cudaMalloc((void**)&d_layer,sizeof(NLayer))!=cudaSuccess)
        puts("ERROR: Unable to allocate the Layer");
    //ALLOCATING THE NEURONS ON THE DEVICE
    if(cudaMalloc((void**)&h_layer.neurons,numNeurons*sizeof(Neuron))!=cudaSuccess)
        puts("ERROR: Unable to allocate the Neurons of the Layer");
    //COPING THE HOST NLAYER ON THE DEVICE
    if(cudaMemcpy(d_layer,&h_layer,sizeof(NLayer),cudaMemcpyHostToDevice)!=cudaSuccess)
                puts("ERROR: Unable to copy the data layer onto the device");

    for(i=0;i<numNeurons;i++)
    {
        //ALLOCATING THE WEIGHTS' ARRAY ON THE DEVICE
        cudaMalloc((void**)&d_weights,weightsPerNeuron*sizeof(float));
        //COPING ITS POINTER AS PART OF THE i-TH NEURONS STRUCT
        if(cudaMemcpy(&d_layer->neurons[i].weights,&d_weights,sizeof(float*),cudaMemcpyHostToDevice)!=cudaSuccess)
                puts("Error: unable to copy weights' pointer to the device");
    }


    //RETURN THE DEVICE POINTER
    return d_layer;
}

我以这种方式从 main 调用该函数(之前声明了内核“测试”):
int main()
{
    NLayer* nL;
    int h_tmp1;
    float h_tmp2;

    nL=setNLayer(10,12,13);
    test<<<1,1>>>(nL);
    if(cudaMemcpy(&h_tmp1,&nL->neurons[0].n_weights,sizeof(float),cudaMemcpyDeviceToHost)!=cudaSuccess);
        puts("ERROR!!");
    printf("RESULT:%d",h_tmp1);

}

当我编译该代码时,编译器向我显示警告,当我执行程序时,它会在屏幕上打印:
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
Error: unable to copy weights' pointer to the device
ERROR!!
RESULT:1

如果我评论内核调用,则不会比较最后一个错误。

我错在哪里?
我不知道该怎么做
谢谢你的帮助!

最佳答案

问题在这里:

cudaMalloc((void**)&nL,sizeof(NLayer));
cudaMalloc((void**)&nL->neurons,6*sizeof(Neuron));

在第一行,nL指向设备上全局内存中的结构。
因此,在第二行第一个参数 cudaMalloc是驻留在 GPU 上的地址,这是未定义的行为(在我的测试系统上,它会导致段错误;但在您的情况下,有一些更微妙的东西)。

做你想做的正确方法是首先在主机内存中创建结构,用数据填充它,然后将其复制到设备,如下所示:
NLayer* nL;
NLayer h_nL;
int i;
int tmp=9;
// Allocate data on device
cudaMalloc((void**)&nL, sizeof(NLayer));
cudaMalloc((void**)&h_nL.neurons, 6*sizeof(Neuron));
// Copy nlayer with pointers to device
cudaMemcpy(nL, &h_nL, sizeof(NLayer), cudaMemcpyHostToDevice);

另外,不要忘记始终检查 CUDA 例程中的任何错误。

更新

在您的代码的第二个版本中:
cudaMemcpy(&d_layer->neurons[i].weights,&d_weights,...) --- 再次,您正在取消引用主机上的设备指针 ( d_layer )。相反,你应该使用
cudaMemcpy(&h_layer.neurons[i].weights,&d_weights,sizeof(float*),cudaMemcpyHostToDevice

给你 h_layer (主机结构),读取其元素( h_layer.neurons ),这是指向设备内存的指针。然后你对其进行一些指针运算( &h_layer.neurons[i].weights )。无需访问设备内存即可计算此地址。

关于struct - CUDA:在结构中分配结构数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11874667/

相关文章:

c - 枚举C中的结构字段

c - 如何处理像这些寄存器这样的结构中的所有字段?

gcc - GCC 中的 OpenMP 4.0 : offload to nVidia GPU

c++ - __global__ 函数的“内联”以避免多重定义错误

CUBLAS 通用矩阵点积

ios - Facebook深度链接不适用于开放图新闻提要故事

python - 有人可以解释 Python 结构解包吗?

c - 具有包含可变大小对象的结构的 Malloc

ios - 与 UIImage 的深度链接

deep-linking - 与 branch.io 上的变量查询的深层链接