우리가 코드를 작성하다 보면, 분기를 나눠야하는 경우가 상당히 많다.
분기를 나누는 이유가 여러가지가 있겠지만, 근본적으로는 상황에 맞게 필요한 연산만 실행하기 위해서일 것이다.
이는 최적화를 위해서 일 수도 있고, 올바른 결과물을 위해서일 수도 있을 것이다.
하지만, 만약 모든 분기가 다 실행된다면?
예를 들어 아래 코드를 보자.
if(현재 픽셀이 피부라면)
{
Color = SkinShading();
}
else if(현재 픽셀이 옷이라면)
{
Color = ClothShading();
}
else
{
Color = HairShading();
}
뭐 이런 예시가 있다고 가정해보자. (일반적으로는 이런 분기는 나뉘지 않을 것 같긴 하다... 옷이랑 피부, 머리카락은 아예 다른 쉐이더를 쓰지 않을까?)
이 때, 우리가 기대하는 것은, 픽셀의 타입에 맞게 하나의 함수만 실행되는 것이다.
현재 픽셀이 피부라면, SkinShading만 실행하고, 옷이라면 ClothShading만 실행하고 그것도 아니라면 hairShading을 실행하는 것이다.
하지만 그래픽카드의 연산은 우리 의도대로 실행되지 않는다고 한다.
그래픽카드는 다중 병렬 연산을 통해 아주 고속으로 수많은 픽셀에 대한 연산을 처리해준다.
일반적으로는 32개나 64개의 레지스터를 묶어서 실행한다고 한다.
이 때, 병렬 연산을 극대화 하기 위해서는 모든 레지스터가 동일한 명령어를 처리하도록 하는 것이 가장 좋다고 한다.
즉, 분기 때문에 각 레지스터들이 다른 연산을 실행하게 되면 병렬 연산의 성능이 저하될 수 있다는 것이다.
이로 인해 레지스터간 처리해야 하는 명령어를 통일하기 위해 GPU에선 모든 분기를 다 실행한 뒤에 조건에 맞는 결과값만 반환하는 방식으로 실행한다고 한다.
하지만, 모든 분기를 다 실행하게 되면 이는 성능상에 엄청난 영향을 끼칠 수 있다. 특히나 if~else문 내부에 있는 연산이 무거울수록 그 정도는 더욱 커질것이다.
만약, 모든 픽셀이 동일한 분기로 진입하는 것이 확정된 상황이라면 모든 분기에 대한 연산을 다 실행하지 않고 특성 분기에 대해서만 실행하도록 최적화가 되어있다고는 한다.
하지만, 일반적인 상황에선 그렇지 않기 때문에 분기를 나누는 것이 아닌가?!
그러므로 우리는 쉐이더 내에서 if else 문을 사용할 때엔 주의를 하여서 사용해야 한다.
분기 안에 특히나 무거운 연산들이 포함되어 있을 때는 더욱 그렇다.
'그래픽스' 카테고리의 다른 글
컴퓨터 그래픽스 - Rim Light (역광) (0) | 2024.05.14 |
---|---|
컴퓨터 그래픽스 - 상수 버퍼를 사용할 때 주의사항 (0) | 2024.05.08 |
컴퓨터 그래픽스 - 깊이 버퍼 (Z-Buffer, Depth-Buffer) (0) | 2024.04.25 |
컴퓨터 그래픽스 - 빛의 반사와 큐브맵 텍스쳐 (환경 매핑) (0) | 2024.04.23 |
컴퓨터 그래픽스 - 퐁 쉐이딩 (Diffuse Light, Specular Light, Ambient Light) (2) | 2024.04.10 |