我有一个在设备中动态分配的指针,那么我如何将它从设备复制到主机。
#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))
为什么?如何将数据从设备复制到主机?
您遇到的问题是您试图在主机代码中间接使用设备指针,这是非法的。在您的示例
中cudaMemcpy(cun[i].a,dun[i].a,10*sizeof(int),cudaMemcpyDeviceToHost)
dun
包含一个设备指针,因此dun[i].a
暗示dun[i]
间接读取a
的值。这不是一个有效的主机内存地址,因此会导致段错误。当您执行以下操作时,实际上已经将指针复制到内核分配的堆内存中:
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
}
应该安全地将您分配的堆内存复制回主机。