2014-01-06 4 views
1
__global__ void gpu_Heat (float *h, float *g, float * sum, int N) { 
     int nbx, bx, nby, by; 
     float diff = 0.0; 
     nbx = (N-2)/blockDim.x; 
     bx = nbx/gridDim.x; 
     nby = (N-2)/blockDim.y; 
     by = nby/gridDim.y;  
     unsigned int ii = blockIdx.x*blockDim.x+threadIdx.x; 
     unsigned int jj = blockIdx.y*blockDim.y+threadIdx.y; 
     unsigned int jid = (ii)*(N-2)+(jj); 
     for (int i=1+ii*bx; i<=min((ii+1)*bx, N-2); i++) 
        for (int j=1+jj*by; j<=min((jj+1)*by, N-2); j++) { 
        g[i*N+j]= 0.25 * (h[ i*N + (j-1)]+ 
           h[ i*N +(j+1) ]+ 
           h[ (i-1)*N + j]+ 
           h[ (i+1)*N + j]); 
         diff = g[i*N+j] - h[i*N+j]; 
         sum[(i-1)*(N-2)+(j-1)] = diff * diff; 
       } 
     __syncthreads(); 
     for(unsigned int s=((N-2)*(N-2))/2; s>0; s>>=1){  
      if(jid<s){ 
       sum[jid]+=sum[jid+s];   
      } 
      __syncthreads();  

     } 
    } 

그래서 내 문제는 sum [0 입력이 동일하고 내가 뭘 잘못하고 있는지 모릅니다. CPU에서 같은 합계 행렬이 줄어들면 실행은 괜찮지 만 GPU가 병렬 감소하면 문제가 발생합니다.CUDA : 각 실행마다 [0]의 값이 변경됨

dim3 Grid = (16,16); 
    dim3 Block = (16,16); 
    gpu_Heat<<<Grid,Block>>>(dev_u, dev_uhelp, dev_sum, np); 
    cudaThreadSynchronize();      // wait for all threads to complete 
    cudaErrorCheck(cudaMemcpy(param.u,dev_u,np*np*sizeof(float),cudaMemcpyDeviceToHost)); 
    cudaErrorCheck(cudaMemcpy(param.uhelp,dev_uhelp,np*np*sizeof(float),cudaMemcpyDeviceToHost)); 
    cudaErrorCheck(cudaMemcpy(sum,dev_sum,sum_size*sizeof(float),cudaMemcpyDeviceToHost)); 

여기서 내가 사용하고있는 테스트의 코드에 의해 계산되는 블록 및 그리드 매개 변수를 명시 적으로 보여줍니다. 답변 해 주셔서 감사합니다.

+0

커널을 초기화하는 데 사용하는 격자 및 블록 매개 변수와 함께 커널의 함수 호출을 게시 할 수 있습니까? 실패하는 이유를 파악하는 데 도움이됩니다. – Bharat

+0

위와 같지만 모든 호출이 변경되는 경우, 즉, 코드에서 경쟁 조건을 의미합니다! –

+0

@Bharat 귀하가 요청한 부분을 추가했습니다. –

답변

2

여러 블록으로 GPU 커널을 실행하고 있습니다. 한 블록의 스레드가 여전히 for 루프의 sum을 계산하고 있지만 다른 블록은 두 번째 루프의 병렬 감소를 수행 중일 수 있습니다. 이 두 개의 for 루프에는 데이터 종속성이 있습니다. 스트리밍 멀티 프로세서를 통한 블록 예약은 장면 뒤에서 발생하고 실행마다 다를 수 있으므로 매번 다른 결과가 나옵니다. __syncthreads(); ~ for 루프는 블록 내부의 스레드를 동기화하지만 호스트로 돌아가서 다른 커널을 실행하지 않는 한 여러 블록 간의 동기화를위한 메커니즘이나 지침이 없습니다.

for 루프를 분리해도 결과가 여러 블록에서 줄어들고 블록의 일정이 결정적이지 않기 때문에 결과가 잘못 될 수 있습니다.

+0

설명해 주셔서 감사합니다. 나는 syncthreads()가 cudaDeviceSynchronize()와 같이 커널 스레드를 모두 동기화한다는 잘못된 가정하에있었습니다. –

관련 문제