CPU · TILESGPU · SIMTWARP · 32 lanesDIVERGENCE · watch
Rozdział 14 / Wydajność

Optymalizacja i równoległość

BVH z Rozdziału 13 zmniejsza liczbę testów na promień. Ten rozdział pyta o coś innego: jak policzyć miliony niezależnych promieni na raz, nie jeden po drugim.

TL;DR
Pass: CPU

Promienie są niezależne — to dobra wiadomość

Policzenie koloru piksela (x,y) nie zależy od koloru piksela (x+1,y). Ta niezależność, rzadka w informatyce, nazywana bywa „embarrassingly parallel” — i to właśnie dzięki niej ray tracing skaluje się tak dobrze na wiele rdzeni. Najprostsza strategia na CPU: podziel obraz na kafle (np. 32×32 piksele), przydziel kafle do puli wątków, każdy wątek liczy swój kafel od początku do końca, niezależnie od innych.

CPU.tiling4 worker threads
T1 T2 T3 T4
Cztery kolory, cztery wątki — każdy kafel policzony niezależnie, w dowolnej kolejności.
Pass: GPU

SIMT i rozbieżność (divergence)

GPU wykonuje grupy wątków (warp/wavefront, zwykle 32) tą samą instrukcją naraz, na różnych danych (SIMT). Świetnie, gdy wszystkie promienie w warpie robią to samo. Katastrofalnie, gdy się rozjeżdżają: jeśli część promieni trafia w szkło (Rozdział 7), a część w diffuse (Rozdział 5), GPU musi wykonać oba fragmenty kodu dla całego warpu — wątki, które nie potrzebują danej ścieżki, po prostu czekają. To centralny problem GPU ray tracingu, którego rasteryzacja (jeden shader na cały trójkąt) w większości unika.

Warp.divergencemixed vs sorted
posortowanie: 0% · 50% lanes w docelowym warpie · nadal 4 przebiegi (2 na warp)
2 WARPY × 8 PROMIENI, DWA MATERIAŁY WARP A → diffuse (docelowo) WARP B → szkło (docelowo)
Przesuń suwak — dwa mieszane warpy (każdy wymaga obu przebiegów) rozdzielają się w jeden czysto-diffuse i jeden czysto-szklany warp (każdy potrzebuje już tylko jednego). To dosłownie krok „Sortuj po materiale” z pipeline'u niżej.
Pass: Techniki

Sortowanie promieni i wavefront path tracing

Nowoczesne GPU renderery (OptiX, silniki „wavefront”/„streaming”) nie prowadzą jednego promienia przez cały pipeline w jednym wątku. Zamiast tego przetwarzają całe partie promieni etapami: wszystkie testy przecięcia naraz, potem sortowanie promieni po typie materiału, potem shading — jeden kernel na materiał, tylko dla promieni, które go potrzebują. To ten sam pipeline z Rozdziału 1, tylko rozbity na kolejkę zamiast rekurencji.

Wavefront.pipelinebatch stages
Generujpromienie Przecięcie(BVH, R.13) Sortuj pomateriale Shading(per-material) Nowe promieniewtórne pętla, aż brak aktywnych promieni
Sortowanie po materiale przed shadingiem to właśnie technika ograniczająca rozbieżność z poprzedniego diagramu.
Z praktyki

To dlatego renderery GPU (Redshift, Cycles GPU, Arnold GPU, V-Ray GPU) czasem renderują pewne typy materiałów — SSS, włosy, wolumetria — wolniej względem CPU niż prosty diffuse: te ścieżki kodu są z natury bardziej rozbieżne.

Ustawienia „liczba wątków” / „CPU threads” w Twoim DCC to dosłownie rozmiar puli wątków z tego rozdziału. Więcej wątków pomaga tylko do liczby rdzeni fizycznych — powyżej tego, wątki zaczynają sobie nawzajem zabierać czas procesora.

Słowniczek
Równoległość (parallelism)
Wykonywanie niezależnych obliczeń jednocześnie.
Kafelkowanie (tiling)
Podział obrazu na niezależne bloki pikseli do rozdania wątkom.
SIMT
Single Instruction, Multiple Threads — model wykonania GPU.
Warp / wavefront
Grupa wątków GPU wykonujących tę samą instrukcję naraz.
Rozbieżność (divergence)
Sytuacja, gdy wątki w warpie potrzebują różnych ścieżek kodu.
Wavefront path tracing
Przetwarzanie promieni w partiach, etap po etapie, z sortowaniem po materiale.
Idź głębiej
Dodatek J — Złożoność sieci shaderów