2013-11-21 3 views
1

저는 CUDA 프로그래밍에 익숙하지 만 약간의 문제가 있습니다. 나는 interthread 통신이 필요한 프로그램을 작성하려고했습니다. 내가 찾은 가능한 모든 방법으로 시도했으나 여전히 작동하지 않습니다. 너는 무엇을 생각하니, 나는 무엇을 놓치고 있는가?CUDA 스레드 간 통신

아래의 코드 스 니펫은 제 전체 프로그램입니다. 매우 동일한 블록에서 2 개의 스레드를 시작합니다. 그들은 하나의 입력과 하나의 출력 배열과 다른 전역 변수를 통해 통신합니다. 값 0은 변수가 비어있어 쓰기가 가능함을 의미합니다. 기본적으로 첫 번째 요소는 입력에서 요소를 읽고 두 번째 요소로 전달하여 출력 배열에 씁니다. 나중에는 파이프 (빈) 0, 그것의 첫 번째 요소를두고있다, 그러나, A와 B

#include <cuda.h> 
#include <cuda_runtime.h> 

#include <stdio.h> 

#define N 1 

__global__ void link(int *in, int *out, int *pipe){ 
    int id = threadIdx.y*blockDim.x + threadIdx.x; //compute index  

    if(id == 0){  //writer thread 

     for(int index = 0;index<N;){     
      if(pipe[0]==0){    
       atomicExch(pipe, in[index++]);    
      }   
     } 
    } 
    else if(id == 1){ // reader thread  

     for(int index=0;index<N;) { 
      if(pipe[0]!=0){ 
       out[index++] = atomicExch(pipe, 0); //read and make it empty  
      }   
     }   
    } 
} 

int main(){ 
    int input[] = {8,7}; 
    int *dev_input; 
    int *dev_output; 
    int *dev_pipe; 
    int *output = (int*) malloc (N*sizeof(int)); 

    cudaMalloc((void**) &dev_input, N*sizeof(int)); 
    cudaMalloc((void**) &dev_output, N*sizeof(int)); 
    cudaMalloc((void**) &dev_pipe, 1*sizeof(int)); 
    cudaMemset(dev_pipe, 0, 1); 
    cudaMemcpy(dev_input, &input[0], N*sizeof(int), cudaMemcpyHostToDevice); 

    link<<<1, 2>>>(dev_input, dev_output, dev_pipe); 

    cudaMemcpy(output, dev_output, N*sizeof(int), cudaMemcpyDeviceToHost); 

    printf("[%d", output[0]); 
    for(int i = 1;i<N;i++) 
     printf(", %d", output[i]); 
    printf("]\n"); 
    int d = 0; 
    scanf("\n", &d); 

} 

독자가 나타나면 사이에 더 많은 스레드와 파이프 라인, 있어야 작가 수 없습니다 변경 사항을보고 프로그램이 교착 상태가됩니다. __threadfence 및 __syncthreads를 추가하려고 시도했지만 도움이되지 않았습니다. 또한 휘발성 공유 메모리를 시도했지만 작동하지 않았습니다. 가능하다면 도와주세요. 잘 모르겠다. 무엇이 잘못되었는지.

+0

[this] (http://pastebin.com/mSAZm86S)를 시도하십시오. 또한 항상 [여기]에서 언급 한 오류 검사를 수행하는 것이 좋습니다 (http://stackoverflow.com/questions/14038589/what-is-the-canonical-way-to-check-for-errors-using-the-cuda -runtime-api). –

+0

고마워요, 이걸 시험해 볼게요. 첫 번째 스레드가 __syncthread()에 도달하면 모든 데이터를 두 번째 스레드로 전달하지 않겠습니까? 그러나 두 번째는 __syncthreads()가 호출되기 전에 그 중 하나를 취하지 않으므로 다시 교착 상태가 될 수 있습니다. 아니면 내가 다시 잘못 생각하고 있니? – user3017074

+0

'__syncthread()'는 장벽과 같습니다. 블록의 모든 스레드가 거기에 도달 한 다음 추가 실행을 계속합니다. 아래에 게시 된 답변은 몇 가지 실수를 지적하므로 (내부적으로 증가하지 마십시오. 즉, [index ++]에서). cuda를 계속 사용하려면 스레드, 블록 및 그리드 개념을 올바르게 이해해야합니다. 또 하나의 오류가 지적됩니다. 'cudaMemset (dev_pipe, 0, 1);''cudaMemset (dev_pipe, 0, 1 * sizeof (int)) '이어야합니다. 이것을 고치고 위에 붙여진 코드를 사용하면 효과가 있습니다. 그리고 가장 중요한 오류 검사를 잊지 마세요. –

답변

1

주의 : CUDA 스레드는 POSIX 스레드과 많이 다릅니다. 단일 명령 다중 스레드 패러다임 (SIMT, this interesting discussion 참조)에 따라 작동합니다. 각 시계 틱에서 모든 스레드 (단일 '랩')는 동일한 (저수준) 명령을 실행합니다. 독자 스레드가 NOP의를 수행 한 후, 두 번째 스레드가 첫 번째가 NOP의를 수행하는 동안 실행하는 동안 코드에서

는, 작가 스레드가 실행됩니다 있지만 대규모의 혜택 않을 것이다, 그래서 그들은 동시에 실행되지 않습니다 GPU의 병렬 구조

어쨌든, 질문, 당신의 for 루프 답변을

for(int index=0;index<N;) 

인덱스를 증가하지 않는다; 그래서 그들은 무한 루프입니다.

for(int index=0;index<N;index++) 

동일한 블록 내의 모든 스레드에 공통적 인 공유 메모리는 스레드 간 통신을위한 전역 메모리보다 훨씬 빠릅니다.

+0

저에게 대답 해 주셔서 감사합니다! 그래서 당신이 말하기를, 내가 문제를 해결하더라도, 그것은 무섭게 효과가 없을 것입니까? 그렇다면 GPU에서 이렇게하는 것이 좋지 않습니까? – user3017074

+0

나는 두려워. GPU는 많은 독립적 인 데이터 청크에서 동일한 작업을 수행하는 많은 스레드가있는 데이터 병렬 작업을 수행하도록 설계되었습니다. 그것은 Xeon Phi에서 작동 할 수 있습니다.그러나 이러한 가속기는 낮은 클록 주파수에서 작동하므로 성능을 얻기 위해 멀티 스레딩을 최적으로 사용해야합니다. – damienfrancois

+0

CUDA에서 스레드 간 통신의 경우 일반적으로 공유 메모리를 사용해야합니다. Atomics는 블록 간 통신에 가장 적합합니다. – ArchaeaSoftware