2014-04-19 41 views
0

我试图初始化设备上的一些结构,但是当它们回来时,它们都是混乱的。我知道我使用指针的方式有问题,但我似乎无法解决这个问题。传入内核的值越来越混乱

继承人的主机

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 

我试过differen牛逼这样做了很长一段时间的办法,但似乎没有任何可以做的伎俩

+0

看起来你并没有初始化'devBodyList'指针数组,我可以看到你已经为它分配了存储空间,但是我没有看到在你设置每个指针指向某些东西的地方(比如一个'body'结构体),试着在你的内核开头附近添加这行:'devBodyList [tid] =&(devBody [tid]);'值得注意的是它将通过双指针('**')引用的数据传递给或fr一个内核有点困难。在“CUDA 2D阵列”上搜索。如果你用'cuda-memcheck'运行你的代码,我想你可能会发现由于单位化指针引起的一些越界访问。 –

+0

是的,我初始化了这个变量。我只是没有把它放在我的帖子中。我编辑我的帖子更清晰。 –

+0

你在哪里初始化数组中的每个指针?我知道你已经为设备上的指针数组分配了存储空间,但是在你可以在你的内核中取消引用其中的一个指针之前,它必须指向一些有效的(在设备上)。你有没有尝试用'cuda-memcheck'运行你的代码? –

回答

1

您得到垃圾输出的原因是,你在这行代码在内核访问一个未初始化的指针:

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

在主机上,您为指针数组这里分配的存储:

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

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

阵列的每个成员是指针body结构,使用第一构件作为一个例子:

devBodyList[0] 

但是,指针不指向任何东西(有效的),除非你初始化它,与像一个声明(在设备代码):

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

现在我可以使用devBodyList[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; 
} 
+0

我很欣赏深入的解释。我要回到基础来尝试获得这个。你能帮我看看吗? http://stackoverflow.com/questions/23177802/cuda-headache-im-just-not-getting-it –