2011-01-16 3 views
0

전역 메모리의 한 배열을 CUDA 스레드 (호스트가 아닌)가 전역 메모리의 다른 배열에 복사해야합니다. 다음과 같이CUDA 스레드로 전역 메모리 복사

내 코드는 다음과 같습니다

__global__ void copy_kernel(int *g_data1, int *g_data2, int n) 
{ 
    int idx = blockIdx.x * blockDim.x + threadIdx.x; 
    int start, end; 
    start = some_func(idx); 
    end = another_func(idx); 
    unsigned int i; 
    for (i = start; i < end; i++) { 
     g_data2[i] = g_data1[idx]; 
    } 
} 

이 때문에 일부 IDX 매우 비효율적이다, [시작, 종료] 지역 스레드의 문제가 너무 많은 복사 명령을 만드는 매우 크다. 효율적으로 구현할 수있는 방법이 있습니까?

청이 사용

답변

0

시도 감사 :

CUresult cuMemcpyDtoD(
    CUdeviceptr dst, 
    CUdeviceptr src, 
    unsigned int bytes 
) 

UPDATE :

당신 맞아요 : http://forums.nvidia.com/index.php?showtopic=88745

이 할 수있는 더 효율적인 방법이 없습니다 이것은 CUDA의 설계가 당신이 오직 sm 커널의 모든 데이터 양.

+0

qba의 대답과 같은 문제 :이 함수는 \ _ \ _ global \ _ \ _ 함수가 아닌 호스트 함수에서만 호출 할 수 있습니다. – Zheng

+1

그래서 nvidia 포럼 스레드를 기반으로하면 장치가 네이티브로 작동 할 수있는 가장 큰 데이터 형식으로 스레드를 작동시키는 것이 가장 좋습니다 (각 반복이 하나의 복사 명령으로 이루어짐). 최적의 수 의 스레드는 장치의 메모리 아키텍처에 의존하기 때문에 경험적으로 결정되어야합니다. – user57368

1

당신이 작성한 방식대로 각 스레드가 '끝'청크에 전체 '시작'을 쓰려고합니다. 실제로 은 실제로 비효율적입니다.

이와 같이해야합니다.

___shared___ unsigned sm_start[BLOCK_SIZE]; 
___shared___ unsigned sm_end[BLOCK_SIZE]; 
sm_start[threadIdx.x] = start; 
sm_end[threadIdx.y] = end; 
__syncthreads(); 
for (int n = 0; n < blockdDim.x; n++) { 
g_data2 += sm_start[n]; 
unsigned lim = sm_end[n] - sm_start[n]; 
    for (int i = threadIdx.x; i < lim; i += blockDim.x) { 
     g_data2[i] = g_data1[idx]; 
    } 
}