2010-08-22 3 views
3

"SIMT"아키텍처의 개념과 디자인 중 일부는 여전히 나에게 불분명합니다.OpenCL : SIMT 실행 모델에 대한 기본 질문

많은 스레드가 잠금 단계에서 실행될 수 있기 때문에 코드 경로와 if()를 분산시키는 것은 다소 나쁜 생각입니다. 이제 그게 정확히 무슨 뜻입니까? 다음과 같은 경우는 어떻습니까?

kernel void foo(..., int flag) 
{ 
    if (flag) 
     DO_STUFF 
    else 
     DO_SOMETHING_ELSE 
} 

"플래그"매개 변수는 모든 작업 단위에서 동일하며 모든 작업 단위에서 동일한 분기가 수행됩니다. 그럼, GPU가 모든 코드를 실행하고, 그럼에도 불구하고 모든 것을 직렬화하고 기본적으로 아직 수행되지 않은 분기를 취할 것입니까? 아니면 조금 더 똑똑하고, 모든 스레드가 지점에 동의하는 한 찍은 지점 만 실행합니다. 어느 쪽이 항상 여기에있을 것입니다.

e.e. 직렬화는 항상 발생합니까 아니면 필요한 경우에만 발생합니까? 바보 같은 질문에 사과드립니다. ;)

답변

3

아니요, 항상 발생하지 않습니다. 두 가지 브랜치를 실행하는 것은 조건이 로컬 작업 그룹의 스레드간에 일관성이없는 경우에만 발생합니다. 즉, 조건이 로컬 작업 그룹의 작업 항목간에 서로 다른 값으로 계산되면 현재 GPU는 두 가지 분기를 모두 실행하지만 올바른 분기 만 실행합니다 값을 쓰고 부작용이있을 것입니다.

따라서 일관성을 유지하는 것은 GPU 분기의 성능에 매우 중요합니다.

+0

정확하게 중요하지 않습니다. 성능 유지에 중요한 요소입니다. 이것은 브랜치의 복잡성에 달려 있지만 적어도 지금까지 대부분의 상황에서 발생했지만, 브랜치가 평가되는지 확인하는 것보다 메모리 액세스를 최적화하는 것이 더 중요했습니다 (통합, 뱅크 충돌 방지, 트래픽 감소). 동일한 경로 (경우에 따라 이러한 최적화에 대해 효과가 있었음). – Grizzly

+0

@ Grizzly 브랜치를 사용하는 경우 매우 중요합니다. –

1

ati는 확실하지 않지만 nvidia는 영리합니다. 워프의 모든 스레드가 같은 방식으로 진행되면 직렬화가 수행되지 않습니다.

1

예를 들어, 플래그는 모든 작업 항목에 대해 동일한 값을 가지므로 좋은 컴파일러는 동일한 방향으로 모든 작업 항목을 취할 코드를 생성합니다.

그러나 다음과 같은 경우에 고려 : 여기

kernel void foo(..., int *buffer) 
{ 
    if (buffer[get_global_id(0)]) 
     DO_STUFF 
    else 
     DO_SOMETHING_ELSE 
} 

이 모든 작업 항목이 동일한 경로를 취할 것이라는 점을 보장 할 수 없습니다, 그래서 직렬화 또는 제어 흐름 제거가 필요하다.

+0

코드 패쓰가 분기되는 지 여부는 하드웨어 내부에서 발생해야하는지 여부에 따라 결정됩니다. 즉, 예를 들어 직렬화가 발생할 수도 또는 수행되지 않을 수도 있습니다. 버퍼 (일부 작업 그룹에서만 발생하지만 다른 작업 그룹에서는 발생하지 않을 수 있음) – Grizzly

+0

제어 흐름 제거 란 무엇입니까? 좀 더 설명해 주시겠습니까? 감사 – Zk1001