使用 GCC 5.3 可以编译以下代码-O3 -fma
float mul_add(float a, float b, float c) {
return a*b + c;
}
产生以下程序集
vfmadd132ss %xmm1, %xmm2, %xmm0
ret
我注意到海湾合作委员会这样做-O3已经在 GCC 4.8 中 https://stackoverflow.com/a/21650876/2542702.
铿锵 3.7 与-O3 -mfma
产生
vmulss %xmm1, %xmm0, %xmm0
vaddss %xmm2, %xmm0, %xmm0
retq
但 Clang 3.7 带有-Ofast -mfma
生成与 GCC 相同的代码-O3 fast
.
我很惊讶 GCC 这样做-O3
因为从这个答案 https://stackoverflow.com/a/15933677/2542702 it says
除非允许宽松的浮点模型,否则不允许编译器融合单独的加法和乘法。
这是因为 FMA 只有一次舍入,而 ADD + MUL 有两次舍入。因此编译器将通过融合违反严格的 IEEE 浮点行为。
然而,从这个链接 http://en.cppreference.com/w/c/types/limits/FLT_EVAL_METHOD it says
无论 FLT_EVAL_METHOD 的值如何,任何浮点表达式都可以收缩,即计算时就好像所有中间结果都具有无限范围和精度。
所以现在我很困惑也很担心。
- GCC 使用 FMA 是否合理
-O3
?
- 熔断是否违反严格的 IEEE 浮点行为?
- 如果熔断确实违反了 IEEE 浮点行为并且因为海湾合作委员会回报__STDC_IEC_559__ https://stackoverflow.com/questions/31181897/status-of-stdc-iec-559-with-modern-c-compilers这不是矛盾吗?
自 FMA可以在软件中模拟 https://stackoverflow.com/questions/28630864/how-is-fma-implemented/30121217#30121217似乎应该有两个针对 FMA 的编译器开关:一个告诉编译器在计算中使用 FMA,另一个告诉编译器硬件具有 FMA。
显然这可以通过选项来控制-ffp-contract
。对于 GCC,默认值是-ffp-contract=fast
而 Clang 则不然。其他选项例如-ffp-contract=on
and -ffp-contract=off
不产生FMA指令。
例如 Clang 3.7 与-O3 -mfma -ffp-contract=fast
产生vfmadd132ss
.
我检查了一些排列#pragma STDC FP_CONTRACT
set to ON
and OFF
with -ffp-contract
set to on
, off
, and fast
。在所有情况下我也使用-O3 -mfma
.
对于 GCC,答案很简单。#pragma STDC FP_CONTRACT
ON 或 OFF 没有区别。仅有的-ffp-contract
很重要。
它使用的海湾合作委员会fma
with
-
-ffp-contract=fast
(默认)。
与 Clang 一起使用fma
- with
-ffp-contract=fast
.
- with
-ffp-contract=on
(默认)和#pragma STDC FP_CONTRACT ON
(默认为OFF
).
换句话说,使用 Clang 你可以得到fma
with #pragma STDC FP_CONTRACT ON
(since -ffp-contract=on
是默认值)或与-ffp-contract=fast
. -ffast-math
(因此-Ofast
) set -ffp-contract=fast
.
我研究了 MSVC 和 ICC。
对于 MSVC,它使用 fma 指令/O2 /arch:AVX2 /fp:fast
。与 MSVC/fp:precise
是默认值。
对于 ICC,它使用 fma-O3 -march=core-avx2
(实际上-O1
足够了)。这是因为默认情况下 ICC 使用-fp-model fast
。但 ICC 即使使用 fma-fp-model precise
。使用 ICC 禁用 fma-fp-model strict
or -no-fma
.
因此,默认情况下,当启用 fma 时,GCC 和 ICC 使用 fma(使用-mfma
对于 GCC/Clang 或-march=core-avx2
与 ICC),但 Clang 和 MSVC 没有。