【问题标题】:What exactly happens when a skylake CPU mispredicts a branch?当 Skylake CPU 错误预测分支时,究竟会发生什么?
【发布时间】:2018-12-01 16:47:24
【问题描述】:

我正在尝试详细了解当错误预测分支时 Skylake CPU 管道的各个阶段中的指令会发生什么,以及来自正确分支目标的指令可以多快开始执行。

因此,让我们将此处的两条代码路径标记为红色(已预测但未实际采用的路径)和绿色(已采用但未预测的路径)。所以问题是: 1. 在红色指令开始被丢弃之前,分支必须经过管道多远(以及它们在管道的哪个阶段被丢弃)? 2. 绿色指令多久可以开始执行(以分支到达的流水线阶段而言)?

我查看了 Agner Fogg 的文档和大量讲义,但没有发现这些要点。

【问题讨论】:

    标签: x86 intel cpu-architecture branch-prediction speculative-execution


    【解决方案1】:

    分支执行单元(在端口 0 和 6 上)实际上是检查 FLAGS 或间接分支地址的条件或间接分支。我认为一旦执行单元发现它就开始恢复,而无需等待它达到退休。 (其中一些是我最好的猜测/理解,不一定有英特尔的优化手册支持。)

    分支预测 + 推测执行将数据依赖与控制依赖解耦,但分支 uop 本身确实对 EFLAGS 或间接地址输入有数据依赖。

    p0 上的分支单元只能运行 predict-not-taken JCC uops(或 macro-fused JCC uops),但这些是常见的。 p6 上的分支单元是处理已取分支的“主”单元。


    对于直接分支 (jmp rel8/rel32 / call rel32),可以在解码时检查预测并重新引导 fetch 阶段,可能会停止前端,但我认为永远不需要在后面触发任何类型的恢复结尾。永远不会为直接无条件分支发出来自错误路径的 Uop。有用于管道重新引导的性能计数器。


    分支错误预测可以通过分支顺序缓冲区快速恢复,这与通常在异常情况下回滚到退休状态不同:When an interrupt occurs, what happens to instructions in the pipeline?。有关管道如何将一切视为投机直到退休的更多信息,请参阅Out-of-order execution vs. speculative execution

    根据David Kanter's Sandybridge microarch writeup

    Nehalem 增强了从分支错误预测中的恢复,该错误预测已被转移到 Sandy Bridge。一旦发现分支预测错误,一旦知道正确的路径,核心就能够重新开始解码,同时乱序机器正在从错误推测的路径中清除 uops。以前,在管道完全刷新之前,解码不会恢复。

    这是由分支顺序缓冲区启用的“快速恢复”,该缓冲区会在条件和间接分支指令上对 reg 重命名状态进行快照,即使在正常程序中也会出现错误预测。但是异常和内存排序机器清除更昂贵。它们确实会发生(尤其是页面错误),但它们更罕见且更难优化。

    快速恢复的关键是已经在ROB + RS(调度程序)中的错误预测分支之前的微指令可以继续执行之后的微指令被丢弃 前端重新引导到正确的地址。因此,如果 JCC uop 的输入足够早地准备好,如果 CPU 在恢复时可以咀嚼长依赖链,则可以隐藏大部分分支未命中惩罚。例如从具有适当长度循环的循环退出的错误预测携带 dep 链,或除总 uop 吞吐量或端口 6 瓶颈之外的任何瓶颈。见Avoid stalling pipeline by calculating conditional early

    如果没有快速恢复,我认为 ROB 中的 所有 微指令都会被丢弃(即所有未退休的微指令)。这里可能有一些中间立场,比如保留在 ROB 中但离开调度程序的分支之前已经执行的微指令。我不知道 Merom/Conroe 到底做了什么。


    相关:Characterizing the Branch Misprediction Penalty 是一篇关于分支未命中和长缓存未命中如何与 ROB 交互的有趣论文。它基于简化的管道模型,但在我看来,它的发现可能适用于 Skylake。

    【讨论】:

    • 如果前一条指令还没有退出,执行端口如何知道 EFLAGS 寄存器的状态?执行端口如何知道预测不正确,即它如何知道原始预测,它是如何与指令关联的?
    • @LewisKelsey:原始预测在 uop 中编码。在 haswell 和更高版本上,甚至在 port0 上还有一个额外的分支执行单元,它只能处理预测未采用的分支。 jcc 对 EFLAGS 有数据依赖,就像 adcsetc。它不需要等待产生它的指令退出,只需执行。
    猜你喜欢
    • 2019-07-29
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-25
    • 1970-01-01
    • 2015-10-23
    • 2011-01-18
    • 2013-06-13
    相关资源
    最近更新 更多