2011-11-30 52 views
1

我有一個指針,它是在設備中動態分配的,那麼我如何將它從設備複製到主機。將設備中分配的數據從設備複製到主機

#include <stdio.h> 

#define cudaSafeCall(call){ \ 
    cudaError err = call;  \ 
    if(cudaSuccess != err){  \ 
    fprintf(stderr, "%s(%i) : %s.\n", __FILE__, __LINE__, cudaGetErrorString(err)); \ 
    exit(EXIT_FAILURE);  \ 
}} 
#define cudaCheckErr(errorMessage) { \ 
    cudaError_t err = cudaGetLastError(); \ 
    if(cudaSuccess != err){    \ 
    fprintf(stderr, "%s(%i) : %s : (code %d) %s.\n", __FILE__, __LINE__, errorMessage, err, cudaGetErrorString(err)); \ 
    exit(EXIT_FAILURE);     \`` 
}} 

struct num{ 
int *a; 
int b; 
}; 

__device__ struct num *gun; 
int main() 
{ 
    int i; 
    char c[100]; 
    struct num *dun,*cun; 
    cudaSafeCall(cudaSetDevice(1)); 
    cun=(struct num*)malloc(10*sizeof(struct num)); 
    cudaSafeCall(cudaMalloc(&dun,10*sizeof(struct num))); 
    cudaSafeCall(cudaMemcpyToSymbol(gun,&dun,sizeof(struct num*))); 
    __global__ void kernel(); 
    kernel<<<1,10>>>(); 
    cudaSafeCall(cudaDeviceSynchronize()); 
    cudaCheckErr(c); 
    cudaSafeCall(cudaMemcpyFromSymbol(&dun,gun,sizeof(struct num*))); 
    cudaSafeCall(cudaMemcpy(cun,dun,10*sizeof(struct num),cudaMemcpyDeviceToHost)); 
    for(i=0;i<10;i++) cudaSafeCall(cudaMalloc(&csu[i].a,10*sizeof(int))); 
    cudaSafeCall(cudaGetSymbolAddress((void**)csu[0].a,(void**)gun[0].a)); 
    for(i=0;i<10;i++) cun[i].a=(int*)malloc(10*sizeof(int)); 
    for(i=0;i<10;i++) cudaSafeCall(cudaMemcpy(cun[i].a,dun[i].a,10*sizeof(int),cudaMemcpyDeviceToHost)); 
    printf("%d ",cun[8].b); 
    printf("%d ",cun[8].a[8]); 
    cudaSafeCall(cudaFree(dun)); 
    free(cun); 
} 

__global__ void kernel() 
{ 
    int i; 
    int tid=threadIdx.x; 
    gun[tid].b=tid; 
    gun[tid].a=(int*)malloc(10*sizeof(int));/*this is dynamically allocated in device.*/ 
    for(i=0;i<10;i++) 
    gun[tid].a[i]=tid+i; 
} 

在這個程序中,它總是在

cudaSafeCall(cudaMemcpy(cun[i].a,dun[i].a,10*sizeof(int),cudaMemcpyDeviceToHost)) 

爲什麼一個 「分段錯誤」?我能做些什麼來將這些數據從設備複製到主機上?

+0

動態內存分配僅支持最新的cuda設備(自2.0版本以來)。如果你想編譯這個體系結構,添加這個nvcc參數'-arch = sm_20'或'-arch = sm_21'。 – Yappie

+0

是的,我已經使用了這個參數,我的cun [8] .b是正確的。只是不知道如何傳遞結構中的元素a。 – helena

回答

0

您遇到的問題是您嘗試在主機代碼中使用設備指針間接尋址,這是非法的。在您的例子

cudaMemcpy(cun[i].a,dun[i].a,10*sizeof(int),cudaMemcpyDeviceToHost) 

dun包含設備指針,因此dun[i].a意味着dun[i]間接讀的a值。這不是有效的主機內存地址,因此會導致seg故障。你當你這樣做實際上已經複製的指針,你的內核分配的堆內存這樣的:

cudaMemcpy(cun,dun,10*sizeof(struct num),cudaMemcpyDeviceToHost); 

所以在與

代碼
int ** a_h = (int **)malloc(10 * sizeof(int *)); // to hold heap pointers 
for(i=0;i<10;i++) { 
    a_h[i] = cun[i].a; // save heap pointer 
    cun[i].a=(int*)malloc(10*sizeof(int));     
    cudaMemcpy(cun[i].a,a_h[i],10*sizeo(int),cudaMemcpyDeviceToHost); // copy heap to host 
} 

應該安全地複製你分配回主機堆內存。

+0

這是工作!非常感謝。這個問題困擾了我很長一段時間。並且a_h不是int *,而是int **。我修改了這一行。它工作正常。 – helena

+0

如果這解決了您的問題,請您考慮[接受我的答案](http://meta.stackexchange.com/a/5235/163653)? – talonmies

+0

我想問你更多的問題。如果元素a是一個int ***,如何複製? – helena

相關問題