Bei dem Versuch, die Leistung meiner Kollisionserkennungsklasse zu verbessern, stellte ich fest, dass ~ 80% der Zeit, die an der GPU verbracht wurde, für if / else-Bedingungen aufgewendet wurde, nur um die Grenzen für die Eimer herauszufinden, die sie durchlaufen sollte.
Etwas präziser:
Jeder Thread erhält eine ID, mit dieser ID holt er sein Dreieck aus dem Speicher (jeweils 3 Ganzzahlen) und mit diesen 3 seine Scheitelpunkte (jeweils 3 Floats).
Anschließend werden die Scheitelpunkte in ganzzahlige Gitterpunkte (derzeit 8 x 8 x 8) umgewandelt und in die Dreiecksgrenzen dieses Gitters umgewandelt
Um die 3 Punkte in Grenzen umzuwandeln, werden die Min / Max jeder Dimension unter jedem der Punkte ermittelt
Da in der von mir verwendeten Programmiersprache ein Minmax fehlt, habe ich selbst einen erstellt, der folgendermaßen aussieht:
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)
Im Durchschnitt sollten es also 2,5 * 3 * 3 = 22,5 Vergleiche sein, was viel mehr Zeit in Anspruch nimmt als die tatsächlichen Dreieck-Kanten-Schnittpunkttests (etwa 100 * 11-50 Anweisungen).
Tatsächlich stellte ich fest, dass die Vorberechnung der erforderlichen Buckets auf der CPU (Single Threaded, keine Vektorisierung), das Stapeln in einer GPU-Ansicht zusammen mit der Bucket-Definition und das Ausführen von ~ 4 zusätzlichen Lesevorgängen pro Thread durch die GPU sechsmal schneller war als der Versuch die Grenzen vor Ort herauszufinden. (Beachten Sie, dass sie vor jeder Ausführung neu berechnet werden, da es sich um dynamische Netze handelt.)
Warum ist der Vergleich auf einer GPU so schrecklich langsam?