【问题标题】:values passed into kernel getting messy传递给内核的值变得混乱
【发布时间】:2014-06-04 07:26:37
【问题描述】:

我正在尝试在设备上初始化一些结构,但是当它们返回时,它们都变得一团糟。我知道我使用指针的方式有问题,但我似乎无法弄清楚。

这是我在主机上的内存分配

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

我已经尝试了很长一段时间的不同方法,但似乎没有任何效果

【问题讨论】:

  • 您似乎没有初始化devBodyListpointer 数组。我可以看到您已经为它分配了存储空间,但我没有看到您将每个指针设置为指向某个东西的位置(例如 body 结构)。尝试在内核开头附近添加这一行:devBodyList[tid] = &amp;(devBody[tid]); 值得注意的是,将双指针 (**) 引用的数据传入或传出内核有些困难。搜索“CUDA 2D 阵列”。如果您使用 cuda-memcheck 运行代码,我想您可能会发现由于未初始化的指针而导致的一些越界访问。
  • 是的,我初始化了那个变量。我只是没有把它放在我的帖子中。我编辑了我的帖子以更清楚。
  • 你在哪里初始化数组中的每个指针?我知道您已经为设备上的一组指针分配了存储空间,但是在您可以在内核中取消引用其中一个指针之前,它必须指向有效的东西(在设备上)。您是否尝试使用 cuda-memcheck 运行您的代码?
  • *(devBodyList[tid]) = devBody[tid];这发生在我的内核内部
  • 那是解除引用 devBodyList[tid]。但是devBodyList[tid] 在哪里设置为合适的值?您似乎在为基本的 C 指针概念而苦苦挣扎,在这里。我向您保证,根据您在此处显示的内容,您正在取消引用内核中的无效指针。如果您不相信我,请尝试使用cuda-memcheck 运行您的代码。将导致无效的全局写入错误是由于 devBodyList[tid] 未设置为正确的值。

标签: c pointers cuda


【解决方案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 之类的操作将该初始化值复制到分配的设备存储中。

除非您考虑到上述情况,否则当您使用指针时,它将包含一个垃圾值,并且取消引用它会产生无效访问。您可以通过使用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;
}

【讨论】:

猜你喜欢
  • 2011-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 2019-07-15
  • 2021-12-31
相关资源
最近更新 更多