【问题标题】:Does a CMP+JE consume more clock cycles than a single MUL?CMP+JE 是否比单个 MUL 消耗更多时钟周期?
【发布时间】:2024-01-30 00:50:01
【问题描述】:

我正在运行 x86 处理器,但我相信我的问题很笼统。我很好奇 CMP + JE 序列与单个 MUL 操作所消耗的时钟周期的理论差异。

在 C 伪代码中:

unsigned foo = 1;    /* must be 0 or 1 */
unsigned num = 0;

/* Method 1: CMP + JE*/
if(foo == 1){
    num = 5;
}

/* Method 2: MUL */
num = foo*5;    /* num = 0 if foo = 0 */

不要对伪代码看得太深,它纯粹是为了阐明这两种方法背后的数学逻辑。

我实际比较的是以下两个指令序列:

方法一:CMP + JE

    MOV EAX, 1    ; FOO = 1 here, but can be set to 0
    MOV EBX, 0    ; NUM = 0

    CMP EAX, 1    ; if(foo == 1)
    JE  SUCCESS   ; enter branch
    JMP FINISH    ; end program

SUCCESS:
    MOV EBX, 5    ; num = 5

FINISH:

方法2:MUL

    MOV EAX, 1    ; FOO = 1 here, but can be set to 0

    MOV ECX, EAX  ; save copy of FOO to ECX
    MUL ECX, 5    ; result = foo*5
    MOV EBX, ECX  ; num = result = foo*5

似乎单个 MUL(总共 4 条指令)比 CMP + JE(总共 6 条指令)更有效,但是指令消耗的时钟周期平均 - 即完成与任何其他指令相同的指令所需的时钟周期数?

如果实际消耗的时钟周期取决于机器,单个MUL 是否通常比大多数处理器上的分支方法更快,因为它需要更少的总指令?

【问题讨论】:

  • 在这种情况下,CMOV 可能比CMP + JEMUL 更有效。
  • 这大概是机器码优化的第一条规则。如果可以,总是避免分支。错误预测的分支非常昂贵。第 0 条规则是始终先测量。
  • 请记住,这有点像“苹果对橙子”的比较——如果foo 不在{0, 1} 中,这两种方法是不等价的。
  • @twalberg 糟糕,我忘了说明 foo 必须是 01 才能进行数学运算。
  • “分支”版本不太可能使用 JE 后跟 JMP - 而是单个 JNE FINISH

标签: c performance optimization assembly x86


【解决方案1】:

现代 CPU 的性能要复杂得多,而不仅仅是计算每条指令的周期数。您需要(至少)考虑以下所有因素:

  • 分支预测
  • 指令重新排序
  • 注册重命名
  • 指令缓存命中/未命中
  • 数据缓存命中/未命中
  • TLB 未命中/页面错误

所有这些都会受到周围代码的严重影响。

所以本质上,几乎不可能执行这样的微基准测试并获得有用的结果!

但是,如果我不得不猜测,我会说没有 JE 的代码通常会更有效,因为它消除了分支,从而简化了分支预测行为。

【讨论】:

  • 所以理论上即使是同一条指令被调用两次的延迟也会不同?
  • @VilhelmGray:在理想世界中(即假设没有停顿等),内核执行给定指令所需的周期数是确定的。但在实践中,上述所有影响都将主导吞吐量。
  • IMO,您应该为数据缓存未命中 + 总线等待添加一个项目符号。 (甚至可能出现页面错误和上下文切换)好的。
【解决方案2】:

通常,在现代 x86 处理器上,CMPMUL 指令都将占用一个整数执行单元一个周期(CMP 本质上是一个 SUB,它会丢弃结果并仅修改标志寄存器)。然而,现代 x86 处理器也是流水线、超标量和无序的,这意味着性能不仅仅取决于这个底层周期成本。

如果不能很好地预测分支,那么分支错误预测惩罚将淹没其他因素,MUL 版本的性能会明显更好。

另一方面,如果分支可以被很好地预测并且你在随后的计算中立即使用num,那么分支版本就有可能执行在平均情况下更好。这是因为当它正确预测分支时,它可以在比较结果可用之前使用num 的预测值开始推测执行下一条指令(而在MUL 的情况下,后续使用num 将对 MUL 的结果有数据依赖性 - 在该结果退出之前,它将无法执行。

【讨论】: