Skip to content

流水线数据冒险模拟器使用指南

考情分析

流水线数据冒险是 408 的高频考点,几乎每年都会考到。常见题型包括:判断相邻指令间是否存在 RAW 冒险、计算需要插入几个气泡、画出有 stall/forwarding 的时空图。这个模拟器用三个模式逐步对比,让你看到冒险在哪、怎么解决、代价几何。

考点你会在哪个模式看到考频
RAW 冒险的识别无处理模式🔥🔥🔥
阻塞/插入气泡阻塞模式🔥🔥🔥
数据转发 (Forwarding)转发模式🔥🔥🔥
stall 周期数计算阻塞模式🔥🔥🔥
转发路径 (EX→EX, MEM→EX)转发模式🔥🔥

走完三个模式大约 10 分钟。走完后你会对"几个 stall"、"转发能否消除 stall"有清晰的画面感。

加载可视化中...

模式一:无处理(看冒险在哪)

你会看到什么

标准的 5 级流水线时空图,5 条指令正常流水执行。但 I2(sub $t3, $t0, $t4)的 ID 阶段被标红——因为此时 I1(add $t0, $t1, $t2)还没有完成 WB,$t0 的值还是旧的。

关键观察:I2 在 CC3 进入 ID 阶段读 $t0,但 I1 要到 CC5 的 WB 阶段才会将结果写回 $t0。这就是经典的 RAW(写后读)冒险

不处理冒险的后果

如果不做任何处理,I2 读到的 $t0 是旧值,计算结果错误。这就是为什么必须用阻塞或转发来解决数据冒险。

模式二:阻塞(插入气泡)

你会看到什么

I2 在进入 ID 之前被暂停(stall),插入 2 个气泡(bubble),直到 I1 的 WB 完成后,I2 才进入 ID 读取正确的 $t0

关键数字

  • 无冒险时总周期 = 9
  • 插入 2 个气泡后总周期 = 11
  • 性能损失 = 2 个时钟周期(约 22%)

阻塞周期数怎么算?

相邻指令的 RAW 冒险(距离 = 1):需要等待 WB - ID = 3 个阶段,但流水线本身就有 1 个周期的自然间隔,所以需要 stall 2 个周期。

通用公式:stall 周期数 = max(0, WB 所在阶段编号 - ID 所在阶段编号 - 指令间距离)

模式三:数据转发(Forwarding)

你会看到什么

I1 的 EX 阶段计算完 $t0 的新值后,通过旁路(橙色箭头)直接送到 I2 的 EX 输入端。I2 不需要等待 I1 的 WB,总周期数保持 9——与无冒险时完全一样!

转发路径

  • EX→EX 转发:I1.EX → I2.EX(相邻指令,距离 = 1)
  • MEM→EX 转发:I1.MEM → I3.EX(间隔 1 条,距离 = 2)

Load-Use 冒险:转发也救不了

如果 I1 是 lw(Load 指令),数据要到 MEM 阶段结束才可用。即使有转发,I2 仍需 1 个 stall。这就是为什么编译器会尝试在 lw 后面插入一条无关指令(指令调度)。408 选择题常考这个区别!

三种方案对比

方案总周期额外代价结果正确性
无处理9错误
阻塞11+2 气泡正确
转发9额外硬件正确

考研高频考点速览

考点考频关键记忆
RAW 冒险识别🔥🔥🔥后条指令读、前条指令写同一个寄存器,且中间间隔不够
阻塞周期数🔥🔥🔥无转发:相邻 = 2 stall,间隔 1 = 1 stall,间隔 2+ = 0
转发能否完全消除 stall🔥🔥🔥R 型可以(0 stall),Load-Use 仍需 1 stall
三种冒险类型🔥🔥RAW(最常见)、WAW、WAR
转发路径🔥🔥EX→EX(距离 1)、MEM→EX(距离 2)
指令调度🔥🔥编译器重排指令消除 Load-Use 冒险,不改变语义

推荐使用流程

第一轮:理解冒险(3 分钟)

  1. 选"无处理"模式,逐周期播放
  2. 观察 I2 的 ID 阶段红色标记——冒险发生的时刻
  3. 想清楚:为什么 CC3 读 $t0 是错误的?

第二轮:感受代价(3 分钟)

  1. 切换到"阻塞"模式
  2. 观察灰色虚线框的气泡——这就是 stall 的代价
  3. 数一数:总周期从 9 变成了 11

第三轮:看转发如何消除 stall(3 分钟)

  1. 切换到"转发"模式
  2. 关注橙色箭头——数据从哪里来、到哪里去
  3. 确认总周期回到了 9——转发消除了全部 stall

做题应用

遇到数据冒险的题时:

  1. 先标出所有 RAW 依赖关系
  2. 计算指令间距离
  3. 根据是否有转发,确定 stall 周期数
  4. 如果有 Load-Use,即使有转发也要加 1 个 stall

真题练习