2011-11-30 4 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].aa의 값을 읽어 dun[i]의 간접을 의미, 장치 포인터를 포함합니다. 올바른 호스트 메모리 주소가 아니므로 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가 정수인 경우 복사하는 방법은 무엇입니까? – helena

관련 문제