【问题标题】:What is it about CMOV which improves CPU pipeline performance?提高 CPU 流水线性能的 CMOV 是什么?
【发布时间】:2015-01-24 01:28:29
【问题描述】:

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

问题域肯定还是一样——我们不知道下一条要执行的指令的地址?所以我不明白在执行 CMOV 时,如何在管道的整个过程中帮助指令提取器(过去 10 个 CPU 周期)选择正确的路径并防止管道停止?

有人可以帮助我了解 CMOV 如何改进分支吗?

【问题讨论】:

  • 我们如何“不知道要执行的下一条指令的地址”?如果指令序列为I1; CMOV; I3,则执行指令I1,然后是CMOV,然后是I3,始终按此顺序执行。在I1 之后的是CMOV。在CMOV 之后的是I3
  • 单指令长分支是一种非常特殊的情况;它适用于通用分支不承认的优化。
  • 另外,您可以将 CMOV 视为根本不是一个分支,而是一个具有Dest = (Dest AND NOT Condition) OR (Source AND Condition) 效果的命令,其中 Source、Dest 和 Condition 是位。
  • Seva 的解释比任何一个答案都好得多。它是数据依赖而不是控制依赖。它有 3 个输入(dest、src 和 flags),并产生一个输出(dest)。对于 OOO 管道,可以完全像 adc 一样跟踪它(具有相同的三个输入和一个输出)。

标签: assembly x86 branch cpu-architecture


【解决方案1】:

CMOV 指令不指导控制流的路径。它们是执行以根据条件代码计算结果的指令,即谓词指令。一些架构(如ARM)可以根据条件码断言多种形式的指令,但x86只能做“mov”,即条件移动(CMOV)。这些被解码并延迟执行以确定指令的结果。

另一方面,分支被预测并实际控制指令的执行。分支预测器“向前看”指令“提取器”,专门寻找分支指令,并通过引导流程来预测路径。想象一条铁轨,前面的人将铁轨向左或向右移动,以告诉火车去哪里。现在,如果那个人选错了方向,火车必须停下来,倒车,然后再朝正确的方向移动。浪费了很多时间。

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

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

希望这会有所帮助..

【讨论】:

  • 很好的答案,虽然我希望 cmov 的火车示例可以包括以某种方式在铁路之间拆分手推车,其中一个最终坠入深渊(显然必须有屋顶打斗场景太)
  • 根据我的测试,在某些情况下,短跳转(1-4 条指令)最终会更快。
【解决方案2】:

有人可以帮助我了解 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
  • 没错。或者,如果您没有备用寄存器,请使用 ddTRUE 之类的变量。
  • 或者,在这种特殊情况下,sete
猜你喜欢
  • 2012-03-22
  • 1970-01-01
  • 1970-01-01
  • 2016-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多