2011-11-30 56 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

相关问题