如果乱序超标量处理器每个周期获取的指令数是常数?

If the number of fetched instructions per cycle is constant for out-of-order superscalar processor?

我想知道无序超标量处理器(假设是 Intel i7 处理器)每个周期获取的指令数是恒定的还是可能会根据缓存未命中率或分支错过给定 code/program 的预测?

如果不是常数,如何解释背后的原因?据我所知,在现代多核处理器中,解码器单元总是尝试解决依赖关系并尝试用独立指令填充流水线气泡。因此,对于任何给定的工作负载,提取指令的数量不应始终相同(大约)?

在给定周期内提取的指令数取决于多种因素。对于 Intel 的第四代核心处理器,当使用指令缓存而不是 µop 缓存时,每个周期都会获取对齐的 16 字节指令块。从这个块中,最多可以解析 6 条指令并将其放入指令队列(最多可容纳来自一个线程的 20 条指令)。如果可以融合两条指令 (a.k.a.macro-ops),则最多可以解码此队列中的五条指令,第一条指令解码为不超过四个融合微操作,其余三个指令解码为单个融合微操作.生成的 µop 存储在一个 56 条目的 µop 解码队列(它也充当循环缓冲区)中。 (解码为超过 4 µop 的指令使用特殊的微代码引擎。)

由于 x86 具有可变长度指令(最多 15 个字节长),因此 16 字节块中的指令数可以变化。此外,对于采取的分支,分支的目标可能不会与 16 字节的块对齐,并且分支指令可能不会在块的最后一个字节结束;这意味着具有未对齐的采用分支目标的块开头的字节将被忽略,并且采用分支之后的块中的字节将被忽略。

(在其他一些微体系结构中,采用的分支会导致一个周期,其中没有(有用的)指令被提取。如果分支目标缓冲区和指令缓存有两个周期延迟,那么在采用的分支上,周期之后开始获取分支指令将没有可用于获取以下指令的目标。)

如果存在指令高速缓存未命中,则在丢失的高速缓存行可用之前无法从该线程获取指令。同样,在可以从指令高速缓存中进行进一步提取之前,必须处理 TLB 未命中。

µop 缓存对每个周期获取的指令数有不同的限制。每个周期可以从微操作缓存中读取四个微操作。这可以对应于一条指令或(通过宏操作融合)多于四条指令。由于 µop 缓存实际上是寻址的,因此 TLB 未命中不会停止读取(尽管 TLB 未命中在给定 µop 缓存命中的情况下不太可能)。

(每个周期有 4 个微操作可以从微操作解码队列移动到 60 条目调度程序。)

对于分支预测错误,由于流水线被刷新,none 在分支之后获取的指令将有助于获取有效指令的计数。虽然在检测到分支预测错误之前将获取指令(并且很可能会执行一些指令),但它们不会影响提交的指令数。

此外,指令的缓冲量有限。如果微操作依赖于数据缓存未命中的负载,调度缓冲区可能会填满,这会导致指令在微操作解码队列中累积(因为该队列将不再被耗尽),然后指令队列在获取之后会很快填充,因为它不能排入 µop 解码队列。

重新排序缓冲区 (ROB) 对离开 µop 解码队列的指令设置了另一个限制;当 ROB 已满时,不能再将指令移入调度缓冲区。如果最旧的指令尚未完成,即使以下所有 191 条指令已完成并准备好提交,也会发生这种情况。

即使没有数据缓存未命中,操作之间的依赖性也会导致缓冲区填满,从而导致指令获取停滞。

正如您可能猜到的那样,拥有第二个线程可以通过减少分支预测的影响(实际上只有一半的指令从流水线中刷新)和提供更多的指令级并行性(因为来自不同线程的指令将是独立的),这允许操作执行并最终提交,耗尽各种缓冲区。

由于存在如此大量的指令缓冲,而且大多数软件并没有始终如一地充分利用执行宽度,因此获取每个周期可能执行的尽可能多的指令的压力较小。高质量的分支预测还意味着实际上会使用更多的提取指令。 (在分支预测错误时,更广泛的获取将更快地填满调度缓冲区,增加独立操作可用的机会。由于多线程增加了可用的指令级并行性的数量,这也为更广泛的获取提供了激励,但它也降低了抵消这种激励的取货摊位的频率和成本。)

为了说明这一点,请查看 this 文档,该文档显示了不同架构在 "parallel." 中执行特定类型指令的能力 正如您所理解的,结合一种延迟类型的指令根据其他人的指示,CPU 会以不同的方式适应混音。因为它们可能依赖于相同的寄存器、高速缓存未命中、分支预测错误(或其他不太明显的因素)并且交互变得更加复杂。