2. 流水线:基础与中级概念

115 阅读3分钟

引言

RISC子集中的每条指令都可以在最多5个时钟周期内实现。这5个时钟周期如下所述。

  1. 取值(IF)
  2. 指令译码/读寄存器(ID)
  3. 执行/有效地址(EX)
  4. 访存(MEM)
  5. 写回(WB)

流水化的主要阻碍——流水线冒险

共有以下3类冒险:

  • 结构冒险:主要发生在不太常用的特殊用途功能单元
  • 数据冒险
  • 控制冒险

数据冒险

有3种类型的数据冒险:

  • 写后读(RAW)冒险:这是最常见的冒险
  • 读后写(WAR)冒险
  • 写后写(WAW)冒险

下面讨论一种用于消除设计数据冒险停顿的技术

利用前递技术将数据冒险停顿减至最少

forwarding=前递=旁路=转发

前递的工作方式如下所述:

  1. 来自EX/MEM和MEM/WB流水线寄存器的ALU结果总是被反馈回ALU的输入端
  2. 如果前递硬件检测到前一个ALU操作已经对当前ALU操作的源寄存器进行了写操作,则控制逻辑选择前递结果作为ALU输入,而不是选择从寄存器堆中读取的值。

分支冒险(控制冒险)

这里讨论4种简单的编译时机制,降低流水线分支代价:

  • 处理分支的最简单机制是冻结冲刷流水线,即保留或删除分支之后的所有指令,直到知道分支目标为止。
  • 一种性能更高但略微复杂的机制是预测未选中,将每个分支都看作未选中分支,让硬件继续执行,就好像该分支未被执行一样。
  • 一种替代机制是将所有分支都看作选中分支。
  • 在早期RISC处理器中广泛使用的第四种机制称为延迟分支

通过预测降低分支成本

当流水线变得越来越深,而且分支的潜在代价增加时,仅使用延迟分支及类似机制就不够了。这时需要寻求一种更积极的方式来预测分支。

这些机制分为两类:依赖编译时可用信息的低成本静态机制;根据程序行为对分支进行动态预测的策略。

动态调度流水线

简单流水线提取一条指令并发射它,除非流水线中的已有指令和被提取的指令之间存在数据相关性,并且不能通过旁路或前递来隐藏。在清除这种相关性之前,不会提取或发射新指令。为了弥补这些性能损失,编译器可以尝试调度指令来避免冒险,这种方法称为静态调度

几种早期处理器使用了另一种名为动态调度的方法,硬件借此方法重新安排指令的执行过程以减少停顿。