【问题标题】:Understanding CPU pipeline stages vs. Instruction throughput了解 CPU 流水线阶段与指令吞吐量
【发布时间】:2015-12-17 19:08:48
【问题描述】:

我缺少一些基本的东西。 CPU 流水线:在基本层面上,为什么指令需要不同数量的时钟周期才能完成,为什么在多级 CPU 中某些指令只需要 1 个周期?

除了明显的“不同的指令需要不同的工作量来完成”,听我说...

考虑具有大约 14 级管道的 i7。这需要 14 个时钟周期才能完成一次运行。 AFAIK,这应该意味着整个管道有 14 个时钟的延迟。然而事实并非如此。

XOR 在 1 个周期内完成,延迟为 1 个周期,表明它没有经过所有 14 个阶段。 BSR 有 3 个周期的延迟,但每个周期的吞吐量为 1。 AAM 的延迟为 20 个周期(超过阶段数)和 8 个吞吐量(在 Ivy Bridge 上)。

有些指令不能每个时钟都发出,但需要不到 14 个时钟才能完成。

我知道多个执行单元。我不明白延迟和吞吐量方面的指令长度与管道阶段的数量有何关系。

【问题讨论】:

  • 当您说 XOR 具有“1 个周期的延迟”时,您究竟是什么意思?你的来源是什么?这似乎是一个毫无意义的衡量标准。
  • Agner Fog 的图表 (agner.org/optimize/instruction_tables.pdf)。这意味着 XOR 需要 1 个时钟周期来执行,因此延迟为 1,而 BSR 需要 3。
  • 你读过他对延迟的解释吗?如果是这样,我不明白您为什么会说“XOR 在 1 个周期内完成并且延迟为 1 个周期,表明它没有经过所有 14 个阶段”。
  • @IanC 通过阅读您的问题和 cmets,我认为您对管道的阶段和功能单元的延迟感到困惑。他们不是一回事。每条(正确的)指令都必须经过所有的流水线阶段。有些阶段有固定的延迟,有些阶段有可变的延迟,例如执行阶段。
  • @IanC 是的,这是典型的行为。当您阅读 Intel 或 Agner Fog 等优化手册时,延迟和吞吐量是指功能单元(执行阶段)。

标签: cpu pipeline cpu-architecture latency instructions


【解决方案1】:

我认为现有答案中缺少的是“绕过”或“转发”数据路径的存在。为简单起见,让我们坚持使用 MIPS 5 级管道。每条指令从出生到死亡需要 5 个周期——获取、解码、执行、内存、写回。这就是处理一条指令所需的时间。

您想知道的是,一条指令将其结果传递给相关指令需要多长时间。假设您有两个连续的 ADD 指令,并且通过 R1 存在依赖关系:

ADD R1, R2, R3
ADD R4, R1, R5

如果没有转发路径,我们必须将第二条指令暂停多个周期(2 或 3 次,具体取决于写回的工作方式),以便第一条指令可以在第二条指令之前将其结果存储到寄存器文件中在解码阶段读取它作为输入。

但是,存在允许从管道中挑选出有效结果(但尚未写回的结果)的转发路径。因此,假设第一个 ADD 从解码中的寄存器文件中获取所有输入。第二个将从寄存器文件中取出 R5,但它会在执行阶段之后从管道寄存器中取出 R1。换句话说,我们在一个周期后将 ALU 的输出路由回其输入。

乱序处理器无处不在地使用转发。它们将具有许多不同的功能单元,这些单元具有许多不同的延迟。例如,ADD 和 AND 通常需要一个周期(做数学运算,抛开之前和之后的所有流水线阶段),MUL 将需要大约 4 个周期,浮点运算将需要很多周期,内存访问具有可变延迟(由于缓存未命中)等。

通过使用转发,我们可以将一条指令的关键路径限制为仅执行单元的延迟,而其他一切(获取、解码、退出)都在关键路径之外。指令被解码并转储到指令队列中,等待其他执行指令产生它们的输入。当一条指令的依赖得到满足时,它就可以开始执行了。

让我们考虑这个例子

MUL R1,R5,R6
ADD R2,R1,R3
AND R7,R2,R8

我将尝试绘制一个时间线,显示这些指令通过管道的流程。

MUL  FDIXXXXWR
ADD   FDIIIIXWR
AND    FDIIIIXWR

键:

F - Fetch
D - Decode
I - Instruction queue (IQ)
X - execute
W - writeback/forward/bypass
R - retire

因此,如您所见,乘法指令的总生命周期为 9 个周期。但是 MUL 和 ADD 的执行存在重叠,因为处理器是流水线的。当 ADD 进入 IQ 时,它必须等待其输入 (R1),依赖于 ADD 结果 (R2) 的 AND 也是如此。我们关心的不是 MUL 总共存在多长时间,而是任何依赖指令必须等待多长时间。那是它的有效延迟,即 4 个周期。如您所见,一旦 ADD 执行,从属 AND 可以在下一个循环中执行,同样是由于转发。

【讨论】:

    【解决方案2】:

    我缺少一些基本的东西。 CPU 流水线:在基本层面上,为什么指令需要不同数量的时钟周期才能完成,为什么在多级 CPU 中某些指令只需要 1 个周期?

    因为我们感兴趣的是指令之间的速度,而不是单个指令的开始到结束时间。

    除了明显的“不同的指令需要不同的工作量来完成”,听我说...

    这就是为什么不同的指令有不同的延迟的关键答案。

    考虑具有大约 14 级管道的 i7。这需要 14 个时钟周期才能完成一次运行。 AFAIK,这应该意味着整个管道有 14 个时钟的延迟。然而事实并非如此。

    这是正确的,尽管这不是一个特别有意义的数字。例如,为什么我们要关心 CPU 完成一条指令需要多长时间?那基本上没有效果。

    XOR 在 1 个周期内完成,延迟为 1 个周期,表明它没有经过所有 14 个阶段。 BSR 有 3 个周期的延迟,但每个周期的吞吐量为 1。 AAM 的延迟为 20 个周期(超过阶段数)和 8 个吞吐量(在 Ivy Bridge 上)。

    这只是一堆误解。 XOR 将一个延迟周期引入依赖链。也就是说,如果我执行 12 条指令,每条指令都修改前一条指令的值,然后添加一个 XOR 作为第 13 条指令,则需要多花一个周期。这就是延迟的含义。

    有些指令不能每个时钟都发出,但需要不到 14 个时钟才能完成。

    没错。那么?

    我知道多个执行单元。我不明白延迟和吞吐量方面的指令长度与管道阶段的数量有何关系。

    他们没有。为什么要有联系?假设在管道的开始有 14 个额外的阶段。为什么这会影响延迟或吞吐量?这只是意味着一切都在 14 个时钟周期后发生,但仍以相同的速率发生。 (虽然它可能会影响错误预测分支的成本和其他事情。)

    【讨论】:

    • 好吧,你明白它是如何工作的。我能找到的每个示例都显示了一个 RISC(不是 CISC)流水线,其中每条等长指令都经过流水线的所有(通常是 5 个)阶段。每个阶段执行不同的功能。恰当的例子:XOR 和 BSR 是否在所有 14 个(比如说)阶段上执行?如果我们将这些阶段想象为车间中的工作站,我们会认为工作从一个站点到另一个站点并得到工作,最终退休。但是为什么有些指令会导致> 1个周期的延迟呢?希望你能理解我的问题。
    • @IanC 在流水线中的每个点,下一条指令都无法进入流水线的下一个状态,除非该指令所依赖的所有先前指令都提供了该指令需要进入该状态的任何内容下个阶段。如果一行中的两条指令需要对第二条指令进行延迟,则第一条指令将引入一个以上的延迟周期。例如,考虑一个乘法,然后是一个结果的增量。在某些时候,增量将不得不等待乘法取得更多进展。
    • @IanC 指令经常在流水线中停止,因为它们前进到下一步所需的条件没有得到满足。这包括需要从主存访问信息、需要其他指令使用的执行资源、需要先前指令的结果等等。
    • 我仍然不清楚的是,当一条指令必须经过所有 14 个阶段才能执行时,它是如何具有 1 的延迟。 add eax, $10 只需要 1 个周期,也就是只执行 1 个阶段。获取、解码、转换为微操作时发生了什么……退休?
    • 那你还是不太明白在这种情况下延迟是什么意思。延迟是如果将此指令添加到其中间,则依赖链将花费多少个周期。因此,例如,假设我们将寄存器递增两次,这需要 17 个周期。然后我们在这两个增量之间加上一个常数,现在需要 19 个周期。这意味着乘法向依赖链添加了 2 个延迟周期。这基本上意味着在某些时候第二个增量必须等待一个额外的周期,因为乘法没有进展到所需的增量。
    猜你喜欢
    • 1970-01-01
    • 2017-03-20
    • 2019-08-27
    • 2019-02-19
    • 2013-03-23
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多