传递给内核的值变得混乱

时间:2014-04-19 23:57:16

标签: c pointers cuda

我正在尝试初始化设备上的一些结构,但是当它们回来时,它们都是凌乱的。我知道我使用指针的方式有问题,但我似乎无法弄明白。

继承我在主机上的内存分配

body* devBodies;
body** devBodyList;
float* devRandoms;
cudaMalloc((void**)&devBodies, n * sizeof(body));
cudaMalloc((void**)&devBodyList, n * sizeof(body*));
cudaMalloc((void**)&devRandoms, n * 3 * sizeof(float));

继承我的函数调用,其中devRandoms只是一个浮点数列表。

CUDAInitBodies<<<n,1>>>(devBodyList, devBodies, devRandoms);

以及我的方法:

__global__ void CUDAInitBodies(body** devBodyList, body* devBody, float* rand)
{
    int j;
    int tid = blockIdx.x;
    *(devBodyList[tid]) = devBody[tid];
    devBodyList[tid]->id = tid;
    devBodyList[tid]->m = 10;
    for(j = 0; j < 3; j++) 
    {
        devBodyList[tid]->a[j] = 0;
        devBodyList[tid]->v[j] = 0;
        devBodyList[tid]->pos[j] = rand[(tid * 3) + j];
    }   

}

然后我将数据复制回主机:

body* bodies = (body*)malloc(n * sizeof(body));
cudaMemcpy(bodies, devBodies, n * sizeof(body), cudaMemcpyDeviceToHost);

当我打印出我的“身体”的变量时,我明白了:

====BODY[-581043205]====
    M = -42522218781525353518415985938704367616.000000
    V = [-311601248975690312470654313562112.000000, 17269896096570671104.000000, 307939529506715418513587721849804947456.000000]
    X = -19247336126697914498972549714433540096.000000
    Y = 17731266573644159438123340575306416128.000000
    Z = -544771403677696.000000

我已经尝试了不同的方法做了很长一段时间,但似乎没有什么可以做的伎俩

1 个答案:

答案 0 :(得分:1)

您获得垃圾输出的原因是您在内核中的这行代码中取消引用了一个未初始化的指针:

*(devBodyList[tid]) = devBody[tid];

在主机上,您在此处为指针数组分配了存储空间:

cudaMalloc((void**)&devBodyList, n * sizeof(body*));

只为指针数组创建存储空间。它不会将数组中的任何指针设置为指向任何有效的指针。

数组的每个成员都是body结构的指针,使用第一个成员作为示例:

devBodyList[0]

但该指针不会指向任何(有效),除非您使用类似(在设备代码中)的语句对其进行初始化:

devBodyList[0] = &(devBody[0]);

现在我可以使用devBodyList[0]作为指向devBody[0]分配的主体结构的指针。请注意,devBodyList[0]已存储在设备上,因此要初始化它,我必须:

  1. 在使用设备代码之前将其初始化(例如上面的代码行)。
  2. 在主机上初始化它,但设置有效指针,然后使用cudaMemcpy之类的操作将该初始化值复制到已分配的设备存储。
  3. 除非您考虑上述情况,否则当您使用指针时,它将包含垃圾值,并且取消引用它将产生无效访问。您可以通过cuda-memcheck运行代码来查看这些无效访问的证据。您将收到“无效的全局写入...”等消息。

    这是一个完全有效的代码,基于你的作品,不会产生垃圾结果。 (我不是说它特别明智,因为使用devBodyList[x]来引用devBody[x]对我来说似乎没用。)但它是合法代码并且不会产生任何内核错误:

    #include <stdio.h>
    
    struct body {
    int id;
    int m;
    int a[3];
    int v[3];
    float pos[3];
    };
    
    __global__ void CUDAInitBodies(body** devBodyList, body* devBody, float* rand)
    {
        int j;
        int tid = blockIdx.x;
        devBodyList[tid] = &(devBody[tid]);
        *(devBodyList[tid]) = devBody[tid];
        devBodyList[tid]->id = tid;
        devBodyList[tid]->m = 10;
        for(j = 0; j < 3; j++)
        {
            devBodyList[tid]->a[j] = 0;
            devBodyList[tid]->v[j] = 0;
            devBodyList[tid]->pos[j] = rand[(tid * 3) + j];
        }
    
    }
    
    int main(){
      int n = 1;
      body *devBodies;
      body **devBodyList;
      float *devRandoms;
    
      cudaMalloc((void**)&devBodies, n * sizeof(body));
      cudaMalloc((void**)&devBodyList, n * sizeof(body*));
      cudaMalloc((void**)&devRandoms, n * 3 * sizeof(float));
    
      CUDAInitBodies<<<n,1>>>(devBodyList, devBodies, devRandoms);
    
      body* bodies = (body*)malloc(n * sizeof(body));
      cudaMemcpy(bodies, devBodies, n * sizeof(body), cudaMemcpyDeviceToHost);
    
      printf("Body %d\n", bodies[0].id);
      printf("M : %d\n", bodies[0].m);
      printf("V : %d\n", bodies[0].v[0]);
      return 0;
    }