14_指令周期和指令流水线

Charlie

1. 指令周期

处理单个指令的过程

  • 取指周期:从内存中提取一条指令
  • 执行周期:执行所提取的指令

1.1. 指令周期

89_VoIPSCreencastCoverWnd.png

1.1.1. 状态图

8a_VoIPSCreencastCoverWnd.png

1.2. 带中断的指令周期

8b_VoIPSCreencastCoverWnd.png

1.2.1. 状态图

8c_VoIPSCreencastCoverWnd.png

1.3. 间址周期

  • 间址周期:把间接地址的读取看成是一个额外的指令子周期
    • 指令的执行可能涉及一个或多个存储器中的操作数,它们每个都要求一次存储器访问
    • 使用间接寻址,还需要额外的存储器访问
    • 相当于取了两次操作数
      8d_VoIPSCreencastCoverWnd.png

1.3.1. 状态图

8e_VoIPSCreencastCoverWnd.png

1.4. CPU

1.4.1. CPU任务

  1. 取指令:CPU必须从存储器(寄存器、cache、主存)读取指令
  2. 解释指令:必须对指令进行译码,以确定所要求的动作
  3. 取数据:指令的执行可能要求从存储器或输入/输出(I/O)模块中读取数据
  4. 处理数据:指令的执行可能要求对数据完成某些算术或逻辑运算
  5. 写数据:执行的结果可能要求写数据到存储器或I/O模块

1.4.2. CPU需求

  • 寄存器:小容量内部存储器
    • CPU需要在指令周期中临时保存指令和数据
    • CPU需要记录当前所执行指令的位置,以便知道从何处得到下一条指令

假定CPU有

  • 1个存储地址寄存器(MAR)
  • 1个存储缓冲寄存器(MBR)/ 存储数据寄存器(MDR)
  • 1个程序计数器(PC)
  • 1个指令寄存器(IR)

数据流

取指周期

NVIDIA_Share_957_704.png
NVIDIA_Share_921_676.png
NVIDIA_Share_918_669.png
NVIDIA_Share_876_684.png

间址周期

NVIDIA_Share_966_667.png
NVIDIA_Share_1008_632.png

中断周期

NVIDIA_Share_1001_607.png
NVIDIA_Share_958_622.png
NVIDIA_Share_966_614.png

指令流水线

  • 指令流水线:一条指令的处理过程分成若干个阶段,每个阶段由 相应的功能部件完成

二阶段方法

  • 将指令处理分成两个阶段:取指令和执行指令
  • 在当前指令的执行期间取下一条指令
    NVIDIA_Share_867_174.png

问题

  • 执行时间一般要长于取指时间
  • 主存访问冲突
  • 条件分支指令使得待取的下一条指令的地址是未知的
    NVIDIA_Share_853_322.png

六阶段方法

  • 更多阶段

    • 取指令(Fetch instruction,FI):读下一条预期的指令到缓冲器
    • 译码指令(Decode instruction,DI):确定操作码和操作数指定符
    • 计算操作数(Calculate operands,CO):计算每个源操作数的有效地址
    • 取操作数(Fetch operands,FO):从存储器取出每个操作数,寄存器中的操作数不需要取
    • 执行指令(Execute instruction,EI):完成指定的操作。若有指定的目的操作数位置,则将结果写入此位置
    • 写操作数(Write operand,WO):将结果存入存储器
  • 各阶段时间几乎相等

  • 例子:NVIDIA_Share_1002_628.png

问题

  • 不是所有指令都包含6个阶段
    • 例:一条LOAD指令不需要WO阶段
    • 为了简化流水线硬件设计,在假定每条指令都要求这6个阶段的基础上来建立时序
  • 不是所有的阶段都能并行完成
    • 例:FI、FO和 WO都涉及存储器访问
  • 若6个阶段不全是相等的时间,则会在各个流水阶段涉及某种等待

限制

  • 条件转移指令能使若干指令的读取变为无效NVIDIA_Share_701_471.png

  • 中断
    NVIDIA_Share_535_737.png

NVIDIA_Share_607_570.png

I3为跳转指令

流水线性能

NVIDIA_Share_1122_577.png
NVIDIA_Share_1002_379.png

  • 误解
    • 流水线中的阶段数越多,执行速度越快
  • 原因
    • 在流水线的每个阶段,将数据从一个缓冲区移动到另一个缓冲区以及执行各种准备和传递功能都涉及一些开销
    • 处理内存和寄存器依赖以及优化管道使用所需的控制逻辑数量随着阶段的增加而急剧增加

冒险(Hazard)

  • 在某些情况下,指令流水线会阻塞或停顿(stall),导致后续指令无法正确执行

结构冒险(Structure hazard)

  • 硬件资源冲突
  • 原因:已进入流水线的不同指令在同一时刻访问相同的硬件资源
  • 解决:使用多个不同的硬件资源,或者分时使用同一个硬件资源

NVIDIA_Share_1129_375.png

数据冒险(Data hazard)

  • 数据依赖性
  • 原因:未生成指令所需要的数据
    NVIDIA_Share_763_433.png

解决方案

NVIDIA_Share_975_600.png
NVIDIA_Share_949_613.png
NVIDIA_Share_988_601.png
NVIDIA_Share_1065_616.png

控制冒险(Control hazard)

  • 原因:指令的执行顺序被更改
    • 转移(Transfer): 分支(branch), 循环(loop), …
    • 中断(Interrupt)
    • 异常(Exception)
    • 调用 / 返回(Call / return)

解决:取多条指令

  • 多个指令流:复制流水线的开始部分,并允许流水线同时取这两条指令,使用两个指令流
  • 预取分支目标:识别出一个条件分支指令时,除了取此分支指令之后的指令外,分支目标处的指令也被取来
  • 循环缓冲器:由流水线指令取指阶段维护的一个小的但极高速的存储器,含有 n 条最近顺序取来的指令

解决:分支预测

  • 静态预测
    • 预测绝不发生
    • 预测总是发生
    • 依操作码预测
  • 动态预测
    • 发生 / 不发生切换
    • 转移历史表

NVIDIA_Share_1013_617.png
NVIDIA_Share_925_623.png

  • 标题: 14_指令周期和指令流水线
  • 作者: Charlie
  • 创建于 : 2023-02-06 20:08:00
  • 更新于 : 2024-07-05 12:55:04
  • 链接: https://chillcharlie357.github.io/posts/5ece27c9/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论