Próbując poprawić wydajność mojej klasy wykrywania kolizji, odkryłem, że ~ 80% czasu spędzonego na GPU spędza na warunkach, jeśli tylko próbuję ustalić granice wiader, przez które powinna się zapętlać.
Dokładniej:
każdy wątek otrzymuje identyfikator, przez ten identyfikator pobiera swój trójkąt z pamięci (3 liczby całkowite), a przez te 3 pobiera swoje wierzchołki (3 liczby zmiennoprzecinkowe każdy).
Następnie przekształca wierzchołki w całkowite punkty siatki (obecnie 8 x 8 x 8) i przekształca je w granice trójkąta na tej siatce
Aby przekształcić 3 punkty w granice, znajduje min / max każdego wymiaru wśród każdego z punktów
Ponieważ w używanym przeze mnie języku programowania brakuje minmax, sam go stworzyłem, wygląda to tak:
procedure MinMax(a, b, c):
local min, max
if a > b:
max = a
min = b
else:
max = b
min = a
if c > max:
max = c
else:
if c < min:
min = c
return (min, max)
Przeciętnie powinno to być 2,5 * 3 * 3 = 22,5 porównań, co ostatecznie pochłania znacznie więcej czasu niż rzeczywiste testy przecięcia krawędzi trójkąta (około 100 * 11-50 instrukcji).
W rzeczywistości stwierdziłem, że wstępne obliczenie wymaganych segmentów na jednostce centralnej (jednowątkowa, bez wektoryzacji), układanie ich w widoku GPU wraz z definicją segmentu i zmuszanie GPU do wykonania ~ 4 dodatkowych odczytów na wątek było 6 razy szybsze niż próba na miejscu ustalić granice. (zauważ, że są one ponownie obliczane przed każdym wykonaniem, ponieważ mam do czynienia z dynamicznymi siatkami)
Dlaczego więc porównanie jest tak strasznie wolne na GPU?