在 OoO 处理器中分别执行相同指令的操作
Execute operations of the same instruction separately in an OoO processor
假设我们有一条指令被分成了3个微操作,我们有一个乱序处理器。我的问题是:这 3 个 uops 必须按顺序执行,或者处理器可以将这些 uops 与来自其他指令的其他 uops 交替执行吗?
我的意思是,在OoO处理器中你可以乱序执行指令,但是如果我们把一条指令分成一些微操作,这些微操作可以不按顺序执行吗?
例如我们有3条指令:A、B和C。A和C被分成1个微指令:A1和C1,B被分成3个微指令:B1、B2、B3。例如,OoO 处理器可以执行 B1 - A1 - B2 - C1 - B3 吗?还是必须连续执行B1-B2-B3?
是的,每个 uop 都是独立调度的,只需要等待其输入准备就绪。 (对于执行端口上的空闲周期,它是在发送到无序后端时分配的。)指令边界与 RS aka 调度程序无关。
对于许多多微指令,微指令对较早的微指令具有数据依赖性。但有时较早的微指令只需要准备好其中一个输入,因此有每个输入到输出的单独最小延迟。
例如add eax, [rdi]
只需要 EAX 在 加载 uop 完成后就绪 。所以通过 EAX 的关键路径延迟只有 1 个周期。但是如果 RDI 没有准备好,或者 RDI 指向的内存没有准备好,那么 add ALU 微指令就不能执行。但是,这仍然是解码到 uops 的重点,不像 P5 Pentium 必须在其有序管道中进行加载和加法1.
(或者对于 例如,额外的 uops 仅用于 FLAGS 输出 ;GP 整数部分已准备就绪,有 1 个周期的延迟,但FLAGS 结果稍后准备好。产生 GP 整数结果的 uop 与 BMI2 shlx
解码到的唯一 uop 基本相同。)
但有些确实有一些 ILP (well actually uop-level parallelism). For example xchg eax, ecx
decodes to 3 register-copy uops on Intel CPUs, and we can measure the latency separately for the EAX->ECX and ECX->EAX directions at 1 and 2 cycles (respectively).
另一个例子是phaddd
;它的解码非常像两个 shufps
uops(2 输入洗牌)和一个 paddd
uop,这取决于两个洗牌。两个 shuffle 都在读取两个输入以提供 shuffle。 Ice Lake 在 2 个端口上有洗牌单元,实际上可以 运行 并行洗牌 uops,给它 2 个周期的延迟(uops.info),低于早期英特尔的 3 个周期,因为单个端口的资源冲突洗牌端口。 (Ice Lake 的额外洗牌端口仅 运行 一些整数洗牌,因此 haddps
在 Ice Lake 上仍然和以前一样糟糕)
请注意,我们无法证明每个 uop 到底在做什么,但考虑到测量的延迟和每个端口的总 uop 计数,对于许多指令,只有一个合理的设计解释行为。例如对于 phaddd
,我们知道 CPU 具有 SIMD 整数添加执行单元和整数洗牌单元,因此将 phaddd
实现为 3 微指令最明显可以通过解码为两个硬连线来完成洗牌模式和普通 paddd
uop.
脚注 1:
针对 P5 的优化显然涉及使用 x86 的 RISCier 子集,例如避免 mov
以外的内存源操作数,并且绝对避免内存目标指令。那是因为它是一个 顺序 管道,并且无法将多 uop 指令分开以独立调度它们。
进一步阅读:p5 与后来的微体系结构:https://agner.org/optimize/. Also https://www.realworldtech.com/sandy-bridge/ 非常好。
http://www.lighterra.com/papers/modernmicroprocessors/ 如果您还没有读过它,那是一本很棒的书,但它并没有深入到您的问题所涉及的详细程度。
假设我们有一条指令被分成了3个微操作,我们有一个乱序处理器。我的问题是:这 3 个 uops 必须按顺序执行,或者处理器可以将这些 uops 与来自其他指令的其他 uops 交替执行吗?
我的意思是,在OoO处理器中你可以乱序执行指令,但是如果我们把一条指令分成一些微操作,这些微操作可以不按顺序执行吗?
例如我们有3条指令:A、B和C。A和C被分成1个微指令:A1和C1,B被分成3个微指令:B1、B2、B3。例如,OoO 处理器可以执行 B1 - A1 - B2 - C1 - B3 吗?还是必须连续执行B1-B2-B3?
是的,每个 uop 都是独立调度的,只需要等待其输入准备就绪。 (对于执行端口上的空闲周期,它是在发送到无序后端时分配的。)
对于许多多微指令,微指令对较早的微指令具有数据依赖性。但有时较早的微指令只需要准备好其中一个输入,因此有每个输入到输出的单独最小延迟。
例如add eax, [rdi]
只需要 EAX 在 加载 uop 完成后就绪 。所以通过 EAX 的关键路径延迟只有 1 个周期。但是如果 RDI 没有准备好,或者 RDI 指向的内存没有准备好,那么 add ALU 微指令就不能执行。但是,这仍然是解码到 uops 的重点,不像 P5 Pentium 必须在其有序管道中进行加载和加法1.
(或者对于 shlx
解码到的唯一 uop 基本相同。)
但有些确实有一些 ILP (well actually uop-level parallelism). For example xchg eax, ecx
decodes to 3 register-copy uops on Intel CPUs, and we can measure the latency separately for the EAX->ECX and ECX->EAX directions at 1 and 2 cycles (respectively).
另一个例子是phaddd
;它的解码非常像两个 shufps
uops(2 输入洗牌)和一个 paddd
uop,这取决于两个洗牌。两个 shuffle 都在读取两个输入以提供 shuffle。 Ice Lake 在 2 个端口上有洗牌单元,实际上可以 运行 并行洗牌 uops,给它 2 个周期的延迟(uops.info),低于早期英特尔的 3 个周期,因为单个端口的资源冲突洗牌端口。 (Ice Lake 的额外洗牌端口仅 运行 一些整数洗牌,因此 haddps
在 Ice Lake 上仍然和以前一样糟糕)
请注意,我们无法证明每个 uop 到底在做什么,但考虑到测量的延迟和每个端口的总 uop 计数,对于许多指令,只有一个合理的设计解释行为。例如对于 phaddd
,我们知道 CPU 具有 SIMD 整数添加执行单元和整数洗牌单元,因此将 phaddd
实现为 3 微指令最明显可以通过解码为两个硬连线来完成洗牌模式和普通 paddd
uop.
脚注 1:
针对 P5 的优化显然涉及使用 x86 的 RISCier 子集,例如避免 mov
以外的内存源操作数,并且绝对避免内存目标指令。那是因为它是一个 顺序 管道,并且无法将多 uop 指令分开以独立调度它们。
进一步阅读:p5 与后来的微体系结构:https://agner.org/optimize/. Also https://www.realworldtech.com/sandy-bridge/ 非常好。
http://www.lighterra.com/papers/modernmicroprocessors/ 如果您还没有读过它,那是一本很棒的书,但它并没有深入到您的问题所涉及的详细程度。