2012-04-02 6 views
1

Ich entwerfe eine Reihe von Vector-Klassen in C++, die SSE (SIMD) unterstützen. Die Bediener wurden aus Bequemlichkeitsgründen überlastet. Beispiel für Klasse:Aufruf einer anderen Implementierung der Funktion basierend auf SSE-Funktionen

class vector2 { 
public: 
//...code 
friend const vector2 operator+ (const vector2 & lhs, const vector2 & rhs); 
//...code 
protected: 
float x, y; 
}; 

Bisher hat die Methode überprüft, ob die CPU eine SSE (SIMD) Funktion hat, eine Klasse mit I PROCESSOR genannt erstellt, die diese Prüfung tut, wenn das Programm zur Laufzeit ausgeführt wird . Beispiel für Verfahren:

const vector2 operator+ (const vector2 & lhs, const vector2 & rhs) { 
vector2 temp; 
if(PROCESSOR.SSE) { 
_asm { //... The "SSE WAY" 
} 
} else { 
// The "NORMAL WAY" 
} 
return temp; 
} 

So wie Sie sehen können, wenn SSE verfügbar ist wird es die „SSE“ Weg laufen sonst wird es „normal“ laufen. Es ist jedoch sehr ineffizient, bei jedem Aufruf dieser Operation prüfen zu müssen, ob SSE verfügbar ist. Gibt es eine Möglichkeit, zwei Versionen einer Methode zu implementieren und nur die entsprechende Methode aufzurufen? Da meine PROCESSOR-Klasse nur einmal die SSE-Prüfung durchführt, gibt es eine Möglichkeit, meine Vektorklasse so einzustellen?

+0

Die Tests selbst können langsam sein, aber diese SSE-Implementierung wird langsamer als Sie "Normal" -Code sein. SSE wurde entwickelt, um mit 16-Byte-Daten zu arbeiten, und ist nicht optimal für nicht ausgerichtete kleinere Typen. Optimieren Sie den Code nicht ohne Profiling. Dies würde Sinn machen, wenn Sie zwei Tabellen von Vektor2 summieren. Aber nur für einen, es wird definitiv langsamer sein. Wie man sagte, ist vorzeitige Optimierung die Wurzel allen Übels. Machen Sie Ihren Code funktionsfähig, dann profilieren Sie ihn und optimieren Sie ihn schließlich. – crazyjul

Antwort

2

Um Code-Duplizierung zu vermeiden, können Sie zwei Vektorklassen erstellen, eine für SSE und eine für Nicht-SSE. Dann können Sie Ihre Anrufalgorithmen nachbilden.

class vector_base { float x,y; } ; 
class vector_sse : public vector_base { vector_sse operator+(...){...} }; 
class vector_nonsse : public vector_base { vector_nonsse operator+(...){...} }; 

template< typename VECTOR > 
void do_somthing() { 
    for(/*lots*/) { 
    VECTOR v = ...; 
    VECTOR w = ...; 
    foo(v+w); 
    } 
} 

int main() { 
    if(PROCESSOR.SSE) { do_something<vector_sse>(); } 
    else { do_something<vector_nonsse>(); } 
} 

Wenn Sie wahrscheinlich andere Klassen als Vektor verwenden (wie Matrix usw.) in einer SSE Weise Sie es besser machen könnte Ihre Typen stattdessen durch Tagging .. in diesem Fall wird der Code wie folgt aussieht:

+0

+1. Ich habe diese Technik vorher mit gutem Erfolg benutzt. crazyjuls Kommentar zu der ursprünglichen Frage ist jedoch beachtenswert; Es ist nicht klar, dass SSE nur für einen Vektor mit zwei Elementen geeignet ist, es sei denn, Sie arbeiten mit mehreren gleichzeitig. –

+0

@JasonR Ich stimme zu, ich nehme an, dass SSE bekanntlich eine erhebliche Beschleunigung für den Code ist. –

+0

Die Klasse war nur ein Beispiel. Ich arbeite mit Vektoren 2,4, 16 (oder Matrizen) –

0

Teilen Sie die Funktion in zwei Teile, einen für SSE und einen nicht. Erstellen Sie einen Funktionszeiger und initialisieren Sie ihn mit der entsprechenden Version der Funktion. Sie können eine Inline-Funktion erstellen, die den Zeiger aufruft, wenn dies Ihren Code sauberer erscheinen lässt.

Leider zahlen Sie immer noch den Preis einer Indirection für den Funktionsaufruf. Ob dies schneller ist als das Testen eines booleschen Flags, kann nur durch ein Benchmarking festgestellt werden.

Der beste Weg, um mit diesem Problem umzugehen, ist sicherzustellen, dass die Menge der Daten, die bei jedem Anruf verarbeitet werden, ausreicht, um den Overhead unbedeutend zu machen.

+0

Wenn Sie aufrufende Funktionen in zwei Formen aufteilen, erreichen Sie schließlich einen Punkt, an dem Sie den Overhead auf Kosten der Verdopplung der Codegröße vermeiden (aber das Extra wird nicht ausgeführt, also kein Geschwindigkeitsverlust dort) –