SSE Vector Klasse (SIMD Optimierung)
-
Hallo,
ich probiere seit einiger Zeit mit SSE Optimierung rum. Dazu habe ich 2 Vector Klassen geschrieben. Eine mit SSE Optimierung und eine ohne. Bei der SSE Optimierung nutze ich die <xmmintrin.h> Intrinsics. Als Compiler verwende ich den gcc in Version 4.1 und das ganze unter Linux. In beiden Klassen sind die Operatoren (+, -, *, /) jeweils als inline deklariert.
Funktionieren tun beide Klassen aber mir ist folgendes aufgefallen.
Wenn ich beide Klassen im gcc mit -O2 optimiere sind diese gleich schnell. Deaktiviere ich im gcc die automatische Optimierung (-O0) so ist die SSE optimierte Vector Klasse wesentlich schneller.
Als Laie würde ich jetzt daraus schliessen, dass der Compiler automatisch SSE optimiert aber das glaube ich auch nicht so recht?
Ich verwende den Datentyp __m128 und dieser sollte ja vom Compiler automatisch 16 Bit aligned angelegt werden. Muss ich dann in der Klasse auch nochmal 16 Bit alignment definieren?
Ich bin für jeden Hinweis dankbar wo ich da ansetzen kann.
MfG, Tim
-
timbo schrieb:
Als Laie würde ich jetzt daraus schliessen, dass der Compiler automatisch SSE optimiert aber das glaube ich auch nicht so recht?
Das tun die neueren Compiler (VC7.1/8.0 und die neuen GCC) soweit ich weiss wirklich. Wie meistens solltest du das Optimieren dem Compiler überlassen, ausser wenn du wirklich weisst, was du tust.
-
nunja, man lernt ja nie aus.
Ich habe mich schon mit dem Thema SSE (bzw. SIMD) befasst. Jedoch hat mich dieses Ergebnis nun doch etwas verwundert. Das Laie war eher auf das Thema SSE bezogen.
Grüße
-
ohne mit dem profiler drueber zu gehen ist es nicht moeglich zu sagen was das limitierende fuer deinen benchmark ist. Heutzutage ist es oft das RAM, da kann man soviel SSE MMX ALTIVEC coden wie man will, vom 'unwissendem' angewendet ist es pures glueck wenn es vorteile bringt.
btw. und was passiert bei -o3?

-
hi timbo,
poste mal deine 2 vector klassen....moechte auch mal die ergebnisse vergleichen und rumspielen...cu
-
timbo schrieb:
Als Laie würde ich jetzt daraus schliessen, dass der Compiler automatisch SSE optimiert aber das glaube ich auch nicht so recht?
Prüfe es doch nach. Einfach Compilerflag -S angeben und Assembler Listing anschauen (-masm=intel oder -masm=att (default) für Dialekt).
-
Oder disassemblieren mit:
objdump -d PROGRAMMIch habe auch schon mit inline SSE Assembler rumgespielt und festgestellt dass sich die SSE Optimierung einer Vektorklasse nicht lohnt. Bei Matrix sieht das wiederum anders aus, da bringt es einiges.
Um rauszufinden ob und wie viele SSE instruktionen der Compiler erzeugt hat
hilft die Zeile:objdump -d PROGRAMM | grep xmm | wc -lKann man als so ne art Pseudometrik verwenden.
-
Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum Rund um die Programmierung verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Hallo,
danke für die Hinweise. Der Tipp mit dem Assembler anschauen war ganz hilfreich. Ohne automatische Compiler-Optimierung (-O0) sind dort Instruktionen zu finden welche auf dem SSE Register (xmm) ausgeführt werden. Sobald ich jedoch den Compiler optimieren lassen, sind dort keine SSE Register (xmm) mehr zu finden. Wenn ich das ganze mit dem ICC (7.1) compiliere sind in beiden Fällen noch SSE Register zu finden.
Hier mal meine (vereinfachten) Vector-Klassen:
Vector.h
class Vector { public: float x, y, z; Vector() { this->x = 0; this->y = 0; this->z = 0; }; Vector(const float x, const float y, const float z) { this->x = x; this->y = y; this->z = z; }; }; // + static inline Vector operator + (const Vector &v1, const Vector &v2) { return Vector( v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); } // - static inline Vector operator - (const Vector &v1, const Vector &v2) { return Vector( v1.x - v2.x, v1.y - v2.y, v1.z - v2.z ); } // * static inline Vector operator * (const Vector &v1, const Vector v2) { return Vector( v1.x*v2.x, v1.y*v2.y, v1.z*v2.z ); } // / static inline Vector operator / (const Vector &v1, const Vector v2) { return Vector( v1.x/v2.x, v1.y/v2.y, v1.z/v2.z ); }VectorSSE:
#include <xmmintrin.h> class VectorSSE { public: __m128 vector; VectorSSE() { vector = _mm_set_ps1(0.0f); } VectorSSE(__m128 m128) { vector = m128;} VectorSSE(const float x, const float y, const float z) { vector = _mm_set_ps(x, y, z, 0.0f); } }; // + static inline VectorSSE operator + (const VectorSSE &v1, const VectorSSE &v2) { return VectorSSE( _mm_add_ps(v1.vector, v2.vector) ); } // - static inline VectorSSE operator - (const VectorSSE &v1, const VectorSSE &v2) { return VectorSSE( _mm_sub_ps(v1.vector, v2.vector) ); } // * static inline VectorSSE operator * (const VectorSSE &v1, const VectorSSE &v2) { return VectorSSE( _mm_mul_ps(v1.vector, v2.vector) ); } // / static inline VectorSSE operator / (const VectorSSE &v1, const VectorSSE &v2) { return VectorSSE( _mm_div_ps(v1.vector, v2.vector) ); }Uns hier mein Test:
// create timer Timer timer = Timer(); // test 1 // without sse timer.start(); Vector result1 = Vector(0, 0, 0); for(int i = 0; i < ITERATIONS; ++i) { result1 = result1 + Vector( rand(), rand(), rand() ); result1 = result1 - Vector( rand(), rand(), rand() ); result1 = result1 * Vector( rand(), rand(), rand() ); result1 = result1 / Vector( rand(), rand(), rand() ); } timer.stop(); timer.printResult("test 1 (without sse2)"); // test 2 // with sse timer.start(); VectorSSE result2 = VectorSSE(0, 0, 0); for(int i = 0; i < ITERATIONS; ++i) { result2 = result2 + VectorSSE( rand(), rand(), rand() ); result2 = result2 - VectorSSE( rand(), rand(), rand() ); result2 = result2 * VectorSSE( rand(), rand(), rand() ); result2 = result2 / VectorSSE( rand(), rand(), rand() ); } timer.stop(); timer.printResult("test 2 (with sse)");Gibt es noch eine Möglichkeit sich das Alignment anzuschaun?
Grüße, Tim