SIMD intelligent einsetzen
-
Pack das Zeug in X dll's und dann lade die zu dem system kompatible... oder arbeite intern direkt mit Funktionszeigern.
-
Pack das Zeug in X dll's und dann lade die zu dem system kompatible... oder arbeite intern direkt mit Funktionszeigern.
Ich würd das nur ungern über DLLs lösen, da mir so der inline vorteil verloren geht, und meist bringt ein einfaches inline mehr als die SIMD optimierung, denk ich mal ...
Das mit den Funktionszeigern klingt interessant, nur blöd das ich noch nie wirklich damit gearbeitet hab
Ich produziere seit Jahren schlechten C++ Code, mit C hatte ich noch nix am Hut.Hab ich durch die Funktionszeiger kein Overhead? Funktioniert dann auch noch inline so wie es soll?
Edit:
Ehm, iwie kann man inline ja garnet bewerkstelligen, wenn man eine codeauswahl zur laufzeit hat, oder täusche ich mich grad?
-
Bingo! (Außer natürlich durch sich selbst verändernden code...)
-
Außer natürlich durch sich selbst verändernden code...
Das müsstest du mir mal genauer erklären!?^^
-
Mr. Potato schrieb:
Außer natürlich durch sich selbst verändernden code...
Das müsstest du mir mal genauer erklären!?^^
Lass lieber die Finger davon und benutz´ Funktionspointer. Wenn man typedefs benutzt sieht das alles nicht mehr so wild aus.
Header
// Typdefinition für Funktionspointer typedef double (*fun_double_2_param)( double, double ); // Addition, einmal Standard FPU, einmal SSE double fpu_add( double op1, double op2 ) { return op1 + op2; } double sse_add( double op1, double op2 ) { return op1 + op2; } struct DoubleOp { // Funktionszeiger auf zu benutzende Funktion static fun_double_2_param add; static void initialize(); }Implementation
// Funktionszeiger mit 0 initialisieren fun_double_2_param DoubleOp::add = 0; void DoubleOp::initialize() { // Funktionspointer in Abhängigkeit der SSE Verfügbarkeit setzen if( !sse_enabled() ) { // kein SSE, normale FPU benutzen add = fpu_add; } else { // SSE verfügbar und benutzen add = sse_add; } } int main(int argc, char* argv[]) { DoubleOp::initialize(); double e = DoubleOp::add( 2,3 ); }Wenn man das sicher machen möchte kann man das
structdurchclassersetzen, die eigentlich Funktionszeiger privat machen und den Aufruf durch eine Wrapper Methode erledigen, die die Gültigkeit des Funktionszeigers prüft.
-
Der OP wollte ja, dass der Code dynamisch plattformabhängig ge"inline"d wird, wo sinnvoll... Ist natürlich schwer zu bewerkstelligen

-
Decimad schrieb:
Der OP wollte ja, dass der Code dynamisch plattformabhängig ge"inline"d wird, wo sinnvoll... Ist natürlich schwer zu bewerkstelligen

Schwer zu bewerkstelligen und nicht zu garantieren. Was und wie ein Compiler inlinen kann, weiß nur der Compiler (und evtl. noch seine Hersteller). Ein "inline" im Code heißt überhauptnichts. Es ist nur ein Hinweis an den Compiler, dass er die Funktion vielleicht wenns ihm nicht zu viel ausmacht und er grade nichts besseres vorhat inlinen könnte. Ob er kann/will/darf prüft ein aktueller Compiler aber sowieso bei so jeder Funktion, daher hat ein explizites "inline" im Code nichts zu sagen.
Was das Inlinen über DLL-Grenzen hinweg angeht - manche Runtimes können auch das. Mein Tip wäre, es so zu implementieren wie es gut umsetzbar ist, ohne den Code zu einem Alptraum zu machen, und dann in einem Stresstest den Profiler zu bemühen.
-
Wie soll der Compiler denn plattformabhängig inline Code erzeugen, wenn erst zur Laufzeit feststeht, ob SSE verfügbar ist oder nicht?
Ein erster Ansatz zur Performancesteigerung ist z.B. die Matrizen als Referenz und nicht als Kopie zu übergeben. Vielleicht wird ja noch anderswo CPU Zeit verbrannt, was man durch einfachere Maßnahmen in den Griff kriegen kann.
-
Btw: Praktisch jede CPU in einem PC unterstützt heutzutage schon mindestens SSE2

Um vielleicht ein paar Zahlen zu nennen: Über 97% der Computer in der Steam Hardware Survey haben sogar SSE3...Natürlich muss das nicht unbedingt deine Zielgruppe widerspiegeln, im Zweifelsfall würde ich auf bedingte Kompilierung setzen, das ist wohl das Einzige was mit Sicherheit optimale Performance liefert. Und wenn du mit MSVC arbeitest dann auch wichtig: Kein inline asm sondern Intrinsics verwenden
-
Eine guter Kompromiss wäre auch, anstatt die direkten mathematischen Operationen per Funktionszeiger auf die richtige Implementierung zu biegen, die zeitraubendsten Algorithmen komplett zu übersetzen, so wird der Aufruf"overhead" verringert, wenns auf den letzten Zyklus ankommt. Andererseits könnte man auch gleich mehrere Executables mitliefern...

-
Stimmt. Das meiste aus SSE bekommt man in der Regel wenn man seine ganzen Datenstrukturen etc. so auslegt dass man möglichst lange Datenströme damit bearbeitet. Einzelne Vektoroperationen über SSE abzuwickeln bringt zwar auch einen gewissen Performancevorteil aber mehr zu gewinnen gibts sicherlich wenn man ganze Algorithmen ensprechend für SSE implementiert. Simples Beispiel: Vektorarithmetik ist in der Regel durchsetzt mit horizontalen Operationen (Skalarprodukten). Eine reguläre SSE Implementierung erfordert da shuffling. Es ist viel effizienter wenn man Algorithmus und Datenstruktur so auslegt dass man nicht ein Skalarprodukt berechnet (dabei gewinnt man praktisch nur dass die Multiplikation der Vektorkomponenten parallelisiert wird) sondern besser 4 Skalarprodukte parallel.