Ich bin auf ein seltsames Problem gestoßen. Ein Algorithmus, an dem ich arbeite, besteht aus vielen Berechnungen wie dieser
%Vor%wobei die Länge der Summe zwischen 4 und 7 liegt.
Die ursprünglichen Berechnungen werden alle mit 64-Bit-Genauigkeit durchgeführt. Zum Experimentieren habe ich versucht, 32-Bit-Genauigkeit für x, y, z-Eingabewerte zu verwenden (so dass Berechnungen mit 32-Bit ausgeführt werden) und das Endergebnis als 64-Bit-Wert zu speichern (direkte Umwandlung).
Ich habe erwartet, dass die 32-Bit-Leistung besser ist (Cachegröße, SIMD Größe usw.), aber für meine Überraschung gab es keinen Unterschied in der Leistung, vielleicht sogar abnehmen.
Die fragliche Architektur ist Intel 64, Linux und GCC . Beide Codes scheinen SSE zu verwenden, und Arrays sind in beiden Fällen auf 16-Byte-Grenze ausgerichtet.
Warum sollte es so sein? Meine Vermutung ist so weit, dass die 32-Bit-Genauigkeit SSE nur für die ersten vier Elemente verwenden kann, während der Rest seriell durch den Cast-Overhead ausgeführt wird.
Auf x87 wird alles intern in 80-Bit-Genauigkeit ausgeführt. Die Genauigkeit bestimmt nur, wie viele dieser Bits im Speicher gespeichert sind. Dies ist einer der Gründe, warum verschiedene Optimierungseinstellungen die Ergebnisse leicht ändern können: Sie ändern die Anzahl der Runden von 80-Bit auf 32- oder 64-Bit.
In der Praxis ist die Verwendung von 80-Bit Gleitkommawerten ( long double
in C und C ++, real
in D) normalerweise langsam, da es keine effiziente Möglichkeit gibt, 80 Bits aus dem Speicher zu laden und zu speichern. 32- und 64-Bit sind normalerweise gleich schnell, vorausgesetzt, dass die Speicherbandbreite nicht der Flaschenhals ist, d. H. Wenn sich sowieso alles im Cache befindet. 64-Bit kann langsamer sein, wenn einer der folgenden Fälle eintritt:
Soweit SIMD-Optimierungen gehen, sollte angemerkt werden, dass die meisten Compiler beim automatischen Vektorisieren von Code schrecklich sind. Wenn Sie nicht direkt in die Assemblersprache schreiben möchten, besteht die beste Möglichkeit, diese Anweisungen zu nutzen, darin, Dinge wie Array-artige Operationen zu verwenden, die beispielsweise in D verfügbar sind und in SSE-Anweisungen implementiert sind. Ähnlich, in C oder C ++, würden Sie wahrscheinlich eine High-Level-Bibliothek von Funktionen, die SSE-optimiert sind, verwenden wollen, obwohl ich nicht von einem guten von der Spitze meines Kopfes weiß, weil ich meist in D programmieren.
Überprüfen Sie zuerst das ASM, das produziert wird. Es kann nicht sein, was Sie erwarten.
Versuchen Sie es auch als Schleife zu schreiben:
%Vor%Einige Compiler könnten die Schleife und nicht das abgerollte Formular bemerken.
Schließlich verwendete Ihr Code ()
und nicht []
. Wenn Ihr Code viele Funktionsaufrufe (12 bis 21) ausführt, werden die FP-Kosten überflutet, und selbst das Entfernen der fp-Berechnung insgesamt wird keinen großen Unterschied machen. Inline-OTOH könnte.
Tags und Links performance floating-point precision