我明白当一个分支很容易预测时,最好使用IF语句,因为该分支是完全自由的。我已经学到了如果该分支不容易预测,那么CMOV更好。然而,我不太明白这是如何实现的?
显然,问题域仍然是相同的-我们不知道要执行的下一条指令的地址吗?所以我不明白从流水线的最深处开始运行CMOV时,如何帮助指令提取器(在过去10个CPU周期)选择正确的路径并防止流水线停顿?
请问有人能帮我理解CMOV如何改善分支吗?
我明白当一个分支很容易预测时,最好使用IF语句,因为该分支是完全自由的。我已经学到了如果该分支不容易预测,那么CMOV更好。然而,我不太明白这是如何实现的?
显然,问题域仍然是相同的-我们不知道要执行的下一条指令的地址吗?所以我不明白从流水线的最深处开始运行CMOV时,如何帮助指令提取器(在过去10个CPU周期)选择正确的路径并防止流水线停顿?
请问有人能帮我理解CMOV如何改善分支吗?
请问有人能帮我理解CMOV如何改善分支吗?
实际上,它并不是改善分支,而是消除分支。CMOV可以被视为两个指令的组合,即MOV和NOP。哪一个指令被执行取决于标志位。因此,在内部它看起来可能像这样:
if (cond) {
mov dst, src
} else {
nop
}
问题域仍然相同-我们不知道要执行的下一条指令的地址吗?
嗯,不是这样的。下一条指令总是跟随CMOV的指令,因此指令流水线不会被无效化和重新加载(忽略分支预测和其他优化)。它是一连续的宏操作码流。以下是一个简单的例子
if (ecx==5)
eax = TRUE
else
eax = FALSE
在基本汇编中:
cmp ecx,5 ; is ecx==5
jne unequal ; what is the address of the next instruction? conditional branch
mov eax,TRUE ; possibility one
jmp fin
unequal: : possibility two
mov eax,FALSE
fin:
nop
使用CMOV
cmp ecx,5
mov eax, FALSE ; mov doesn't affect flags
mov ebx, TRUE ; because CMOV doesn't take immediate src operands, use EBX for alternative
cmove eax, ebx ; executes as MOV if zero-flag is set, otherwise as NOP
nop ; always the next instruction, no pipeline stall
在当前的CPU上是否值得使用?明确的答案是肯定的。根据我的经验和(当然)算法的不同,速度提升是显著的,值得付出努力。
cmove
不允许立即操作数。因此,您需要清除一个寄存器:mov ebx, TRUE
然后cmove eax, ebx
。 - Björn Lindqvistsete
。 - alecovCMOV指令不直接控制程序流。它们是基于条件码执行的指令,用于计算结果,也就是被谓词化的指令。一些体系结构(如ARM)可以根据条件码谓词许多形式的指令,但x86只能使用"mov",即有条件移动(CMOV)。这些指令需要解码并在执行时延迟以确定指令的结果。
另一方面,分支则是预测和实际导向指令执行的。分支预测器“向前看”,专门查找分支指令,并通过导向控制流来预测路径。类比铁路轨道上的人员会将铁轨向左或向右移动,以告诉列车该往哪里走。如果那个人选择了错误的方向,列车就必须停下来、倒车,然后再朝正确的方向行驶。浪费大量时间。
与此不同,CMOV并未引导流程。它们只是简单的指令,需要额外的时间(并创建附加依赖项),以根据条件码来确定移动的正确结果。类比列车不决定向左还是向右走,而是沿着一条不需要拐弯的直路前进,但速度较慢(显然更为复杂,但这是我现在想到的最好的比喻)。
CMOV曾经效率非常低(延迟很高),但现在已经得到改进,变得相当快,使它们更加实用和高性能。
希望这有所帮助。
I1; CMOV; I3
,那么指令I1
,然后是CMOV
,最后是I3
被依次执行,总是按照这个顺序。跟在I1
之后的是CMOV
。跟在CMOV
之后的是I3
。 - Pascal CuoqDest = (Dest AND NOT Condition) OR (Source AND Condition)
,其中Source、Dest和Condition都是位。 - Seva Alekseyevadc
一样精确追踪(adc
也具有相同的三个输入和一个输出)。 - Peter Cordes