Ich verstehe gcc's --ffast-math
Flag von Geschwindigkeit für Float-Ops erheblich erhöhen kann und außerhalb der IEEE-Standards liegt, aber ich kann anscheinend keine Informationen darüber finden, was wirklich passiert, wenn es eingeschaltet ist. Kann jemand bitte einige Details erklären und vielleicht ein klares Beispiel dafür geben, wie sich etwas ändern würde, wenn die Flagge ein- oder ausgeschaltet wäre?
Ich habe versucht, SO nach ähnlichen Fragen zu durchsuchen, konnte aber nichts finden, was die Funktionsweise von ffast-math erklärt.
double
, variiert jedoch je nach Anwendung). Eine Sache, die zu beachten ist, ist, dass ffast-math-Optimierungen nicht unbedingt "mehr" Abrundungen hinzufügen. Der einzige Grund, warum es nicht IEEE-konform ist, ist, dass die Antwort (wenn auch geringfügig) von der geschriebenen abweicht.x
kleiner als 10 ist, ist der Fehler in Mysticals Beispiel um 10 ^ -10 gesunken. Aber wenn jax = 10e20
, wird der Fehler wahrscheinlich viele Millionen betragen.-fassociative-math
dem in inbegriffen-funsafe-math-optimizations
denen wiederum sind mit-ffast-math
Warum nicht GCC optimizea*a*a*a*a*a
zu(a*a*a)*(a*a*a)
?-ffast-math
macht viel mehr als nur die strikte IEEE-Konformität zu brechen.Zuallererst verstößt es natürlich gegen die strikte IEEE-Konformität, was beispielsweise die Neuordnung von Anweisungen zu etwas ermöglicht, das mathematisch (idealerweise) aber im Gleitkomma nicht genau gleich ist.
Zweitens wird die Einstellung
errno
nach mathematischen Funktionen mit einem Befehl deaktiviert , was bedeutet, dass ein Schreiben in eine threadlokale Variable vermieden wird (dies kann bei einigen Architekturen einen 100% igen Unterschied für diese Funktionen bewirken).Drittens wird davon ausgegangen, dass die gesamte Mathematik endlich ist , was bedeutet, dass keine Überprüfungen auf NaN (oder Null) durchgeführt werden, an denen sie nachteilige Auswirkungen haben würden. Es wird einfach angenommen, dass dies nicht passieren wird.
Viertens ermöglicht es reziproke Approximationen für Division und reziproke Quadratwurzel.
Außerdem wird die vorzeichenbehaftete Null deaktiviert (Code geht davon aus, dass die vorzeichenbehaftete Null nicht vorhanden ist, auch wenn das Ziel dies unterstützt) und die Rundungsmathematik, die unter anderem eine konstante Faltung zur Kompilierungszeit ermöglicht.
Last, es Code generiert, aufgrund Signalisierung / Trapping math passieren kann keine Hardware - Interrupts geht davon aus, dass (das heißt, wenn diese nicht deaktiviert auf der Zielarchitektur sein kann und folglich passieren kann , werden sie nicht behandelt werden).
quelle
-ffast-math
Setzt -fno-math-errno, -funsafe-math-Optimierungen, -ffinite-math-only, -fno-rounding-math, -fno-Signaling -nans und -fcx-Limited-Range. Diese Option bewirkt, dass das Präprozessor-Makro FAST_MATH definiert wird. "und etwas von glibc, wie (in dermath.h
Nähe von math_errhandling)" Standardmäßig unterstützen alle Funktionen sowohl die Fehler- als auch die Ausnahmebehandlung. Im schnellen Mathematikmodus von und Wenn Inline-Funktionen definiert sind, ist dies möglicherweise nicht der Fall. "-ffast-math
ermöglicht es dem Compiler, einige Ecken zu kürzen und einige Versprechen zu brechen (wie erklärt), was im Allgemeinen als solches nicht gefährlich und für die meisten Menschen kein Problem darstellt. Für die meisten Menschen ist es das gleiche, nur schneller. Wenn Ihr Code diese Versprechen jedoch annimmt und sich darauf verlässt , verhält sich Ihr Code möglicherweise anders als erwartet. Normalerweise bedeutet dies , dass das Programm scheint zu funktionieren, vor allem, aber einige Ergebnisse können „unerwartete“ (sagen wir, in einer Physik - Simulation, zwei Objekte möglicherweise nicht kollidieren richtig).-O2
Aktiviert im Allgemeinen "jede" rechtliche Optimierung, mit Ausnahme derjenigen, die Größe gegen Geschwindigkeit tauschen.-O3
ermöglicht auch Optimierungen, bei denen Größe gegen Geschwindigkeit getauscht wird. Es behält immer noch 100% Korrektheit bei.-ffast-math
Versuche, mathematische Operationen schneller zu machen, indem "leicht falsches" Verhalten zugelassen wird, das normalerweise nicht schädlich ist, aber vom Wortlaut der Norm als falsch angesehen wird. Wenn Ihr Code auf zwei Compilern tatsächlich sehr unterschiedlich schnell ist (nicht nur 1-2%), überprüfen Sie, ob Ihr Code streng standardkonform ist und ...#pragma omp parallel for
und innerhalb des Schleifenkörpers lesen und schreiben Sie an Adressen, auf die durch Funktionsargumente verwiesen wird, und führen eine nicht triviale Verzweigung durch. Als ungebildete Vermutung könnten Sie Caches aus Ihrem implementierungsdefinierten Aufruf von Threads heraus verprügeln, und MSVC vermeidet möglicherweise fälschlicherweise Zwischenspeicher, für die Aliasing-Regeln vorgeschrieben wären. Unmöglich zu sagen.