汪道之

有人的地方就有江湖

0%

系统结构第三章_流水线

流水线的基本概念

1. 什么是流水线

定义:流水线是利用执行指令操作之间的并行性,实现多条指令重叠执行的技术

1.1 术语

流水段(流水级):完成一条指令的一部分操作

机器周期(流水线周期):指令沿流水线移动一个流水段的时间。长度取决于最慢的流水段,一般是一个时钟周期(有时是两个时钟周期)。每个流水线周期从指令流水线流出一条指令

吞吐量:单位时间从流水线流出的指令数

流水线设计者:平衡每个流水段的时间,使之等长。因此,每条指令在流水线的平均执行时间在理想情况下为:非流水线机器平均指令执行时间/流水线机器段数

流水线加速比:非流水线机器平均指令执行时间/流水线机器平均指令执行时间

理想情况:流水线加速比=流水线机器段数

1.2 特点

  1. 类似自动装配线
  2. 有多个段(级),段间有流水线寄存器
  3. 每个流水段执行指令或操作的不同部分
  4. 流水段之间采用同步时钟控制
  5. 流水线是开发串行指令流中并行性的一种实现技术

2. RISC指令系统的特点

  1. 所有参加运算的数据来自寄存器,结果也写入寄存器,寄存器为32/64位
  2. 访存只有loadstore指令
  3. 指令的类型较少,所有指令长度相同
  4. 不同指令执行的时钟周期数差别不大

3. 非流水线方式下RISC指令系统的实现

3.1 多周期CPU实现

假定指令系统是MIPS的一个定点子集:load/store指令,ALU指令,转移指令

一条指令的执行过程最多需要5个时钟周期:CPI=5

图示:

image-20210504195556778

电路图示:

image-20210504195639490

上图分析:

  1. IF:Instruction fetch cycle

    1. 按照PC内容访问指令存储器,取出指令
    2. PC+4→NPC,以获取下一条指令地址
  2. ID:Instruction decode/register fetch cycle

    1. 指令译码
    2. 读寄存器
    3. 如果需要,则符号扩展指令中的位移量
  3. EX:Execution(执行)/effective address cycle

    • Load/Store:计算数据存储器有效地址
    • R-R/R-I ALU:执行运算操作
    • Branch:做“=0?”测试,并置条件,计算目标地址
  4. MEM:Memory access

    • Load:送有效地址到数据存储器,取数据
    • Store:写ID,读出数据到有效地址单元中
    • Branch:如果条件满足计算目标地址送PC;否则NPC送PC
  5. WB:Write-back cycle

    • Load or ALU:写结果到寄存器堆

3.2 多周期实现的改进

  1. 对于Branch,将“=0?”测试和计算可能的转移目标地址提前到ID
  2. 完成ALU指令在MEM cycle

图示:

image-20210504201717892

  1. 改进硬件冗余

    1. ALU可以共享
    2. 数据和指令存储器可以合并

4. 经典5段流水线RISC处理器

4.1 特点

  1. 5个段构成一个指令流水线,一条指令经过每个段
  2. CPI减小到1,因为平均每个时钟周期发射或完成一条指令
  3. 在任意时钟周期,在每个流水段正执行一条指令的部分
  4. 理想情况下,性能提升5倍

图示:

image-20210504202456375

4.2 实现

为了实现,在每两段之间新增流水线寄存器,其作用:

  1. 在本周期提供流水段中指令操作的数据及控制信息
  2. 周期结束时,存指令操作结果供下一个流水段指令使用

如下图蓝色部分:

image-20210504203103762

4.3 对比

  1. 对比单周期实现,流水线减少了时钟周期长度

    image-20210504203333003

  2. 对比多周期实现,流水线减少了CPI

    image-20210504203357254

4.4 问题

4.4.1 存储器访问冲突

结构冒险(structure hazard):在同一时钟周期不同操作使用同一数据通路资源

图示:

image-20210504203832540

解决:使用分开的指令cache和数据cache

图示:

image-20210504204140731

注意:如果时钟周期不变,流水线存储系统的带宽必须是非流水线的5倍

4.4.2 寄存器冲突

图示:

image-20210504204333445

解决:重新设计寄存器堆资源

  1. 允许在一个时钟周期WB段先写,ID段后读

    每个时钟周期完成2个读和一个写

    需要提供两个读端口和一个写端口

    当写和读同一个寄存器会发生数据冒险(Data hazard)

4.4.3 更新PC时冲突

每个时钟周期必须增量PC并存储到PC

遇到转移指令时可能会改变PC的值,可能会产生控制冒险(Control hazard)

5. 流水线的基本性能

  1. 增大了吞吐量(单位时间完成指令条数)
  2. 每一条指令的执行时间没有加快
  3. 延迟:附加的控制增加了开销
  4. 不平衡:流水线各段时间以最慢的为准
  5. 附加开销:流水线寄存器
  6. 流水线冒险:串行机器不会产生冒险
  7. 填充和排空:会减小加速比

流水线的主要障碍-流水线冒险(相关)

1. 冒险分类与有停顿流水线性能

1.1 冒险分类:

  1. 结构冒险:指令重叠执行时,发生硬件资源冲突
  2. 数据冒险:几条指令重叠执行时,后面指令依赖前面指令的结果却没有准备好(没有计算或存储)
  3. 控制冒险:发生在流水线执行转移指令时,在进入ID段时,转移条件和转移目标地址不能按时提供给IF段取下一条指令

冒险出现时:避免流水线上有冒险的指令执行下一个流水段

冒险总是可以用停顿(流水线气泡/气泡)解决:停顿时,其后的所有指令被停顿,指令之前的指令继续执行,没有新的指令被取到流水线

图示:

image-20210504211313154

1.2 有停顿的流水线性能

加速比公式:

image-20210504211507892

流水线CPI=理想CPI(≈1)+平均每条指令的停顿周期数

忽略流水线时钟周期的额外开销,并假设流水段是平衡的,则:非流水线时钟周期=流水线时钟周期

最终得:

image-20210504212021602

2. 结构冒险:流水段竞争

2.1 定义

发生在同一时钟周期,2条或多条指令想要使用同一硬件资源

2.2 出现情况

  1. 多重访问寄存器堆
  2. 多重访问存储器
  3. 没有或没有充分流水功能部件

2.3 解决

  1. 寄存器堆的多重访问

    图示:

    image-20210504213234617

    方法1.:简单插入一个停顿,将降低加速比

    方法2:在一个时钟周期WB段先写,ID段后读

    image-20210504213429124

  2. 多重访问单端口存储器

    图示:

    image-20210504213646077

    方法1:插入停顿

    image-20210504213806538

    方法2:提供另一个存储器端口

    方法3:分开指令存储器和数据存储器

    image-20210504213843051

    方法4:使用指令缓冲器

  3. 没有完全流水化的功能部件

    image-20210504214056065

2.4 认识

结构冒险是被允许的,为了减少成本、减少部件延迟

3. 数据冒险

3.1 定义

由于流水线上指令重叠执行,改变了原来串行执行的读/写操作数顺序,使得后面依赖前面指令结果的指令得不到准备好的数据

3.2 解决

不要让指令在数据冒险时重叠执行

3.3 实施

流水线停顿

软件:

image-20210505153243028

硬件:

增加硬件互锁(Interlock)

增加额外硬件检测需要停顿的情况

增加额外硬件放“气泡”(暂停)到流水线

image-20210505153751740

3.4 Forwarding(前推、直通、转发、相关数据通路)

有数据冒险指令需要的结果可能已经计算出来,存放在流水线寄存器中,所以我们可以在数据通路中增加数据线(buses)传送这些结果,这些buses总是从后面的流水段连接到前面的流水段

图示:

image-20210505154733078

image-20210505155325030

image-20210505155531924

image-20210505155617247

image-20210505155645091

没有Forwarding和有Forwarding的比较:

image-20210505155812070

image-20210505155823248