【问题标题】:Which instructions can produce a branch misprediction on x86 CPUs?哪些指令会在 x86 CPU 上产生分支错误预测?
【发布时间】:2020-05-03 02:33:31
【问题描述】:

我这里有一道测试题。

哪些指令可能会减慢处理器的工作速度,那么 管道不预测(分支预测)进一步的执行方式?

可能的答案: JGE |添加 |子 |推 | JMP |新西兰 |穆尔 | JG |打电话

如果我们谈论分支预测,JGE、JMP、JNZ 和 JG 是要走的路吗?

【问题讨论】:

  • 无条件 JMP 不能被错误预测,因为它是无条件跳转的。
  • @ecm 所以,因为 JMP 无条件跳转,管道总是预测结果?
  • 差不多。
  • @ecm 等等,但是间接分支和间接调用呢,比如JMP EAX / CALL EAX?当EAX 在现场使用一些顶级公式计算时,间接跳转和调用肯定会产生管道气泡。
  • @ecm: 是的,ret 很有趣,因为它通常与 call 匹配,因此 CPU 通常有一个特殊的预测器堆栈(如 16 或 24 个条目)专用于 ret,预测它比将其视为 BTB 的任何其他间接分支要好得多。例如对于 x86 blog.stuffedcow.net/2018/04/ras-microbenchmarks。高性能 ARM 微架构为 bx lr 做类似的事情。但无论如何,对我来说更令人惊讶的事实是,即使是直接无条件分支也需要在获取阶段进行预测,甚至在它们被解码之前。 ret 更明显是一个间接分支。

标签: assembly x86 cpu pipeline branch-prediction


【解决方案1】:

mul 之类的指令,don't do anything special to EIP 当然不能错误预测,但是每一种跳转/调用/分支在流水线设计中都可能在某种程度上错误预测,即使是简单的@ 987654327@。在像现代 x86 CPU 这样的大量流水线无序执行设计中,这种影响可能很严重。

是的,jcc 条件分支总是需要预测; FLAGS 的值在解码时不可用,只有在稍后执行时才可用。

即使是直接的 jmp rel8 / jmp rel32(和 call rel32)也需要在前端的早期进行预测,甚至在解码之前,因此获取阶段知道哪个在获取可能包含或不包含跳转的块(无条件或预测的条件;它不需要知道,是否继续获取直线)之后,要获取下一个的块。如果 BTB 的数量过多,请参阅 Slow jmp-instruction 了解有关运行速度较慢的简单无条件直接分支的更多信息。

如果您考虑像classic 5-stage RISC 这样的简单有序流水线,在阶段之间没有缓冲区,所有分支基本上都是等效的:获取阶段需要每个时钟获取 1 条指令以避免气泡。它需要在前一条指令仍在解码时知道下一条获取地址。更长的管道使这个问题更加严重。


但更简单地说,jmpcall 有间接形式,例如 jmp eaxjmp [edi],它们从寄存器或内存中加载新的 EIP。那些显然需要预测;您对它的去向有无限的可能性,而不仅仅是采取或不采取。

依赖于数据的分支(以 FLAGS 为条件,或以寄存器或内存为间接条件)可以在发现错误预测之前一直进入后端(并无序执行)。恢复可能需要丢弃执行来自错误路径的后续指令的结果,以及获取/解码正确的路径。 What exactly happens when a skylake CPU mispredicts a branch?

但处理直接 jmp/call 的错误预测更简单:只需重新引导 fetch/decode 阶段,因为在解码指令后目标地址是已知的,而无需执行它。错误预测不会进入后端,所以它“只是”前端的一个泡沫。


有趣的事实:ret 也可能会误判;它基本上是一个间接分支 (pop eip)。但是有一些特殊的预测器利用了 call 和 ret 指令之间的通常配对,保留了最近调用的内部堆栈,以反映内存中调用堆栈的可能使用方式。 http://blog.stuffedcow.net/2018/04/ras-microbenchmarks/

【讨论】:

    猜你喜欢
    • 2011-07-11
    • 2018-12-01
    • 2015-09-25
    • 2015-10-17
    • 1970-01-01
    • 2015-03-31
    • 2012-02-26
    • 2014-01-25
    • 1970-01-01
    相关资源
    最近更新 更多