Introduce Of Wave Programming
Windows 10 Fall Creators Update 가 나오면서 Shader Model 6.0 이 추가되었다. 여태까지의 Shader Model 업데이트는 대부분 DirectX 버젼이 올라가면서 같이 업데이트 된 경우가 많으나 이번의 Shader Model 6.0 은 따로 업데이트 되었다. Shader Model 6.0 에서의 가장 큰 기능 추가는 당연히 Wave Intrisic 이라고 할 수 있겠다. Wave Intrisic 을 제외하면 Shader Model 6.0 은 바뀐게 없다.
여태까지의 HLSL 을 사용한 쉐이더 작성은 거의 대부분 Single-Threading 으로 작동되었다. Pixel Shader 에서 ddx, ddy instrisic 을 사용하여 Gradient 데이터를 가져올 수 있긴 했지만 이 것을 제외하면 거의 없었다고 보면 되겠다. 그래서 Shader Model 6.0 에서는 다른 Thread 와 인터렉션 할 수 있는 Wave Intrisic 을 지원한다. MSDN : HLSL Shader Model 6.0 을 살펴보면 알겠지만 단순한 API 들을 제공하는 것이다. 하지만 내부에서 동작하는 것은 조금 다르다.
MSDN : HLSL Shader Model 6.0 에서 나온 용어에 대한 설명이 필요하다. Lane 은 일반적으로 생각되는 한개의 Thread 가 실행되는 것이다. Shader Model 6.0 이전의 쉐이더 모델은 단순히 Lane 개념 안에서 코딩을 해야 했다. Lane 은 상황에 따라 실행되고 있는 상태일 수도 있고, 쉬고 있는 상태일 수도 있다. Wave Intrisic 을 사용해 이를 각각의 Lane 에서도 알 수 있다. Wave 는 GPU 에서 실행되는 Lane 의 묶음을 뜻한다. 즉 여러개의 Lane 이라고 할 수 있겠다. 같은 Wave 안의 Lane 들은 Barrier 라는게 없다. 필자가 알고 있는 Barrier 는 Memory Barrier 인데, 이는 Thread(Lane)끼리의 같은 메모리에 접근하는 것에 대한 동기화를 위해 있는 개념이다. 동기화를 위한 Barrier 는 속도를 늦출 수 밖에 없다. 하지만 Wave 로 묶여진 Lane 들은 서로 Barrier 가 명시적으로 존재하지 않기 때문에 Wave 별로 빠른 메모리 접근이 가능하다는 것이다. Wave 는 Warp, WaveFront 라고도 불리울 수 있다고 한다.
그리고 이 API 들을 통해 약간의 드라이버 내부를 엿볼 수 있다. Pixel Shader 에서 Render Lane 과 Helper Lane 이 구분되어져 있는데, 이는 ddx,ddy 를 통해 픽셀의 Gradient 를 계산하는 것에 대한 보다 디테일한 개념을 생각할 수 있게 해준다. GPU 드라이버 시스템에서는 픽셀을 처리하기 위해 단순히 한개의 픽셀만 처리하는게 아닌 2x2 의 픽셀을 엮어 계산한다. 이를 MSDN 문서에서는 2x2 의 픽셀 뭉치를 Quad 라고 명칭한다. Quad 는 두가지 종류에 스레드가 실행된다. 하나는 우리가 잘 알고 있는 Pixel Shader 를 실행하는 Render Lane 이다. Render Lane 은 화면에 보여주는 색을 결과로 내놓게 된다. 그리고 나머지 한가지는 Helper Lane 인데, 이는 Pixel 별로 Gradient 를 계산하기 위해 실행되는 Lane 으로써 아무런 결과를 내놓지 않고 단순히 계산을 위한 Lane 이다.
Shader Model 6.0 은 DirectX12 과 Vulkan 에서 지원한다. DirectX 에서는 Pixel Shader 와 Computer Shader 에서 지원한다. Vulkan 에서는 모든 쉐이더 단계에서 지원한다. 그래픽 카드 벤더별로 조금씩 다른게 있으니 GDCVault(GDC 2017) : Wave Programming D3D12 Vulkan 에서 참고 바란다.
이 API 는 여러 쓰레드들 끼리 쉽게 협력하여 보다 효율적인 쉐이더 병렬 프로그래밍을 가능하게 해줄듯하다. 다만 Shader Model 5.0 에서 소개된 ComputeShader 만큼의 임팩트는 없다. 패러다임의 아주 큰 변화는 없다는 뜻이다. DirectX12 가 지향하는 드라이버 시스템에서의 부담을 줄이는 것과 Shader Model 6.0 은 서로 방향이 비슷하다고 생각된다.
추가
gpu branching and divergence에서 NVidia 의 Volta 아키텍쳐에 대해서 잠깐 언급했었다. Volta 아키텍쳐는 GPGPU 기능을 강화하기 위해 Thread 의 관리 꽤나 향상시켰다. Wave Intrisic 들은 다른 Thread 와의 처리를 도와주기 때문에 Shader Model 6.0 을 지원하는 GPU 가 나온다면 재미있는 시도들이 나올듯 하다.