1. 结构冒险 (Structural Hazard)
- 现象:硬件资源冲突。例如,IF 阶段要读指令内存,MEM 阶段要读数据内存。如果指令和数据共用一个 Cache(冯·诺依曼瓶颈),就会冲突。
- 对策:哈佛架构(指令/数据 Cache 分离)。
2. 数据冒险 (Data Hazard) - 重点
- 现象:RAW (Read After Write)。下一条指令需要上一条指令的计算结果,但结果还没写回寄存器。
- 例子:
add $1, $2, $3 # $1 的结果在 WB 阶段才写回
sub $4, $1, $5 # sub 在 ID 阶段就要读 $1
- 对策:
- 阻塞 (Stall/Bubble):暂停流水线,直到数据准备好(浪费性能)。
- 转发/旁路 (Forwarding/Bypassing):直接将 EX 或 MEM 阶段的中间结果“搭桥”传给下一条指令的 ALU 输入端。这是硬件优化的核心。
- 编译器调度:调整指令顺序,填充无关指令。
3. 控制冒险 (Control Hazard) - Spectre 之源
- 现象:遇到分支指令 (Branch/Jump)。CPU 在 IF 阶段就要取下一条指令,但直到 MEM 阶段才知道是否跳转。取错了怎么办?
- 对策:
- 阻塞:遇到分支就停(太慢)。
- 延迟分支 (Delayed Branch):MIPS 特色。分支指令后面的一条指令(延迟槽)总是被执行。
- 分支预测 (Branch Prediction):
- 静态预测:总是预测不跳(或向下跳)。
- 动态预测:使用 BHT (Branch History Table) 记录历史跳转情况。2 位饱和计数器是经典算法。
4. 关联链接
- Spectre漏洞:攻击者训练 BHT,让 CPU 错误预测并执行恶意代码,虽然后来流水线冲刷(Flush)了,但 Cache 留下了痕迹。