参考书籍:《计算机体系结构:量化研究方法》

基本概念

吞吐量

吞吐量:单位时间内可以完成的指令数(常用单位GIPS,每秒千兆条);
延迟:从头到尾执行一条指令所需要的时间(常用单位ps)。

吞吐量和延迟互为倒数(要求延迟以ns为单位)。

关键点

RISC处理器的经典5级流水线

流水线是一种将多条指令重叠执行的实现技术。一条指令的执行需要多个操作,流水线技术充分利用了这些操作之间的并行性。

将一条指令在流水线中下移一步所需的时间为处理器周期(通常为1个时钟周期)。由于所有各级同时进行,所以处理器周期的长度由最缓慢流水线所需时间决定。

流水线可以缩短每条指令的平均执行时间,降低CPI(每执行一条指令所需的时钟周期数)。

RISC体系结构有几个关键属性,这些属性大大简化了流水线的实现方式:

  • 所有数据操作都是对寄存器中数据的操作;
  • 只有载入(将数据从存储器转移到寄存器)和存储(将数据从寄存器转移到存储器)操作会影响到存储器;
  • 指令格式的数量很少,所有指令通常都是同一种大小。

大多数的RISC体系结构,比如MIPS,通常有三类指令:ALU指令、载入和存储指令和分支与跳转指令。

在RISC指令集中,每一条指令最多需要5个时钟周期:

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

流水线中使用docker 流水线技术_流水线中使用docker

为了确保不同流水级中的指令不会相互干扰,可以在连续流水级之间引入流水线寄存器,这样会在时钟周期的末尾,将一个给定流水级得出的所有结果都存储到寄存器中,在下一个时钟周期用作下一级的输入。

流水化提高了CPU指令吞吐量,但不会缩短单条指令的执行时间。相反,由于流水线控制会产生开销,它通常还会稍微延长每条指令的执行时间。

流水化加速比 = 非流水化指令平均执行时间 ÷ 流水化指令平均执行时间

流水线冒险

冒险会阻止指令流中的下一条指令在其自己的指定时钟周期内执行,降低了流水化所能获得的理想加速比。

  • 结构冒险:在重叠执行模式下,如果硬件无法同时支持指令的的所有可能组合方式,就会出现资源冲突,从而导致结构冒险;
  • 数据冒险:根据流水线中的指令重叠,指令之间存在先后顺序,如果一条指令取决于先前指令的结果,就可能导致数据冒险;
  • 控制冒险:分支指令及其他改变程序计数器的指令实现流水化时可能导致控制冒险。

转发(forwarding)

转发是一种硬件技术,它的关键是要认识到,在可能导致数据冒险的情况下,后一条指令要等到前一条指令实际生成结果之后才会真正用到它。前一条指令将运算结果放在流水线寄存器中,如果可以把它从这里转移到后一条指令需要的地方,那就可以避免出现停顿。

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

我们需要转发的结果可能不只来自前一条指令,还可能来自提前两个周期启动的指令。

流水线中使用docker 流水线技术_数据_02

需要停顿的数据冒险

并非所有潜在数据冒险都可以通过旁路方式处理,比如使用载入指令结果而产生的数据冒险无法使用简单的硬件消除,因为该指令在MEM周期结束之前不会得到数据。

流水线中使用docker 流水线技术_寄存器_03

为了保持正确,载入指令需要一种称为“流水线互锁”的执行模式。一般情况下,流水线互锁会检测冒险,并在该冒险被清除之前使流水线停顿,让希望使用某一数据的指令等待,直到源指令生成该数据为止。

流水线中使用docker 流水线技术_寄存器_04

延迟分支

分支在五级流水线中会导致一个周期的停顿,延迟分支是处理这个问题的一种编译时机制。

延迟分支的执行周期为:分支指令——依序后续指令——选中时的分支目标。其中依序后续指令位于分支延迟时隙中,无论分支是否被选中,这一指令都会执行。

编译器的任务在于让后续指令有效并可用,因此需要使用一些优化方式:

  • 在延迟时隙内载入分支之前一条不相关的指令,这是最佳选择;
  • 填充分支的目标指令(一般需要复制),循环分支中使用;
  • 填充未被选中的指令,这样必须确保程序能正确执行。

延迟分支调度的局限性在于对可排在延迟时隙中的指令有限制,为了提高编译器填充分支延迟时隙的能力,处理器可以引入一种取消分支。当分支的行为与预期一致时,分支延迟时隙中的指令就像普通的延迟分支一样执行,反之,则转为空操作。

动态分支预测

最简单的分支预测机制是分支预测缓冲区,它是一个小型存储器,会根据分支指令地址的地位部分进行索引。

分支预测缓冲区包含一个位来表明该分支最近是否被选中。这一机制是最简单的缓冲区形式,当分支延迟过长时,它可以用于缩短分支延迟。

采用这样一种缓冲区时,我们事实上并不知道预测是否正确。这种预测就是一种提示,我们假定它是正确的,并在预测方向上开始提取。如果这一提示最终是错误的,那将预测位反转后存回。

缓冲区的性能取决于两点:一是对所关注分支的预测频繁程度,二是该预测在匹配时的准确度。

这样的1位预测机制在性能上有一处短板:即使某个分支总是被选中,在其未被选中时,我们也可能得到两次错误预测,因为错误预测会导致该预测位反转。

为了弥补这一弱点,我们经常使用2位预测机制:预测必须连续错过两次之后才会进行修改。

许多分支被选中和不被选中的概率并非均等,而是严重偏向其中一种状态,对于此类分支,2位预测器的错误预测率经常1位预测器。

对于一个n位计数器,其取值介于0到2n-1之间:当计数器大于或等于其最大值的一半时,分支被预测为选中,否则预测为未选中。对n位预测器的研究已经证明,2位预测器的效果几乎与n位预测器相同,所以大多数系统都采用2位分支预测器,而不是更具一般性的n位预测器。