# 3.10 贯穿各层的问题
<!-- source: p0261 -->

## 硬件推测与软件推测

本章高度依赖硬件的推测方法，与附录 H 的软件方法，为开发 ILP 提供了不同选择。它们的部分取舍与局限如下：

- 要广泛推测，就必须能够对内存访问消歧。对于包含指针的整数程序，在编译时很难做到。<!-- source: p0262 -->硬件方案利用前面介绍的技术，在运行时动态消除内存地址歧义，允许加载在运行时越过存储。支持围绕内存访问进行推测，也有助于克服编译器过度保守的问题；但如果不进行选择性推测，恢复机制的开销可能淹没收益。
- 当控制流难以预测，而且硬件分支预测优于编译时的软件分支预测时，硬件推测效果更好。许多整数程序符合这些条件：动态预测器的错误预测率通常不到静态预测器的一半。由于预测错误时，推测指令可能拖慢计算，这个差异十分重要。因此，即使静态调度处理器，通常也具有动态分支预测器。
- 硬件推测即使对推测指令，也能维持完全精确的异常模型。近期软件方案也增加了特殊支持，以实现这一点。
- 硬件推测不需要补偿或记账代码，而激进的软件推测机制需要这些代码。
- 编译器能够看到代码序列中更远的部分，可能因此比纯硬件方法获得更好的调度结果。
- 动态调度结合硬件推测时，为了在同一体系结构的不同实现上取得良好性能，不需要使用不同代码序列。这个优点最难量化，但长期看可能最重要。有趣的是，它也是 IBM 360/91 的设计动机之一。另一方面，IA-64 等较新的显式并行体系结构，也加入了灵活机制，减轻代码序列对具体硬件的固有依赖。

硬件支持推测的主要缺点，是复杂度与额外硬件资源。评价这项成本时，必须同时考虑软件方法的编译器复杂度，以及依赖这种编译器后，处理器可以简化多少、这些简化有多大价值。

有些设计者尝试结合动态与编译器方法，兼取两者之长。但组合也可能产生有趣而隐蔽的相互作用。例如，将条件移动与寄存器重命名结合，会出现一个微妙的副作用：一条被取消的条件移动，仍必须向目标寄存器复制一个值，因为该目标已在流水线较早阶段被重命名。

<!-- source: p0263 -->

这些细微交互使设计与验证更复杂，也可能降低性能。

Intel Itanium 是有史以来以软件支持 ILP 和推测为基础、设计目标最为雄心勃勃的计算机。它未实现设计者的期待，尤其是在通用、非科学计算代码上。面对第 244 页描述的困难，设计者开发 ILP 的目标有所收敛，大多数体系结构最终选择硬件机制，每周期发射 3～4 条指令。

## 推测执行与存储系统

支持推测执行或条件指令的处理器，天然可能产生一些无效地址，而没有推测执行时本不会出现这些地址。

对这些地址触发保护异常，在功能上是不正确的，也很可能抵消推测执行的收益。如 3.5、3.6 节所述，超标量处理器把异常推迟到指令准备提交时，也就是不再具有推测性时才触发。但 3.12 节将看到，即使只是执行了后来会被撤销的无效地址加载，也可能成为严重安全漏洞的根源。

同理，也不能让这些指令因缓存未命中而使缓存停顿，因为不必要的停顿同样可能淹没推测收益。因此，这类处理器必须配备非阻塞缓存。实际上，访问 DRAM 的未命中代价非常大，所以只有当下一级是片上缓存（L2 或 L3）时，才处理推测产生的未命中。

第 84 页的图 2.5 显示，对于某些行为规律的科学计算程序，编译器能够保持多次未完成的 L2 未命中，从而有效降低 L2 未命中代价。要使这种方法奏效，缓存后方的存储系统也必须在同时进行的内存访问数量上，配合编译器的目标。

> 译注：原文引用“第 84 页的图 2.5”，但本版图 2.5 列出的是 DDR DRAM 与 DIMM 的时钟频率、带宽和命名，不能据此核验本段关于科学计算程序未命中的论述。原引用予以保留，不推断作者本来意指哪个图表。
