在指令流水线中,一个流水段需要一个时钟周期;非流水线中,一条指令的一个阶段需要一个机器周期。
流水段划分
取指 IF | 译码/读寄存器 ID | 执行/计算地址 EX | 访存 MEM | 写回 WB |
---|
每两个流水段中间都有流水段寄存器。
流水线对指令集的要求
- 指令长度尽量一致
- 指令格式尽量规整
- 采用 LOAD/STORE 访问存储器
- 指令按边界存放
不同类型指令在各流水段中的操作
IF | ID | EX | MEM | WB | |
---|---|---|---|---|---|
ALU | 取指 | 译码 读寄存器堆 | 执行 | - | 结果写回寄存器堆 |
Load/Store | 取指 | 译码 读寄存器堆 | 计算访存有效地址 | 访存 | Store:将读出的数据写回寄存器堆 |
转移 | 取指 | 译码 读寄存器堆 | 计算转移目的地址 设置条件码 | 若条件成立,将目的地址送到 PC | - |
解决流水线冒险的方法
结构冲突
多条指令同时争用同一资源而形成的冲突,也称资源冲突。
解决办法:
- 前一指令访存时,使后一条指令(以及其后续指令)暂停一个时钟周期
- 单独设置数据存储器和指令存储器,取指令和取数分别在不同的存储器进行,避免 IF 和 MEM 冲突
数据冒险
也称数据相关,指下一条指令会用到当前指令计算出的结果
- 写后读 RAW:当前指令将数据写入寄存器后,下一条指令才能从该寄存器读取数据
- 读后写 WAR:当前指令读出数据后,下一条指令才能写该寄存器
- 写后写 WAW:当前指令写入寄存器后,下一条指令才能写该寄存器
解决方案:
- 后续指令暂停几个时钟周期
- 将前一条指令的 EX 计算结果存入 EX/MEM 段寄存器,下一条指令不需要等上一条指令 WB 写回,直接读取 EX/MEM 段寄存器,,称为转发(旁路)技术
- 通过优化,调整指令顺序避免数据相关
load-use 冒险是指 load 指令与其后紧邻的运算类指令存在数据相关问题,无法通过转发技术解决,只能通过优化顺序避免或者插入空操作推迟指令。
load 指令只有在 MEM 结束时才能得到主存中的结果,并在 WB 段存入。推迟后,下一条指令的 EX 段可以从 MEM/WB 寄存器中获取 load 指令的结果。
控制冒险
执行转移、调用、返回指令会改变 PC 值,会造成断流。
解决方法:
- 和数据冒险一样插入若干 nop 指令来弥补延迟损失的时间片
- 对转移指令进行分支预测,尽早生成转移目标地址
- 静态预测:若总是不满足预测条件,即继续执行后续指令
- 动态预测:根据程序执行的历史情况,进行动态预测调整,有较高的预测准确率
Cache 缺失的处理过程也会导致流水线阻塞(数据冒险)
流水线的性能指标
- 吞吐率:
- 加速比:
高级流水线技术
超标量流水线技术
超长指令字技术
静态多发射技术,由编译程序挖掘出指令间潜在的并行性,将多条能并行操作的指令组合成一条具有多个操作码字段的超长指令字(可达几百位),为此可能需要多个部件。
超流水线技术
流水段划分越多,时钟周期越短,指令吞吐率越高,超流水线是通过提高流水线主频的方式来提升流水线性能的。
流水线级数越多,用于流水线寄存器的开销越大。