在给定周期中获取的指令数取决于多个因素。对于 Intel 的第四代 Core 处理器,当使用指令缓存而不是 µop 缓存时,每个周期都会获取对齐的 16 字节指令块。可以从这个块中解析多达 6 条指令并将其放置在指令队列中(该队列最多可以容纳来自线程的 20 条指令)。如果可以融合两条指令(也称为宏操作),则最多可以解码来自该队列的五条指令,第一条指令解码为不超过四个融合微操作,其余三个指令解码为单个融合微操作。生成的 µops 存储在一个 56 条目的 µop 解码队列中(也用作循环缓冲区)。 (解码成超过 4 个微指令的指令使用特殊的微码引擎。)
由于 x86 具有可变长度指令(最长 15 字节长),因此 16 字节块中的指令数量可能会有所不同。此外,对于采用分支,分支的目标可能不会与 16 字节块对齐,并且分支指令可能不会在块的最后一个字节处结束;这意味着具有未对齐的分支目标的块开头的字节将被忽略,而在分支之后的块中的字节将被忽略。
(在其他一些微架构中,采用分支可能会导致没有(有用的)指令被提取的循环。如果分支目标缓冲区和指令缓存有两个周期延迟,那么在采用分支上,分支之后的循环开始获取指令将没有目标可用于获取以下指令。)
如果存在指令高速缓存未命中,则在丢失的高速缓存行可用之前,无法从该线程获取指令。类似地,在从指令缓存中进一步获取之前,必须处理 TLB 未命中。
µop 缓存对每个周期获取的指令数有不同的限制。每个周期可以从 µop 缓存中读取 4 个 µop。这可以对应于一条指令或(使用宏操作融合)多于四条指令。由于 µop 缓存被虚拟寻址,TLB 未命中不会停止读取(尽管由于 µop 缓存命中,TLB 未命中不太可能)。
(每个周期可以有四个 µop 从 µop 解码队列移动到 60 条目调度器。)
由于分支预测错误,由于流水线被刷新,因此在分支之后获取的任何指令都不会影响获取的有效指令的计数。虽然会在检测到分支错误预测之前获取指令(并且很可能会执行一些指令),但它们不会影响已提交的指令数量。
此外,指令的缓冲量是有限的。如果依赖于具有数据缓存的加载的微操作未命中,则调度缓冲区可能会被填满,这会导致指令在微操作解码队列中累积(因为该队列将不再被耗尽),然后在获取之后的指令队列将很快填充,因为它不能排入 µop 解码队列。
重排序缓冲区 (ROB) 对离开 µop 解码队列的指令设置了另一个限制;当 ROB 已满时,不能再将指令移入调度缓冲区。如果最旧的指令尚未完成,即使所有后续 191 条指令都已完成并准备好提交,也会发生这种情况。
即使没有数据缓存未命中,操作之间的依赖关系也会导致缓冲区被填满,从而导致指令获取停止。
正如您可能猜到的那样,拥有第二个线程可以通过减少分支预测的影响(实际上只有一半的指令从管道中刷新)并提供更多的指令级并行性(因为来自单独的线程将是独立的),这允许操作执行并最终提交,从而耗尽各种缓冲区。
由于存在如此大量的指令缓冲,并且大多数软件并未始终如一地充分利用执行宽度,因此获取每个周期可能执行的尽可能多的指令的压力较小。高质量的分支预测还意味着实际上将使用更多获取的指令。 (在分支错误预测中,更宽的取指会更快地填满调度缓冲区,从而增加独立操作可用的机会。由于多线程增加了可用的指令级并行量,这也为更广泛的取指提供了动力,但它也减少了与这种激励相反的获取停顿的频率和成本。)