什么是CMOV提高CPU流水线性能?

use*_*112 10 x86 assembly branch cpu-architecture

我理解当分支很容易预测时,使用IF语句会更好,因为分支是完全免费的.我已经了解到,如果不容易预测分支,那么CMOV会更好.但是,我不太明白这是如何实现的?

当然问题域仍然是相同的 - 我们不知道下一条指令的执行地址?因此,我不明白管道的所有方式,当CMOV执行时,如何帮助指令获取器(过去10个CPU周期)选择正确的路径并防止管道停顿?

有人可以帮我理解CMOV如何改进分支?

小智 9

CMOV指令不指导控制流的路径.它们是为了基于条件代码(即谓词指令)计算结果而执行的指令.某些体系结构(如ARM)可以基于条件代码来预测多种形式的指令,但x86只能执行"mov",即条件移动(CMOV).这些被解码,并且以等待时间执行以便确定指令的结果.

另一方面,分支被预测并实际上指导执行指令.分支预测器"向前看"指令"fetcher",特别是寻找分支指令,并通过引导流来预测路径.想象一下铁路轨道,前方人员向左或向右移动轨道,告诉火车去哪里.现在如果那个人选择了错误的方向,火车必须停下来,备份,然后再朝正确的方向移动.浪费了很多时间.

另一方面,CMOV不会引导流动.它们只是指令需要额外的时间(并创建额外的依赖关系),以根据条件代码确定移动的正确结果.想想火车,而不是决定左转或右转,采取直线路径,不需要转弯,但有点慢(显然更复杂,但它是我现在能想到的最好的).

CMOV曾经非常糟糕(非常高的延迟),但后来改进得相当快,使它们更加可用和性能更高.

希望这可以帮助..

  • 很好的答案,尽管我希望cmov的火车示例可以包括以某种方式在铁路之间拆分小车,其中一个小车最终跌入深渊(显然也必须有屋顶战斗场景) (2认同)

zx4*_*485 6

有人可以帮我理解CMOV如何改进分支?

嗯,它不会改善分支,它会删除它.CMOV可以被视为一个中的两个指令,MOV和NOP.执行哪一个取决于标志.所以内部可能看起来像

if (cond) {
    mov dst, src
} else {
    nop
}
Run Code Online (Sandbox Code Playgroud)

...

当然问题域仍然是相同的 - 我们不知道下一条指令的执行地址?

好吧,不.下一条指令始终是CMOV之后的指令,因此指令流水线不会失效并重新加载(分支预测和其他优化保留在一边).它是宏观操作的一个连续流程.一个简单的例子如下

if (ecx==5)
    eax = TRUE
else
    eax = FALSE
Run Code Online (Sandbox Code Playgroud)

在基本的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
Run Code Online (Sandbox Code Playgroud)

与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
Run Code Online (Sandbox Code Playgroud)

在当前的CPU上是否值得?一个明确的是.根据我的经验和(当然)取决于算法,速度增益是重要的并且值得付出努力.

  • `cmove` 不允许立即操作数。所以你需要破坏一个寄存器:`mov ebx, TRUE` 然后是`cmove eax, ebx`。 (2认同)
  • 或者,在本例中为“sete”。 (2认同)