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