我理解当分支很容易预测时,使用IF语句会更好,因为分支是完全免费的。我已经了解到,如果不容易预测分支,那么CMOV会更好。但是,我不太明白这是如何实现的?
问题域肯定是一样的 - 我们不知道下一条指令的执行地址?所以我不明白管道的所有方式,当CMOV执行时,它如何帮助指令获取器(过去10个CPU周期)选择正确的路径并防止管道停滞?
有人可以帮我理解CMOV如何改进分支?
答案 0 :(得分:8)
CMOV指令不指导控制流的路径。它们是被执行以基于条件代码(即,预测指令)计算结果的指令。某些体系结构(如ARM)可以基于条件代码来预测多种形式的指令,但x86只能执行“mov”,即条件移动(CMOV)。这些被解码,并以延迟执行,以确定指令的结果。
另一方面,分支机构被预测并实际上指导执行指令。分支预测器“向前看”指令“fetcher”,特别是寻找分支指令,并通过引导流来预测路径。想象一下铁路轨道,前方人员向左或向右移动轨道,告诉火车去哪里。现在,如果这个人选择了错误的方向,火车必须停下来,备份,然后再朝正确的方向移动。浪费了很多时间。 另一方面,CMOV不会引导流动。它们只是指令需要额外的时间(并创建额外的依赖关系),以根据条件代码确定移动的正确结果。想想火车,而不是决定左转或右转,采取直线路径,不需要转弯,但有点慢(显然更复杂,但它是我现在能想到的最好的)。 CMOV曾经非常糟糕(非常高的延迟),但后来改进得非常快,使它们更具可用性和性能。希望这会有所帮助..
答案 1 :(得分:6)
有人可以帮我理解CMOV如何改进分支?
嗯,它不会改善分支,它会删除它。 CMOV可以被视为一个中的两个指令,MOV和NOP。执行哪一个取决于标志。所以内部可能看起来像
if (cond) {
mov dst, src
} else {
nop
}
...
问题域肯定是一样的 - 我们不知道下一条指令的执行地址?
嗯,不。下一条指令始终是CMOV之后的指令,因此指令流水线不会失效并重新加载(分支预测和其他优化保留在一边)。它是宏观操作的一个连续流程。
就是一个简单的例子if (ecx==5)
eax = TRUE
else
eax = FALSE
在基本的asm中:
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上是否值得?一个明确的是。根据我的经验和(当然)取决于算法,速度增益是重要的,值得努力。