Skip to content

L07:复杂流水线——乱序执行、寄存器重命名与异常(Out-of-Order Execution, Register Renaming, and Exceptions

MIT 6.5900 Fall 2024 · Joel Emer 主题:记分牌回顾、按序发射的限制、乱序发射、Little's Law 与寄存器数、Tomasulo 重命名、重排序缓冲(ROB)、精确异常


一、CDC 6600 式记分牌回顾

指令按序发射,仅当不会引起 RAW、不会引起 WAW 时才发射;保证执行阶段至多一条指令能写某寄存器;因按序发射 + 立即读操作数,WAR 不可能发生。两个位向量:Busy[FU#](FU 可用性)、WP[reg#](寄存器是否有挂起写)。


二、按序发射的限制

例(含一条 long 延迟的 FLD):

1 FLD   f2, 34(x12)   延迟 1
2 FLD   f4, 45(x13)   延迟 long
3 FMUL.D f6, f4, f2   延迟 3
4 FSUB.D f8, f2, f2   延迟 1
5 FDIV.D f4, f2, f8   延迟 4
6 FADD.D f10, f6, f4  延迟 1

按序限制使指令 4 无法被分派——尽管它与卡住的指令 2、3 无依赖。


三、乱序发射(Out-of-Order Issue

  • 发射级缓冲保存多条等待发射的指令;
  • 译码把下一条指令加入缓冲(若有空间且不引起 WAR/WAW 冒险);
  • 可发射缓冲中任何 RAW 已满足的指令(暂设每周期至多一次分派);写回可能使更多指令就绪。

仅靠乱序发射并未带来显著提升——因为 WAR/WAW 冒险仍阻止指令 5 被分派。


四、Little's Law 与寄存器数

在飞指令数限制吞吐,而 ISA 的哪个特性限制了在飞指令数?→ 寄存器数

T=NL

例:4 个浮点寄存器、每浮点操作 8 周期 → 只有 ½ 次发射/周期!浮点流水线常因寄存器少而填不满(IBM 360 只有 4 个 FPR)。

关键问题:微架构能否在不损失 ISA 兼容性的前提下用比 ISA 指定更多的寄存器?→ 能。Tomasulo(IBM, 1967)提出基于即时寄存器重命名的巧妙方案。


五、寄存器重命名(Register Renaming

为每个寄存器写提供一个新位置,从而消除 WAR 与 WAW 冒险(重命名 ⇒ 额外存储)。

in-order:     1 (2,1) . . . . . . 2 3 4 4 3 5 . . . 5 6 6
out-of-order: 1 (2,1) 4 4 5 . . . (2,5) 3 . . 3 6 6   # f4 重命名为 f4'

处理寄存器依赖

  • 译码做寄存器重命名,为每个寄存器写提供新位置 → 消除 WAR/WAW;
  • 重命名后的指令加入发射级结构——重排序缓冲(ROB);ROB 中任何 RAW 已满足的指令可被分派;
  • 乱序/数据流执行处理 RAW。

重排序缓冲(Reorder Buffer, ROB)[Smith and Pleszkun, 1985]

ROB 每项:Ins# | use | exec | op | p1 src1 | p2 src2。指令槽成为执行候选当:持有有效指令(use 置位)、尚未开始执行(exec 清零)、两操作数都可用(present 位 p1、p2 置位)。

体系结构寄存器值在哪里并不明显——可能在寄存器文件,也可能在 ROB 某项中(以 tag ti 或数据 vi 形式)。

重命名与乱序发射

  • 源中的名字(tag)何时被数据替换?→ 每当某功能单元产生数据时;
  • 名字(tag)何时可复用?→ 每当一条指令完成时;
  • 重命名表 + 寄存器文件每项持有数据 vi 或 tag ti(带 present 位)。

数据驱动执行(Data-Driven Execution

  • 译码级分配指令模板(即 tag t)并把 tag 存入寄存器文件;
  • 指令完成时其 tag 被释放;
  • 公共总线<t, result> 立即广播给所有等待该数据的指令(IBM 360/91 Tomasulo 浮点单元的做法,把 tag 替换为值是昂贵操作)。

ROB 循环管理:开始执行置 exec 位;完成时 use 位标记为空闲;仅当 use 空闲才推进 ptr2。


六、Tomasulo 的有效性

重命名与乱序执行 1969 年首次在 IBM 360/91 实现,但只对很小一类问题有效,直到 90 年代中期才重新出现。为什么?

  1. 没有解决内存延迟问题(它比 FU 延迟问题大得多);
  2. 使异常变得不精确
  3. 还需解决分支/跳转代价问题。

七、精确异常(Precise Exceptions

异常可视为在两条指令间隐式插入的条件子程序调用。须表现为异常恰好发生在两条指令(IiIi+1)之间:

  • Ii 及之前所有指令的效果已完成
  • Ii 之后任何指令的效果尚未发生
  • 处理程序要么中止程序、要么从 Ii+1 重启。

乱序完成对异常的影响:高速下难实现精确异常——想在更早指令的异常检查完成前就开始执行较晚指令。

处理异常的选项

异常造成对下一个 PC 值的依赖。处理选项:停顿、旁路、找别的事做、改架构、推测(最常见)。

对推测的指令,把状态更新延迟到提交;较早的异常须覆盖较晚的。


八、按序提交实现精确异常

指令执行的四个阶段:

  • 取指(Fetch):从 Cache 取指令位 —— 按序;
  • 译码(Decode):放入相应发射缓冲 —— 按序;
  • 执行(Execute):指令与操作数送执行单元,完成时结果与异常标志可用 —— 乱序;
  • 提交(Commit / graduation):指令不可逆地更新体系结构状态 —— 按序。

实现:取指与译码按序进入 ROB;执行乱序(乱序完成);提交(写回体系结构状态即寄存器文件与内存)按序。提交前需临时存储保存结果(影子寄存器与存储缓冲)。

精确异常的扩展

ROB 项增加 <pd, dest, data, cause> 字段;按程序序提交到寄存器文件与内存(缓冲可循环维护);异常时通过 ptr1 = ptr2 清空 ROB(store 须等提交才更新内存)。

回滚与重命名

寄存器文件不再含重命名 tag(只持已提交状态),译码级如何找源寄存器的 tag?→ 搜索 ROB 的 dest 字段

重命名表(Renaming Table

重命名表是加速寄存器名查找的缓存(每项 tag + valid)。每次取异常后需清空;控制转移时也清有效位。

物理寄存器文件(Physical Register File

ROB 空间低效——一个数据值可能存于 ROB 多处。

思路:把所有数据值放在物理寄存器文件,tag 既是数据值的名字也是持有它的物理寄存器的名字,ROB 只存 tag。于是 64 位数据值可被 8 位 tag 替换(256 项物理寄存器文件)。


九、分支代价(Branch Penalty

从取指到分支解析之间,误预测时需 kill 多少指令?现代处理器在 nextPC 计算与分支解析之间可能有 >10 个流水级


小结

  • 按序发射受 WAR/WAW 与寄存器数限制;乱序发射仅靠自身提升有限,寄存器重命名(Tomasulo)消除 WAR/WAW 才是关键;
  • Little's Law 说明寄存器数限制在飞指令数从而限制吞吐;重命名提供额外存储以容纳更多在飞指令;
  • ROB 支持按序取指/译码、乱序执行、按序提交,从而在乱序核中实现精确异常;物理寄存器文件方案让 ROB 只存 tag、更省空间;
  • Tomasulo 早期受限于内存延迟、不精确异常与分支代价——后两者由 ROB 与分支预测解决。

下一讲:分支预测与推测执行