2014-02-10 2 views
1
for (int ir = 0; ir < nr; ir++) 
{ 
    td = 0; 
    md = 0; 
    for (int i = 0; i < nc; i++) 
    { 
     d[ir * nc + i] = func(nc, cH, vH, ir, i); 
     td   += dist[ir * nc + i]; 
    } 

    md  = td/nc; 
    mdi[ir] = md; 
} 

나는 위의 코드를 가지고 있으며 GPU로 이식하려고합니다. 그리고 나는이 코드를 시도했다.Cuda로 이식하기

//get thread IDs 
const int ir = blockDim.y * blockIdx.y + threadIdx.y; //nR 
const int i = blockDim.x * blockIdx.x + threadIdx.x; //nC 
int  td = 0; 
int  md = 0; 

d[ir * nc + i] = func(nc, c, v, ir, i); //out 
td   += d[ir * nc + i]; 

md = td/nc; 
if (i % nc == 0) 
{ 
    mdi[ir] = md;//out 
    td  = 0; 
    md  = 0; 
} 

그러나 결과가 일치하지 않습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까? 어떤 충고?

+7

완전한 두 경우에 대한 lable 코드. 기대하고있는 결과와 실제로 얻은 결과를 나타냅니다. –

+1

하나의 문제점은'td + ='입니다. 직렬 버전에서는 내부 루프 내에서이를 업데이트합니다. 즉, 루프의 반복 사이에 종속성이 있음을 의미합니다. 이러한 종속성은 병렬 처리 할 때 리팩터링되어야합니다. 당신이 시도한 것처럼 보이지만, 스레드 로컬'td' 변수를 만든 다음 그 변수에 한 번만 추가하면됩니다. 즉, 변수는 각 스레드에 의해 업데이트되지 않습니다. 이 특별한 문제에 대한 한가지 옵션은'td' 변수를 전역으로 만들고 그것을'atomicAdd()'로 업데이트하는 것입니다. 그것은 최적이 아닐 수도 있습니다. –

+1

포팅하는 알고리즘의 유형을 설명하기 위해 제목과 본문에 뭔가를 추가 할 수 있습니까? 그 이유는 SO에 대한 질문이 OP보다 다른 사람들에게 잠재적으로 도움이되기 때문입니다. OP에게만 이익이되는 질문은 너무 현지화되어 있습니다. 질문의 의미는 문제가있는 사람이 같은 유형의 알고리즘을 포팅해도 검색에서 찾을 수 없기 때문에 질문에만 도움이됩니다. –

답변

1

번째 코드는 완전하지 않다 : I 는 C와V의 정의를 볼 수 없으며 두 번째 코드는 I DIST 배열을 볼 수 없다.

큰 문제가 있음을 알면 실수가 없다고 가정합니다. 2 차원 행렬에 func (...)을 채우고있는 것 같습니다. 괜찮습니다.

1D 벡터를 채울 때 문제가 발생합니다. md 이것은 공유 변수가 아니므로 배열에 쓰여진 값은 쓰레드에 의해 계산 된 값과 일치합니다.

당신의 문제는 당신이해야 충분히 작은 경우 TD 블록에서 공유 값 : How to share a common value between threads in a given block?

하면 쓰기 전에 블록의 스레드를 동기화하기 위해 기억 CUDA: synchronizing threads

NC 를하는 경우이 블록 크기보다 큰 경우 매트릭스의 모든 행에 대해 줄이기를 사용해야합니다. http://developer.download.nvidia.com/compute/cuda/1.1-Beta/x86_website/projects/reduction/doc/reduction.pdf