Erste Tests der SIMD-Optimierungen

Bei der Nutzung von SIMD entsteht lediglich ein geringer Overhead, um die “breiten” 64- bzw. 128-Bit-Register vor den eigentlichen Operationen mit Werten zu füllen, und die Resultate aus den Registern zu extrahieren und zurück in den Speicher zu schreiben. Der Speedvorteil überwiegt den Overhead, selbst bei geringen Datenmengen. Nur ist die Frage, ob es sich lohnt, sich für geringe Datenmengen hinzusetzen und in Assembler zu programmieren, was ja doch schon einen gewissen Aufwand mit sich bringt.

Für größere Datenmengen macht sich der Speedvorteil tierisch bemerkbar und da kann es sich unter Umständen tatsächlich lohnen, mal ein bisschen Assembler zu programmieren. Mir persönlich macht es sogar Spaß, insofern würde ich es auch ohne den so hohen Zeitvorteil machen.

Den Unterschied zwischen geringen und großen Datenmengen sowie den zwischen einer regulären Implementierung in C++ und Implementierungen unter Verwendung von SIMD möchte ich anhand folgender Tabelle demonstrieren:

Tech. / # Vek. 1 10 100 1.000 10.000
C++ 100,0 % 100,0 % 100,0 % 100,0 % 100,0 %
SSE 103,9 % 99,9 % 49,8 % 26,8 % 24,6 %
3DNow! 115,4 % 97,2 % 48,4 % 26,0 % 24,0 %

Die Tabelle enthält die “Performance” (in Form des relativen Zeitaufwands) von drei verschiedenen Implementierungen einer Funktion “vec3trans”, die eine Menge von 3D-Vektoren mit einer 4×4-Matrix transformiert. Die Prozentwerte in der Tabelle stellen die jeweilis zur Ausführung der Funktion benötigte Zeit in Relation zur Referenzimplementierung in C++ dar. Es wurden pro Implementierung jeweils 1 Vektor, 10, 100, 1.000 und 10.000 Vektoren transformiert. Pro Implementierung und Anzahl Vektoren wurden die Ergebnisse mehrerer Durchläufe gemittelt, um unerwünschte äußere Einflüsse “wegzuglätten”.

Der relativ hohe Overhead in der ersten Spalte der Tabelle (Anzahl Vektoren 1) ist nicht auf den Einsatz von SIMD zurückzuführen. Vielmehr liegt es daran, dass die Transformationsmatrix vor den SIMD-Operationen transponiert wird, um dann die Transformation vieler Vektoren weiter zu beschleunigen. Das führt, wie man sieht, bei geringen Datenmengen leider zu einem Nachteil. Würde die Matrix nicht erst transponiert, wäre der Speedvorteil selbst bei einer geringen Datenmenge von einem Vektor bereits zu erkennen. Was bleibt, ist der bei höher werdender Datenmenge steigende (aber konvergierende) Speedvorteil. Und dieser ist doch schon beachtlich: Die SIMD-Implementierungen benötigen bei größeren Datenmengen nur ca. ein Viertel der Zeit im Vergleich zur Referenzimplementierung in C++. Wahnsinn!

Eine Menge von 10.000 3D-Vektoren entspricht übrigens einem schon recht großen 3D-Modell, wie es in Cyber E-Razor rockt die Galaxis garantiert nicht geben wird. Die bisherigen 3D-Modelle umfassen maximal ca. 1.500 Vertizes (Vertizes: Eckpunktvektoren des 3D-Gittermodells, grob gesagt). Selbst diese Modelle sollte ich für den Einsatz im Spiel noch optimieren, das heißt in diesem Fall, möglichst ohne großen optischen Qualitätsverlust weniger (als 1.000?) Vertizes verwenden.

Hinterlasse eine Antwort