mit GCC 5.3 der folgende Code mit compield -O3 -fma
Fused multiply hinzufügen und Standard Rundungsmodi
float mul_add(float a, float b, float c) {
return a*b + c;
}
erzeugt die folgende Montage
vfmadd132ss %xmm1, %xmm2, %xmm0
ret
I noticed GCC doing this with -O3
already in GCC 4.8.
Clang 3.7 mit -O3 -mfma
produziert
vmulss %xmm1, %xmm0, %xmm0
vaddss %xmm2, %xmm0, %xmm0
retq
aber Clang 3.7 mit -Ofast -mfma
mit -O3 fast
den gleichen Code wie GCC produziert.
Ich bin überrascht, dass GCC mit -O3
tut, weil von this answer sagt es
Der Compiler ist nicht erlaubt eine getrennte Zusatz zu verschmelzen und sich vermehren, wenn Sie für einen entspannten Modell Gleitkommazahlen ermöglichen.
Dies ist, weil ein FMA nur eine Rundung hat, während ein ADD + MUL zwei hat. Der Compiler wird also das strikte IEEE-Fließkomma-Verhalten durch Verschmelzen verletzen.
jedoch aus this link sagt
Unabhängig von dem Wert von FLT_EVAL_METHOD jede Gleitkommaausdruck kontrahiert werden kann, das heißt, berechnet, als ob alle Zwischenergebnisse unendlichen Bereich und Präzision aufweisen.
So jetzt bin ich verwirrt und besorgt.
- Ist GCC gerechtfertigt in der Verwendung von FMA mit
-O3
? - Verletzt die Fusion das strikte IEEE-Fließkommaverhalten?
- Wenn Fusing IEEE Fließkommazahl verletzt und GCC returns
__STDC_IEC_559__
ist dies nicht ein Widerspruch?
Da FMA can be emulated in software es scheint, dort zu sein, sollten zwei Compiler-Schalter für FMA sein: man den Compiler sagen FMA in Berechnungen verwendet werden und man den Compiler zu sagen, dass die Hardware FMA hat.
apprently kann dies mit der Option -ffp-contract
gesteuert werden. Mit GCC ist der Standard -ffp-contract=fast
und mit Clang ist es nicht. Andere Optionen wie -ffp-contract=on
und -ffp-contract=off
erzeugen keine FMA-Anweisung. Beispiel: Clang 3.7 mit -O3 -mfma -ffp-contract=fast
produziert vfmadd132ss
.
Ich habe einige Permutationen von #pragma STDC FP_CONTRACT
Set ON
und OFF
mit -ffp-contract
Set on
, off
und fast
.In allen Fällen habe ich auch -O3 -mfma
verwendet.
Mit GCC ist die Antwort einfach. #pragma STDC FP_CONTRACT
ON oder OFF macht keinen Unterschied. Nur -ffp-contract
zählt.
GCC verwendet es fma
mit
-ffp-contract=fast
(Standard).
mit Clang verwendet es fma
- mit
-ffp-contract=fast
. - mit
-ffp-contract=on
(Standard) und#pragma STDC FP_CONTRACT ON
(Standard istOFF
).
Mit anderen Worten mit Clang können Sie fma
mit #pragma STDC FP_CONTRACT ON
bekommen oder mit -ffp-contract=fast
(seit -ffp-contract=on
der Standard ist). -ffast-math
(und damit -Ofast
) Set -ffp-contract=fast
.
Ich schaute in MSVC und ICC.
Mit MSVC verwendet es die Fma-Anweisung mit /O2 /arch:AVX2 /fp:fast
. Mit MSVC /fp:precise
ist der Standardwert.
Mit ICC verwendet es fma mit -O3 -march=core-avx2
(actually -O1
ist ausreichend). Dies liegt daran, dass ICC standardmäßig -fp-model fast
verwendet. Aber ICC verwendet fma sogar mit -fp-model precise
. Um FMA mit ICC zu deaktivieren, verwenden Sie oder .
Standardmäßig verwenden GCC und ICC fma, wenn fma aktiviert ist (mit -mfma
für GCC/Clang oder -march=core-avx2
mit ICC), aber Clang und MSVC nicht.
Könnte ein Compiler-Fehler sein. Überlegen Sie, es zu melden. – fuz
Ich bin mir ziemlich sicher, was GCC macht, ist in Ordnung. Nachdem ich den FLT_EVAL_METHOD-Doc über Contracting-FP-Ausdrücke gelesen habe, bin ich überrascht, dass 'clang' * das nicht tut. Ich poste das nicht als Antwort, da es nicht auf einer echten Standarddokumentation basiert, nur mein Verständnis davon, wie * ich * denke, dass die Dinge angesichts des Materials in der Frage funktionieren sollten/sollten. –
@FUZxxl, meinst du, das Gleitkomma-Tag wäre passender als ieee-754? (Wenn es so ist, kannst du es ändern). Ich denke, ich sollte auch das Fließkomma-Tag verwenden. –