2014-04-19 39 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 –