简介

  • 这里的流水线技术主要是指令流水线
  • 将一条指令的执行过程拆分成多个独立的阶段,在一个时钟周期(本人认为,这里的时钟周期表示的含义更接近 机器周期,指完成一个指令内部阶段所耗费的时间; 机器周期这一概念被 阶段(逻辑划分)时钟周期(时间单位划分) 淡化了)下,有多条指令的阶段同时执行,优化指令的执行效率

流水线模型

根据指令阶段划分给出模型,例如 取指 -> 译码 -> 执行 3级模型;

在此给出的是在 RISC 架构中比较常见的5级流水线模型: 取指(IF) -> 译码(ID) -> 执行(EX) -> 访存(MEM) -> 写回(WB)

  1. 取指: 从指令存储器读取下一条要执行的指令
  2. 译码: 对指令解码,转换成相关的控制信号
  3. 执行: 根据控制信号做相关的操作,包含访存地址计算等
  4. 访存: 指令为加载(load)时,从内存读取数据; 指令为存储(store)时,将数据存储到内存中
  5. 写回: 将执行结果写回到目标寄存器或存储器中(一般是寄存器,写内存的话一般在第4点完成)

指令执行方式

预设

  • k级流水线模型
  • 各个阶段的执行时间相同,均为t
  • 流水线模式下,每个时钟周期下都有一条指令进入流水线

串行执行(非流水线方式)

串行执行

  • 单条指令执行时间: T=ktT = kt
  • n条指令执行时间: T1=kntT_{1} = knt
  • 吞吐率(单位时间内完成的指令数量): Th1=nT1=1ktTh_{1} = \frac{n}{T_{1}} = \frac{1}{kt}

流水线方式

流水线

  • 单条指令执行时间: T=ktT = kt
  • n条指令执行时间: T2=(n1)t+kt=(n+k1)tT_{2} = (n - 1)t + kt = (n + k - 1)t
  • 吞吐率(单位时间内完成的指令数量): Th2=nT2=n(n+k1)tTh_{2} = \frac{n}{T_{2}} = \frac{n}{(n + k - 1)t}
    • nn \to \infty 时,Th2=1tTh_{2} = \frac{1}{t} ,理想流水线吞吐率为每个时钟周期完成一条指令(流水线填满后,没有冲突时是这个状态)
  • 加速比(衡量流水线相对于串行模式的性能提升倍数): S=T1T2=knt(n+k1)t=knn+k1k(n>>k)S = \frac{T_{1}}{T_{2}} = \frac{knt}{(n + k - 1)t} = \frac{kn}{n + k - 1} \approx k(n >> k)
  • 效率(流水线中的指令占用的时空区域和流水线整体的时空区域的比值, 时空区域: 图中的坐标轴围成的区域):
    E=kntk(n+k1)t=nn+k11(n>>k)E = \frac{knt}{k(n + k - 1)t} = \frac{n}{n + k - 1} \approx 1(n >> k) ,当 n 远大于 k 时,流水线的效率趋近于 1,即流水线整体处于忙碌状态

现实因素对性能指标计算的影响

  • 各个阶段的执行时间不一定相同,多个阶段有相对较慢的阶段,这个会导致其它阶段处于等待中
  • 流水线冒险/冲突导致的停顿
  • 处理器会提前对程序做分支预测,当分支预测错误时,会导致后续多条指令错误执行,处理器会清空原先的计算结果(涉及多个时钟周期执行的内容),转到正确的分支上执行,影响性能

流水线冒险(Pipeline Hazards)

在流水线中可能由某些因素,导致下一个时钟周期中下一条指令不能执行(流水线断流),影响流水线的效率

5级流水线模型

结构冒险(Structural Hazards)

  • 硬件资源导致的存取/读写冲突(硬件不支持多条指令在同一时钟周期内执行)

  • 例: 下图中展示的是 取指 和 访存 同时读取内存可能存在的冲突
    Structural Hazards

  • 解决方法

    • 流水线停顿,产生空泡(bubbles)(取指操作延迟一个时钟周期执行)
    • 分离指令存储器和数据存储器
    • 采用双端口存储器

数据冒险(Data Hazards)

  • 一条指令依赖前一条指令的运算结果(局部性冒险)

  • 例: 下图展示的是执行 EX 阶段指令依赖上一条需要执行 MEM 指令(存储)的数据
    Data Hazards

  • 解决方法

    • 流水线停顿/互锁,产生空泡(bubbles)(EX 操作延迟一个时钟周期执行)
    • 数据旁路/转发

控制冒险(Control Hazards)

  • 处理器在取指阶段末尾才能确定分支是否成功,但在此期间已经顺序读取了下一条指令,导致存在风险(控制流改变,全局性冒险)
  • 解决方法
    • 流水线停顿,等到分支确定后(EX 阶段执行后得到结果)再恢复
    • 静态预测,预测永远跳转/不跳转(准确率相对较低)
    • 动态预测,处理器根据分支的历史行为动态进行预测
      • 使用复杂的分支预测逻辑判断分支是否成功(选择概率高的分支,预测错误时清空所有错误执行的指令以及产生的结果)
    • 延迟分支,编译器重新排列指令顺序,在分支指令之后插入一条(或几条)无论分支是否成功都会执行的指令

其它

  • 超标量流水线: 每个时钟周期向流水线发射多条指令,并能从流水线流出多个结果
  • 超流水线技术: 把一般完成一条指令的流水线段再细分成更多的流水线段。这样原时钟周期的几分之一的时间间隔就可以发射一条指令,并从流水线流出一个结果