免责声明: 深入了解硬件如何实际执行指令有点新鲜。
阅读 Jason Gregory 的《游戏引擎架构》,我正在阅读隐式和显式并行性部分。
因此,根据我从书中读到的内容(以及维基百科的一些内容),我会定义:
我的描述(在某种程度上)正确吗?有什么我应该注意的遗漏吗?
是的,大部分是正确的。 不过,VLIW 机器仍然需要正确的分支预测来保持管道供给。 由于超标量机器实际上获取机器代码块(要并行解码),因此它们之间的分支预测问题非常相似。 非 VLIW 需要预测提取块中的哪个指令是所采用的分支,并丢弃其余部分,但在解码之后才需要该预测。 与 VLIW 一样,需要预测下一个要获取的(对齐的 16 字节)块,以便在所采用的分支的管道中具有相同数量的“冒泡”周期。 (一些 CPU 通过在 fetch 到达之前开始生成预测来实现对所采用分支的无气泡预测,因此它可以及时准备好。)像 fetch/decode/exec 这样的阶段之间的队列可以隐藏气泡,特别是当较早的时候阶段比后面阶段的平均吞吐量更宽。 以拥有更多飞行指令为代价,因此正确的分支预测更加重要。
您可以构建一个 VLIW 来查找多个指令字之间的并行性。 例如后来的 IA-64(例如 McKinley)将在每个时钟获取/解码 2 个包,每个包包含 IIRC 3 条指令。 这么宽的有序超标量必须检查这 6 条指令中每对指令之间的危险。 但麦金莱只需要对一个捆绑中的每条指令与另一捆绑中的每条指令进行 3 次更简单的并行检查。(实际上,非 VLIW 机器通过寄存器重命名进行无序执行,因此危险消失,只保留真正的依赖关系。硬件调度程序的工作是避免每个执行端口上的资源冲突。)
当前最常见的 ISA 都不是 VLIW(x86、AArch64 / ARM、RISC-V)。 它们是有序或无序的超标量。 适用于一种微体系结构的 VLIW 捆绑包大小和指令混合限制不适用于另一种微体系结构,但它们已融入 ISA 中。 让硬件来处理这一切可以让硬件的宽度变得更加灵活。 另外,静态公开大量 ILP 并不总是那么容易,特别是如果您不想展开具有较大机器代码大小的每个循环。
具有短向量寄存器的 SIMD 更适合数据并行问题,并且在 2000 年代初期真正走到了最前沿,当时 MMX 已经存在了一段时间,SSE/SSE2 也很流行,x86-64 使 SSE2 基线为 64位代码可以在没有运行时检测的情况下假设支持。 拥有更宽的执行单元而不是通过整个管道发送更多标量指令是一个巨大的胜利。
另请参阅