| 项目 | 值 |
|---|---|
| 定义 | 后续指令需要前面指令的结果但结果尚未写回 |
| 三种类型 | RAW(写后读)、WAR(读后写)、WAW(写后写) |
| 最常见 | RAW(真数据相关) |
| 解决方法 | 转发 / 旁路、流水线停顿、编译器调度 |
| 转发 | 将结果直接从流水段传给需要的指令,不停顿 |
| 停顿 | 插入气泡等待数据就绪 |
数据冒险是指后续指令需要用到前面指令的结果,但该结果尚未写回寄存器 / 存储器。
| 类型 | 名称 | 含义 | 五级流水线中是否出现 |
|---|---|---|---|
| RAW | 写后读 | i 写 → j 读 | 是(最常见) |
| WAR | 读后写 | i 读 → j 写 | 否(顺序执行不会出现) |
| WAW | 写后写 | i 写 → j 写 | 否(顺序执行不会出现) |
指令1: ADD R1, R2, R3 // R1 = R2 + R3,在 EX 阶段产生结果
指令2: SUB R4, R1, R5 // 需要 R1 的值,在 ID 阶段读 R1
指令2在 ID 读 R1 时,指令1的 R1 还在 EX 阶段(未写回) → RAW 冒险。
指令 j 在 ID 阶段读寄存器 X,且存在前面的指令 i 满足:
不等写回,直接将结果从流水段寄存器传给需要的地方:
EX结果 → 转发到 → EX输入(EX-to-EX 转发)
MEM结果 → 转发到 → EX输入(MEM-to-EX 转发)
插入气泡等待结果写回:简单但降低性能,通常配合编译器调度使用。
// 调度前(需要停顿)
ADD R1, R2, R3
SUB R4, R1, R5 // 紧跟,RAW 冒险
// 调度后(无冒险)
ADD R1, R2, R3
OR R6, R7, R8 // 插入无关指令
SUB R4, R1, R5 // 距离拉远,转发即可
硬件检测冒险并自动插入停顿。
| 解决方法 | 停顿周期 | 优点 | 缺点 |
|---|---|---|---|
| 转发 / 旁路 | 0 | 无性能损失 | 增加硬件复杂度 |
| 停顿 1~2 周期 | 1~2 | 简单 | 降低性能 |
| 编译器调度 | 0 | 不增加硬件 | 依赖编译器 |
| Load-Use 冒险 | 必停 1 周期 | — | 转发无法解决 |
LW R1, 0(R2) // 从存储器加载 R1,MEM 阶段才出结果
ADD R3, R1, R4 // 需要 R1,EX 阶段就要用
即使有转发,也必须停顿 1 个周期(MEM → EX 来不及) → Load-Use 冒险。
| 考法 | 解题套路 |
|---|---|
| 识别数据冒险类型 | RAW:后指令读前指令写的寄存器 |
| 判断是否需要停顿 | 能用转发解决 → 不停顿;Load-Use → 停 1 周期 |
| 画转发路径 | EX 结果转发到 EX 输入,MEM 结果转发到 EX 输入 |
| 编译器调度 | 插入无关指令拉开距离 |
| 计算停顿周期数 | 无转发:1~2 周期;有转发:Load-Use 1 周期 |
两条指令:i: ADD R1,R2,R3(写 R1)与 j: SUB R4,R1,R5(读 R1)。切换"转发 / 停顿"观察差异。
★ 演示级:选择处理方式,逐拍推进 MIPS 五段流水线(IF/ID/EX/MEM/WB)周期表 —— i 写 R1,j 读 R1,形成 RAW 依赖。
↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。