Mar*_*aux 72 optimization performance assembly cpu-architecture branch-prediction
在阅读了这篇文章后(在StackOverflow上回答)(在优化部分),我想知道为什么条件移动不容易受到分支预测失败的影响.我在一篇关于cond移动的文章中找到了(PDF由AMD提供).在那里,他们声称cond的性能优势.移动.但为什么会这样呢?我没有看到它.在评估ASM指令的时刻,前面的CMP指令的结果尚未知晓.
谢谢.
Pas*_*uoq 62
如果事情进展顺利,现代处理器通常在每个周期执行一到三个指令(如果它没有停止等待这些指令的数据依赖性从先前的指令或从存储器到达).
上面的语句对于紧密循环来说非常好,但是这不应该让你失去一个额外的依赖,它可以阻止在循环到来时执行指令:对于要执行的指令,处理器必须已经开始获取和解码之前15-20个周期.
处理器遇到分支时应该怎么做?获取和解码两个目标都不会扩展(如果跟随更多分支,则必须并行获取指数数量的路径).因此处理器只推测性地获取和解码两个分支中的一个.
这就是为什么错误预测的分支是昂贵的:它们花费了15-20个周期,由于有效的指令管道,它们通常是不可见的.
条件移动不需要预测,因此它永远不会有这种惩罚.它具有数据依赖性,与普通指令相同.实际上,条件移动比普通指令具有更多的数据依赖性,因为数据依赖性包括"条件真实"和"条件错误"情况.在有条件地移动r1到的指令之后r2,内容r2似乎依赖于之前r2和之前的值r1.良好预测的条件分支允许处理器推断出更准确的依赖性.但是,如果需要时间到达,数据依赖性通常需要一到两个周期才能到达.
请注意,从内存到寄存器的条件移动有时会是一个危险的赌注:如果条件是从内存中读取的值未分配给寄存器,则您等待内存什么都不做.但是指令集中提供的条件移动指令通常是寄存器来注册,防止程序员的这个错误.
Mar*_*tin 44
这都是关于指令管道的.请记住,现代CPU在管道中运行其指令,当CPU可以预测执行流程时,这会显着提高性能.
add eax, ebx
cmp eax, 0x10
cmovne ebx, ecx
add eax, ecx
Run Code Online (Sandbox Code Playgroud)
在评估ASM指令的时刻,前面的CMP指令的结果尚未知晓.
也许,但CPU仍然知道后面的指令cmov将被执行,而不管cmp和cmov指令的结果如何.因此可以提前安全地提取/解码下一条指令,而分支不是这种情况.
下一条指令甚至可以在执行之前执行cmov(在我的示例中,这将是安全的)
add eax, ebx
cmp eax, 0x10
je .skip
mov ebx, ecx
.skip:
add eax, ecx
Run Code Online (Sandbox Code Playgroud)
在这种情况下,当CPU的解码器看到je .skip它必须选择是继续预取/解码指令1)来自下一条指令,还是2)来自跳转目标.CPU将猜测此前向条件分支不会发生,因此下一条指令mov ebx, ecx将进入管道.
几个周期之后,je .skip执行并执行分支.哦,废话!我们的管道现在拥有一些永远不应该执行的随机垃圾.CPU必须刷新所有缓存的指令并重新开始.skip:.
这是错误预测的分支的性能损失,cmov因为它不会改变执行流程,所以它永远不会发生.
Jes*_*ter 17
实际上结果可能还不知道,但如果其他情况允许(特别是依赖链),则cpu可以重新排序并执行后面的指令cmov.由于不涉及分支,因此无论如何都需要评估这些指令.
考虑这个例子:
cmoveq edx, eax
add ecx, ebx
mov eax, [ecx]
Run Code Online (Sandbox Code Playgroud)
后面的两条指令cmov不依赖于结果cmov,因此即使在cmov本身处于挂起状态时也可以执行它们(这称为乱序执行).即使它们无法执行,它们仍然可以被提取和解码.
分支版本可以是:
jne skip
mov edx, eax
skip:
add ecx, ebx
mov eax, [ecx]
Run Code Online (Sandbox Code Playgroud)
这里的问题是控制流正在改变,并且cpu不够聪明,以至于mov如果分支被错误预测为可能只是"插入"跳过的指令 - 而是它抛弃了它在分支之后所做的一切,并重新启动从头开始.这是罚款的来源.
你应该阅读这些。使用Fog+Intel,只需搜索CMOV。
\n\nLinus Torvald 在 2007 年左右对 CMOV 的批评
\n Agner Fog 对微架构的比较
\n Intel\xc2\xae 64 和 IA-32 架构优化参考手册
简而言之,正确的预测是“免费的”,而条件分支错误预测可能会在 Haswell 上花费 14-20 个周期。然而,CMOV 从来都不是免费的。尽管如此,我仍然认为 CMOV 现在比托瓦兹咆哮时要好得多。没有一个答案能够在所有处理器上始终正确。
\n