2011-07-31 6 views
41

OpenCL에서는 작업 그룹의 스레드를 동기화하기 위해 barrier() 함수를 사용할 수 있습니다. 나는 (일반적으로) 그들이 무엇을 위해 무엇을 언제 사용하는지 이해한다. 또한 작업 그룹의 모든 스레드가 장벽을 넘어야한다는 사실을 알고 있습니다. 그렇지 않으면 문제가 있습니다. 그러나 지금까지 장벽을 사용하려 할 때마다 내 비디오 드라이버가 손상되거나 잘못된 메모리에 액세스하는 것과 관련된 오류 메시지가 나타나는 것으로 보입니다. 지금까지 2 개의 다른 비디오 카드에서 이것을 보았습니다 (1 ATI, 1 NVIDIA).OpenCL의 장애물

그래서, 내 질문은 :

  1. 어떤 생각이 왜 이런 일이까요?
  2. barrier(CLK_LOCAL_MEM_FENCE)barrier(CLK_GLOBAL_MEM_FENCE)의 차이점은 무엇입니까? 나는 그 문서를 읽었지 만 그것은 나에게 명확하지 않았다.
  3. barrier(CLK_LOCAL_MEM_FENCE)barrier(CLK_GLOBAL_MEM_FENCE)을 사용하는 경우에 대한 일반적인 규칙이 있습니까?
  4. 잘못된 매개 변수 유형으로 barrier()을 호출하면 오류가 발생할 수 있습니까?

답변

30

앞서 언급 한 것처럼 장벽은 같은 작업 그룹의 스레드 만 동기화 할 수 있습니다. 커널의 여러 작업 그룹을 동기화 할 수있는 방법은 없습니다.

이제

귀하의 질문에 대답 할 수는 사양 중 하나를 나에게 분명 아니었지만, 섹션 6.11.9 대답 포함하는 나에게 보인다

CLK_LOCAL_MEM_FENCE - 장벽 기능 것 중 하나 플러시 어떤 변수를 로컬 메모리에 저장하거나 메모리 울타리를 대기열에 넣고 로컬 메모리에 대한 올바른 메모리 작업 순서를 보장합니다.

CLK_GLOBAL_MEM_FENCE - barrier 함수는 메모리 펜스 을 대기열에 두어 전역 메모리에 대한 올바른 메모리 순서를 지정합니다. 작업 항목 (예 : 버퍼 또는 이미지 메모리 개체에 쓰고 업데이트 된 데이터를 읽는 경우)이 유용 할 수 있습니다. 쓰고 __global 메모리 공간을 읽는데 때 쓰고 __local 메모리 공간에 읽기, CLK_GLOBAL_MEM_FENCE 때

그래서, 내 이해, 당신은 CLK_LOCAL_MEM_FENCE를 사용해야합니다.

이 테스트가 느리지 만 대부분의 경우 장벽이 필요할 때 어떤 메모리 공간이 영향을 받는지 의심 스럽지만 단순히 두 가지를 조합하여 사용합니다.

이렇게하면 그룹의 모든 스레드가 장벽을 통과하지만 확신 할 수있는 한 순서 쓰기 문제를 읽는 메모리가 없어야합니다.

는 도움이되기를 바랍니다.

+3

은 분명히 CLK_GLOBAL_MEM_FENCE는 CLK_LOCAL_MEM_FENCE보다 자주 느립니다. 이유는 블록 내의 모든 스레드가 메모리 액세스가 완료 될 때까지 기다려야하기 때문입니다. 그리고 전역 메모리 액세스가 완료되기를 기다리는 것은 로컬 메모리 액세스보다 훨씬 비쌉니다. 물론 이것은 항상 사실이 아닙니다. 액세스 패턴 (Fermi에는 이제 캐시가 있습니다. 이는 공유 메모리와 비슷한 대기 시간을 갖는 L1에서 전역 액세스를 캐시 할 수 있음을 의미합니다), 커널의 글로벌/로컬 메모리 액세스 수 , 점유, 은행 충돌, coalescences 등. – Zk1001

31

여기에 예전 스레드 복원. 장벽()에 약간의 문제가있었습니다.

충돌 문제와 관련하여 장애물이있을 경우 잠재적 인 원인이 될 수 있습니다.장벽을 사용할 때 그룹의 모든 작업 항목이 해당 명령에 도달 할 수 있어야합니다. 그렇지 않으면 커널이 중단되어 충돌이 발생할 수 있습니다.

if(someCondition){ 
    //do stuff 
    barrier(CLK_LOCAL_MEM_FENCE); 
    //more stuff 
}else{ 
    //other stuff 
} 

나의 이해는 하나 개 이상의 작업 항목 someCondition을 만족하는 경우, 모든 작업 항목이 해당 조건을 만족해야하며, 장벽을 건너 뛸 것 몇 가지가있을 것입니다. 장벽은 모든 작업 항목이 그 지점에 도달 할 때까지 기다립니다. 위의 코드를 수정하려면 다음과 같이 약간 재구성해야합니다.

if(someCondition){ 
    //do stuff 
} 
barrier(CLK_LOCAL_MEM_FENCE); 
if(someCondition){ 
    //more stuff 
}else{ 
    //other stuff 
} 

이제 모든 작업 항목이 장벽에 도달합니다.

이것이 루프에 어느 정도 적용되는지는 알 수 없습니다. 작업 항목이 for 루프에서 분리되면 장벽을 뚫을까요? 나는 확신 할 수 없다.

업데이트 : for 루프에 장벽이있는 몇 개의 ocl 프로그램을 성공적으로 종료했습니다. 모든 작업 항목이 for 루프를 동시에 종료하는지 확인하십시오. 또는 더 나은 방법으로 루프 외부에 장벽을 놓으십시오.

(출처 : OpenCL을 5 장, p90-91와 이기종 컴퓨팅)

+2

당신의 코멘트를 주셔서 감사합니다. 나도 잘 모르겠지만, 작업 그룹의 모든 스레드가 해당 작업 그룹의 스레드가 있으면 장벽을 넘어야한다고 생각합니다. 따라서 루프 그룹은 작업 그룹의 모든 스레드가 장벽을 치기 전에 깨면 아무런 문제가 없습니다. 그러나 작업 그룹의 적어도 하나의 스레드가 루프의 특정 반복에서 장벽을 쳤다면 해당 작업 그룹의 모든 스레드가 필요합니다. –

+0

문서가 건너 뛰는 또 다른 경우는 if/else가 있고 두 경우 모두 장벽을 호출하는 경우입니다. 이것은 프로그램을 크래시하는 것처럼 보이지 않지만 아무런 영향도 미치지 않습니다. AMD의 예제 코드는 for-loops에서 실행되는 모든 스레드를 유지한다는 것을 발견했습니다. 일부는 용도가 없지만 장벽에 부딪치게됩니다. –

관련 문제