gpt4 book ai didi

performance - x86_64 : is IMUL faster than 2x SHL + 2x ADD?

转载 作者:行者123 更新时间:2023-12-04 17:08:02 33 4
gpt4 key购买 nike

/O2(发行版)模式下查看Visual Studio(2015U2)生成的程序集时,我看到此“手动优化”的C代码片段已转换回乘法:

int64_t calc(int64_t a) {
return (a << 6) + (a << 16) - a;
}

集会:
  imul        rdx,qword ptr [a],1003Fh  

所以我想知道这是否真的比编写方式快,例如:
  mov         rbx,qword ptr [a]  
mov rax,rbx
shl rax,6
mov rcx,rbx
shl rcx,10h
add rax,rcx
sub rax,rbx

我总是觉得乘法总是慢于几个移位/加法?现代英特尔x86_64处理器不再是这种情况吗?

最佳答案

没错,现代x86 CPU(尤其是Intel)具有非常高的性能倍增器。imul r, r/mimul r, r/m, imm均为3个周期的延迟,即使对于64位操作数大小,在Intel SnB系列和AMD Ryzen上每1c吞吐量也需要1个周期。

在AMD Bulldozer系列中,延迟为4c或6c,每2c延迟一次或每4c吞吐量延迟一次。 (对于64位操作数大小,速度较慢)。

来自Agner Fog's instruction tables的数据。另请参见标签Wiki中的其他内容。

现代CPU中的晶体管预算非常庞大,并允许以如此低的延迟进行64位乘法所需的硬件并行度。 (It takes a lot of adders制作large fast multiplierHow modern X86 processors actually compute multiplications?)。

受功率预算(而不是晶体管预算)的限制,这意味着可以为许多不同功能使用专用硬件,只要它们不能全部同时开关即可(https://en.wikipedia.org/wiki/Dark_silicon)。例如您不能同时在Intel CPU上同时饱和pext/pdep单元,整数乘数和矢量FMA单元,因为它们中有许多都在同一执行端口上。

有趣的事实:imul r64也是3c,因此您可以在3个周期内获得完整的64 * 64 => 128b乘法结果。 imul r32是4c延迟和一个额外的uop。我的猜测是,额外的uop/周期会将64位结果从常规64位乘法器分成两个32位一半。

编译器通常针对延迟进行优化,并且通常不知道如何优化短的独立依赖链以实现吞吐量,而长延迟的依赖链则依赖长循环的依赖链。

gcc和clang3.8及更高版本最多使用两个LEA指令,而不是imul r, r/m, imm。我认为,如果替代方法是3条或更多指令(不包括imul),则gcc将使用mov

这是一个合理的调整选择,因为3条指令的dep链的长度与Intel上的imul相同。使用两个1周期指令会花费额外的时间,从而将等待时间缩短1个周期。

clang3.7和更早的版本倾向于imul,只需要一个LEA或移位的乘法器除外。因此,最近clang更改为优化延迟,而不是优化吞吐量以乘以小常数。 (或者也许是出于其他原因,例如不与仅与乘法器位于同一端口上的其他设备竞争。)

例如this code on the Godbolt compiler explorer:

int foo (int a) { return a * 63; }
# gcc 6.1 -O3 -march=haswell (and clang actually does the same here)
mov eax, edi # tmp91, a
sal eax, 6 # tmp91,
sub eax, edi # tmp92, a
ret

clang3.8和更高版本进行相同的代码。

关于performance - x86_64 : is IMUL faster than 2x SHL + 2x ADD?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37925143/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com