GPU의 데이터 병렬 아키텍처
정지 대기를 피하기 위하여
그래픽 처리 장치가 필요한가?
어차피 같은 연산을 매우 자주 반복하는 것이기 때문에 해당 기능을 담당하는 전용 하드웨어를 사용하면 성능 향상의 효과가 있다.
이전의 GPU가 이러한 단순 기능을 고정한 파이프라인이었다면, 최근의 GPU는 프로그래밍 가능성과 확장성을 지향한다.
데이터 병렬 아키텍처
데이터 검색을 기다림으로 인해 처리 장치가 멈추는 것을 정지 대기라고 하며, 이를 피하기 위한 다양한 시도가 있었다. CPU와 GPU는 시도의 방향성이 다르다.
GPU 칩 영역의 대부분은 수천 개의 셰이더 코어라 하는 대규모 처리 장치 집합으로 구성. GPU는 정렬된 유사 데이터 집합을 차례대로 처리하는 “스트림 프로세서” → 병렬 처리 가능. 병렬 처리를 위하여 데이터간 독립성을 유지.
GPU의 지연 시간은 일반적으로 CPU보다 높다. 캐시 메모리와 제어 로직 전용 칩 영역이 적기 때문.
1) 셰이더 프로세서가 그냥 수행된다면
레스터화 된 메시가 몇천의 프래그먼트로 구성되었다! → 각 프래그먼트에 대하여 셰이더 프로세스 수행 → 레지스터 값에 대하여 빠른 접근과 연산 → 텍스처와 같은 분리된 자원 접근 시도 → 멀다. 수천 클럭 소모하며 정지 대기. → 참사!!
2) 각 프래그먼트에 약간의 공간 보유
앞과 동일한 상황 → 텍스처 접근 명령어 인식 및 실행 → 바로 다음 프래그먼트로 이동 → 모든 프래그먼트 이동 이후 다시 처음으로 돌아옴 → 데이터 가져왔네? 연산 속행.
공간이 없으면? 데이터를 가져와서 레지스터에 넣을 때 까지 기다려야한다. 그래야 접근할테니.
3) SIMD(Single Instruction, Multiple Data)
연산 수행과 데이터를 분리하여 고정된 수의 셰이더 프로그램에서 동일 명령을 같은 단계로 맞춰 수행.
4) 스레드
CPU의 그거 아님. 프래그먼트에 대한 각 픽셀 셰이더의 호출이다. 셰이더의 입력값에 대한 약간의 메모리와 셰이더 실행에 필요한 레지스터 공간으로 이루어진 것.
동일 셰이더 프로그램을 사용하는 스레드를 집합으로 묶는다. 이를 엔비디아는 warp, AMD는 wavefront라고 부른다. 묶인 스레드들은 SIMD 레인에 할당되어 처리된다.
5) 셰이더 프로그램 구조체
각 스레드가 사용하는 레지스터의 양이 중요하다. 한정된 자리에 마른 사람들 이나 뚱뚱한 사람들이 들어갔을 때, 어느 쪽이 더 많이 들어가겠는가?
- 각 스레드가 많은 레지스터를 사용한다. → 더 적은 스레드, 워프가 GPU에 거주한다.
- 많은 워프가 “비행중(거주 워프)” 일때 → 점유율이 높다! → 여러 워프를 치환하며 진행하는 동안 앞선 워프의 데이터 로딩이 완료됨. → 별도의 정지대기 없이 순서가 왔을 때 바로 이어서 실행 가능.
- 비행중인 워프가 적다 → 점유율이 낮다 → 모든 워프에 대하여 치환 과정이 끝나서 처음으로 돌아왔는데 아직도 로딩중 → 정지대기? 다시 순회? → 어느 쪽이든 효율적이지 못하다.
6) 동적 분기
if 명령어와 반복문으로 인한 스레드 분산. 자세한건… 더 알아봐야 할 듯.
출처
- 리얼-타임 렌더링 4/e(에이콘 출판)