在Intel和AMD x86_64处理器上,SIMD矢量化寄存器具有特定的融合乘法加法功能,但是通用(标量,整数)寄存器don't - 你基本上需要乘法,然后加上(除非你能把东西装进lea
)。
为什么?我的意思是,这是无用的,以至于不值得开销吗?
答案 0 :(得分:10)
整数乘法是常见的,但不是与整数有关的大多数常见事项之一。但是对于浮点数,总是使用乘法和加法,并且FMA为许多ALU绑定的FP代码提供主要加速。
此外,浮点实际上避免了使用FMA的精度损失(x*y
内部临时在添加之前完全没有舍入)。这就是the ISO C99 / C++ fma()
math library function存在的原因,以及为什么在没有硬件FMA支持的情况下实施起来很慢。
整数FMA(或乘法累加,又称MAC)与单独的乘法和加法相比,没有任何精确的好处。
某些非x86 ISA确实提供整数FMA。它没有用处,但英特尔和AMD都不愿意将它包括在内until AVX512-IFMA(而且这仍然只适用于SIMD,基本上暴露了52位的尾数乘法器电路,双精度FMA / vmulpd
供整数指令使用。)
非x86示例包括:
MIPS32,madd
/ maddu
(无符号)乘以累加到hi
/ lo
寄存器(用作特殊寄存器)通过常规乘法和除法指令的目的地。)
ARM smlal
和朋友(32x32 => 64位MAC,或16x16 => 32位),也可用于无符号整数。操作数是常规的R0..R15通用寄存器。
整数寄存器FMA在x86上很有用,但是有3个整数输入的uops很少。 CMOV和ADC有3个输入,但其中一个是标志。即便如此,在为Haswell的FP FMA添加3输入uop支持之后,他们还没有解决到Intel上的单个uop,直到Broadwell。
Haswell后来可以使用3个整数输入跟踪融合域uops for (some) micro-fused instructions with indexed addressing modes。 Sandybridge / Ivybridge解除了add eax, [rdx+rcx]
之类的指示。 (但Nehalem可以让它们像Haswell一样保持微融合; SnB简化了融合域uop格式)。无论如何,这是融合的域,而不是调度程序。只有Broadwell / Skylake可以在调度程序中跟踪3输入整数uop,并且只能用于2个整数+标志,而不是3个整数寄存器。
英特尔确实使用了统一的"调度程序,FP和整数运算使用相同的调度程序,它可以跟踪正确的3输入FP FMA。 IDK是否存在技术障碍。如果没有,IDK为什么英特尔没有将整数FMA作为BMI2的一部分包括在内,它增加了东西like mulx
(2输入2输出mul
,主要是显式操作数,与遗留{{ 1}}使用mul
。)
SSE2 / SSSE3 确实具有向量寄存器的整数mul-add指令,但在加宽16x16 =>之后只有水平加法。 32位(SSE2 pmaddwd
)或(无符号)8x(带符号)8 => 16位(SSSE3 pmaddubsw
)。
但这些只是2输入指令,所以即使有乘法和加法,它也与FMA非常不同。
脚注:问题标题最初表示没有FMA"对于标量"。标量FP FMA具有相同的FMA3扩展,添加了这些的打包版本:VFMADD231SD
和朋友以标量双精度操作,并且相同风格的vfmaddXXXss可用于XMM寄存器中的标量浮点数。