2012-02-21 4 views
1

나는이 코드를 가지고 있지만 가끔은 작동하지 않는다. (printf ("ERR : % d \ n", id)). CUDA 4.1에서 작동하며 GTS450은 컴퓨팅 기능 2.1입니다. ,] CUDA 코드가 작동하지 않습니다. 이유가 무엇입니까?

당신이 그것을 실행하려면

는, 어쩌면 당신은 몇 번 실행해야합니다

더 높은 목적이 나던 코드는, 스피은 그것의 작동하지 않는, 내 마음이 말해 있기 때문에, 그 권리 이유를 찾기 위해 노력 "오류"가 나타나거나 격자 크기를 변경하면!

PS :

int id = d_mans[man].m_id; 
    if(id == -1) //If It never works with this "id", its creating new 
    { 
     id = atomicAdd(&d_last_ids, 2); 

     d_ids[id] = 10; //set to non-zero 
     d_mans[man].m_id = id; //save new id for next time 

     printf("ADD:%d\n", id); 
    } 

    if(d_ids[id]==0) 
     printf("ERR:%d\n", id); //THIS SHOULD NEVER HAPPEN, BUT BECOMES !!! 

여전히 일부 블록은 .m_id [사람] d_mans에 쓴 경우 경쟁 조건을 포함하지만, 이 코드 때문에 here you can download exe file for win64 - you need to have cuda4.1 driver이 일 것으로 보인다

class MAN 
{ 
public: 
    int m_id; 
    int m_use; 

    __device__ 
    MAN() 
    { 
     m_id = -1; 
     m_use = 0; 
    } 
}; 

__device__ int* d_ids = NULL; 
__device__ int d_last_ids = 0; 

__device__ MAN* d_mans = NULL; 


__global__ void init() 
{ 
    d_mans = new MAN[500]; //note: 500 is more than enough! 
    d_ids = new int[500]; 

    for(int i=0; i < 500; i++) 
     d_ids[i] = 0; 
} 


__device__ int getMAN() //every block get unique number, so at one moment all running blocks has different id 
{ 
    while(true) 
    { 
     for(int i=0; i < 500; i++) 
      if(atomicCAS(&(d_mans[i].m_use), 0, 1)==0) 
       return i; 
    } 
} 
__device__ void returnMAN(int id) 
{ 
    int s = atomicExch(&(d_mans[id].m_use), 0); 
} 



__global__ void testIt() 
{ 
    if(threadIdx.x==0) 
    { 
     int man = getMAN(); 

     int id = d_mans[man].m_id; 
     if(id == -1) //If It never works with this "id", its creating new 
     { 
      id = atomicAdd(&d_last_ids, 2); 

      d_ids[id] = 10; //set to non-zero 
      d_mans[man].m_id = id; //save new id for next time 

      printf("ADD:%d\n", id); 
     } 

     if(d_ids[id]==0) 
      printf("ERR:%d\n", id); //THIS SHOULD NEVER HAPPEN, BUT BECOMES !!! 

     returnMAN(man); 
    } 
} 



int main() 
{ 
    init<<<1, 1>>>(); 
    printf("init() err: %d\n", cudaDeviceSynchronize()); 

    testIt<<<20000, 512>>>(); 
    printf("testIt() err: %d\n", cudaDeviceSynchronize()); 

    getchar(); 
    return 0; 
} 
+1

'init' 커널 호출이 실패했다는 말입니까? 오류 메시지는 무엇입니까? – talonmies

+0

아니요 CUDA 오류가 없습니다. 문제는 프로그램이 "printf ("ERR : % d \ n ", id);" 라인,하지만 이것은 결코 일어날 수 없다! – Milan

+0

달성하려는 목표는 무엇입니까? 내가 writen 한 것처럼 – harrism

답변

0

나는이 변경되었습니다

심지어 __threadfence()가 필요하지 않습니다.

1

은하지 않은 d_ids [id]에 썼습니다. 아마도 컴파일러는 "0이 아닌 값으로 설정"하고 "다음에 사용할 새 ID 저장"명령이나 캐시를 업데이트하는 경우가 있습니다.

실제로 할당 자에게 문제가 있습니다. 마지막으로 사용 된 '사람'의 색인을 찾는 것이 좋습니다.

__device__ int* d_ids = NULL; 

이에 :

__device__ volatile int* d_ids = NULL; 

을 그리고 작품을 좋아!

+0

그 문제는 변수가 캐시에 있다고 생각하기 때문에 시간에 업데이트하지 않습니다. 일부 "블록"은 오류를 기록하기 때문에 일부 오류가 나타나지 않습니다 (캐쉬 업데이트 전역 메모리). 그러나 문제는 어떻게 해결할 수 있는가? – Milan

+0

아마 솔루션 : 나는 약간의 "무료"사람을 발견하면 아닌 값 – Milan

+0

을 포함 나던 ID를 내 솔루션을 시도하고 오류없이 작동하는지, 나는 그것을 확인할 수 있도록 getMAN() 코드를 변경할 수 있지만 여전히 수 있습니다 캐시가 블록이 완료되면 즉시 전역 메모리를 갱신하지 않는 이유는 없습니다. 왜 지연 되었습니까 ?? – Milan

관련 문제