流水线
简介
- 这里的流水线技术主要是指令流水线
- 将一条指令的执行过程拆分成多个独立的阶段,在一个时钟周期(本人认为,这里的时钟周期表示的含义更接近 机器周期,指完成一个指令内部阶段所耗费的时间; 机器周期这一概念被 阶段(逻辑划分) 和 时钟周期(时间单位划分) 淡化了)下,有多条指令的阶段同时执行,优化指令的执行效率
流水线模型
根据指令阶段划分给出模型,例如 取指 -> 译码 -> 执行 3级模型;
在此给出的是在 RISC 架构中比较常见的5级流水线模型: 取指(IF) -> 译码(ID) -> 执行(EX) -> 访存(MEM) -> 写回(WB)
- 取指: 从指令存储器读取下一条要执行的指令
- 译码: 对指令解码,转换成相关的控制信号
- 执行: 根据控制信号做相关的操作,包含访存地址计算等
- 访存: 指令为加载(load)时,从内存读取数据; 指令为存储(store)时,将数据存储到内存中
- 写回: 将执行结果写回到目标寄存器或存储器中(一般是寄存器,写内存的话一般在第4点完成)
指令执行方式
预设
- k级流水线模型
- 各个阶段的执行时间相同,均为t
- 流水线模式下,每个时钟周期下都有一条指令进入流水线
串行执行(非流水线方式)

- 单条指令执行时间:
- n条指令执行时间:
- 吞吐率(单位时间内完成的指令数量):
流水线方式

- 单条指令执行时间:
- n条指令执行时间:
- 吞吐率(单位时间内完成的指令数量):
- 当 时, ,理想流水线吞吐率为每个时钟周期完成一条指令(流水线填满后,没有冲突时是这个状态)
- 加速比(衡量流水线相对于串行模式的性能提升倍数):
- 效率(流水线中的指令占用的时空区域和流水线整体的时空区域的比值, 时空区域: 图中的坐标轴围成的区域):
,当 n 远大于 k 时,流水线的效率趋近于 1,即流水线整体处于忙碌状态
现实因素对性能指标计算的影响
- 各个阶段的执行时间不一定相同,多个阶段有相对较慢的阶段,这个会导致其它阶段处于等待中
- 流水线冒险/冲突导致的停顿
- 处理器会提前对程序做分支预测,当分支预测错误时,会导致后续多条指令错误执行,处理器会清空原先的计算结果(涉及多个时钟周期执行的内容),转到正确的分支上执行,影响性能
流水线冒险(Pipeline Hazards)
在流水线中可能由某些因素,导致下一个时钟周期中下一条指令不能执行(流水线断流),影响流水线的效率

结构冒险(Structural Hazards)
-
硬件资源导致的存取/读写冲突(硬件不支持多条指令在同一时钟周期内执行)
-
例: 下图中展示的是 取指 和 访存 同时读取内存可能存在的冲突

-
解决方法
- 流水线停顿,产生空泡(bubbles)(取指操作延迟一个时钟周期执行)
- 分离指令存储器和数据存储器
- 采用双端口存储器
数据冒险(Data Hazards)
-
一条指令依赖前一条指令的运算结果(局部性冒险)
-
例: 下图展示的是执行 EX 阶段指令依赖上一条需要执行 MEM 指令(存储)的数据

-
解决方法
- 流水线停顿/互锁,产生空泡(bubbles)(EX 操作延迟一个时钟周期执行)
- 数据旁路/转发
控制冒险(Control Hazards)
- 处理器在取指阶段末尾才能确定分支是否成功,但在此期间已经顺序读取了下一条指令,导致存在风险(控制流改变,全局性冒险)
- 解决方法
- 流水线停顿,等到分支确定后(EX 阶段执行后得到结果)再恢复
- 静态预测,预测永远跳转/不跳转(准确率相对较低)
- 动态预测,处理器根据分支的历史行为动态进行预测
- 使用复杂的分支预测逻辑判断分支是否成功(选择概率高的分支,预测错误时清空所有错误执行的指令以及产生的结果)
- 延迟分支,编译器重新排列指令顺序,在分支指令之后插入一条(或几条)无论分支是否成功都会执行的指令
其它
- 超标量流水线: 每个时钟周期向流水线发射多条指令,并能从流水线流出多个结果
- 超流水线技术: 把一般完成一条指令的流水线段再细分成更多的流水线段。这样原时钟周期的几分之一的时间间隔就可以发射一条指令,并从流水线流出一个结果
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Forgotten Area!


