提问人:HesLg 提问时间:6/24/2022 更新时间:6/24/2022 访问量:122
为什么 Clang 会添加额外的 FMA 指令?
Why does Clang add extra FMA instructions?
问:
#include <immintrin.h>
__m256 mult(__m256 num) {
return 278*num/(num+1400);
}
.LCPI0_0:
.long 0x438b0000 # float 278
.LCPI0_1:
.long 0x44af0000 # float 1400
mult(float __vector(8)): # @mult(float __vector(8))
vbroadcastss ymm1, dword ptr [rip + .LCPI0_0] # ymm1 = [2.78E+2,2.78E+2,2.78E+2,2.78E+2,2.78E+2,2.78E+2,2.78E+2,2.78E+2]
vmulps ymm1, ymm0, ymm1
vbroadcastss ymm2, dword ptr [rip + .LCPI0_1] # ymm2 = [1.4E+3,1.4E+3,1.4E+3,1.4E+3,1.4E+3,1.4E+3,1.4E+3,1.4E+3]
vaddps ymm0, ymm0, ymm2
vrcpps ymm2, ymm0
vmulps ymm3, ymm1, ymm2
vfmsub213ps ymm0, ymm3, ymm1 # ymm0 = (ymm3 * ymm0) - ymm1
vfnmadd213ps ymm0, ymm2, ymm3 # ymm0 = -(ymm2 * ymm0) + ymm3
ret
为什么 Clang 要在代码中添加两个额外的 FMA 指令?结果应该已经用 计算了。额外的指令不会增加延迟,而不仅仅是使用 like with 吗?vmulps ymm3, ymm1, ymm2
vdivps
-O3
答:
7赞
harold
6/24/2022
#1
额外的 FMA 补偿了 的精度降低。 是结果的估计值,但精度约为通常精度的一半。vrcpps
ymm3
为简单起见,假设除法是 。q = a / b
第一个 FMA 计算差值,即对除法“偏离”的估计值(在原始比例中,除以之前)。第二个 FMA 将近似地将该差值除以(乘以 ),因此它成为 的刻度差值,然后减去它以使其更接近 。vfmsub213ps
(a * b⁻¹) * b - a
b
b
b⁻¹
q
q
a / b
如果您可以降低精度,则可以显式使用并乘以该精度,那么就不会有额外的 FMA 来补偿。_mm256_rcp_ps
除了使用之外,额外的指令不会增加延迟吗
vdivps
是的,这个 4 指令序列在 Ice Lake 上需要 16 个周期,而需要 11 个周期。但是,与 相比,吞吐量大约翻了一番。根据上下文,延迟或吞吐量可能更重要。更多时候是吞吐量。编译器不一定非常擅长决定哪个更重要,尽管在这种情况下我不能责怪它(没有上下文)。vdivps
vdivps
评论
-ffast-math
-Ofast
-O3 -ffast-math
vdivps
vdivps