Hes*_*sLg 2 c++ precision x86 assembly numerical-methods
#include <immintrin.h>
__m256 mult(__m256 num) {
return 278*num/(num+1400);
}
Run Code Online (Sandbox Code Playgroud)
.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
Run Code Online (Sandbox Code Playgroud)
为什么 Clang 在代码中添加了两条额外的 FMA 指令?结果应该已经用 计算出来vmulps ymm3, ymm1, ymm2。vdivps除了使用like with之外,额外的指令是否会增加延迟-O3?
额外的 FMA 可以补偿降低的精度vrcpps。ymm3是结果的估计,但精度约为通常精度的一半。
为了简单起见,我们假设除法是q = a / b。
第一个 FMAvfmsub213ps计算差值(a * b\xe2\x81\xbb\xc2\xb9) * b - a,这是对除法“偏离”程度的估计(在除以 之前的原始比例中b)。第二个 FMA 将该差值近似除以b(乘以b\xe2\x81\xbb\xc2\xb9),使其成为 的标度差q,并从中减去它q以使其更接近a / b。
如果您可以接受降低的精度,则可以显式地使用_mm256_rcp_ps并乘以该精度,然后就不会需要额外的 FMA 来补偿。
\n\n除了使用之外,额外的指令是否会增加延迟
\nvdivps
是的,这个 4 指令序列在 Ice Lake 上需要 16 个周期,而在 Ice Lake 上则vdivps需要 11 个周期。然而,与 相比,吞吐量大约增加了一倍vdivps。根据上下文,延迟或吞吐量可能更重要……更常见的是吞吐量。编译器不一定很擅长决定哪个更重要,尽管在这种情况下我不能责怪它(没有上下文)。
| 归档时间: |
|
| 查看次数: |
132 次 |
| 最近记录: |