第15讲-指令周期和指令流水线
指令周期
- 指令周期:处理单个指令的过程(时间)
- 取指周期:从内存中提取一条指令
- 执行周期:执行所提取的指令
- 只有当机器关闭、发生某种不可恢复的错误或遇到停止计算机的程序指令时,程序执行才会停止
- 间址周期
- 指令的执行可能涉及一个或多个存储器中的操作数,它们每个都要求一次存储器访问
- 使用间接寻址,还需要额外的存储器访问
- 间址周期:把间接地址的读取看成是一个额外的指令子周期
- CPU的任务
- 取指令:CPU 必须从存储器(寄存器、cache 、主存)读取指令
- 解释指令:必须对指令进行译码,以确定所要求的动作
- 取数据:指令的执行可能要求从存储器或输入/输出(I/O)模块中读取数据
- 处理数据:指令的执行可能要求对数据完成某些算术或逻辑运算
- 写数据:执行的结果可能要求写数据到存储器或I/O 模块
- CPU需求:寄存器
- CPU需要在指令周期中临时保存指令和数据
- CPU需要记录当前所执行指令的位置,以便知道从何处得到下一条指令
- CPU需要一些小容量的内部存储器
- 假定CPU 有:
- 1个存储地址寄存器(MAR)
- 1个存储缓冲寄存器(MBR)/ 存储数据寄存器(MDR)
- 1个程序计数器(PC)
- 1个指令寄存器(IR)
- 假定CPU 有:
指令流水线
- 流水处理(pipelining):如果一个产品要经过几个制作步骤,通过把制作过程安排在一条装配线上,多个产品能在各个阶段同时被加工
- 指令流水线:一条指令的处理过程分成若干个阶段,每个阶段由相应的功能部件完成
- 两阶段方法
- 将指令处理分成两个阶段:取指令和执行指令
- 在当前指令的执行期间取下一条指令
- 问题:执行时间一般要长于取指时间
- 更多问题
- 主存访问冲突
- 条件分支指令使得待取的下一条指令的地址是未知的
- 超标量流水线(Superscalar)
- 超标量结构:具有两条或两条以上并行工作的流水线结构
- 单周期→标量流水线: 时间并行性的优化, 主要是对现有硬件的分段
- 标量流水线→超标量流水线: 空间并行性的优化, 需成倍增加硬件资源
- 多核CPU:一个CPU 芯片中集成多个超标量处理器核
冒险
-
在某些情况下,指令流水线会阻塞或停顿(stall),导致后续指令无法正确执行
-
类型
- 结构冒险(Structure hazard)/ 硬件资源冲突
- 不同指令同时使用相同的硬件资源,比如访存
- 数据冒险(Data hazard)/ 数据依赖性
- 有些数据要等前序计算完成
- 控制冒险(Control hazard)
- 比如条件转移
- 结构冒险(Structure hazard)/ 硬件资源冲突
-
结构冒险
- 原因:已进入流水线的不同指令在同一时刻访问相同的硬件资源
- 数据冒险
- 原因:未生成指令所需要的数据
- 例如:一条指令需要使用之前指令的运算结果,但是结果还没有写回
- 控制冒险
- 原因:指令的执行顺序被更改
- 转移(Transfer): 分支(branch), 循环(loop),
- 中断(Interrupt)
- 异常(Exception)
- 调用/ 返回(Call / return)
- 影响:
- 转移指令占比15%~25%(平均每隔4~7 条指令)
- 转移平均损失10 个周期
- 流水线越深,超标量数越多,转移指令的影响越大
- 解决方案1:取多条指令
- 多个指令流:复制流水线的开始部分,并允许流水线同时取这两条指令,使用两个指令流
- 预取分支目标:识别出一个条件分支指令时,除了取此分支指令之后的指令外,分支目标处的指令也被取来
- 循环缓冲器:由流水线指令取指阶段维护的一个小的但极高速的存储器,含有n 条最近顺序取来的指令
- 解决方案2:分支预测
- 静态预测(规则不变)
- 预测绝不发生跳转
- 预测总是发生跳转
- 依操作码预测
- 动态预测(规则变化)
- 发生/ 不发生切换
- 转移历史表
- 仅在连续发生两次错误时改变状态
- 例如:有一个双层循环,当内循环进行时,总是预测不跳转,最后一次预测错误。如果一次预测错误就切换,那么下一次进入内循环时会预测跳转,然而实际发生跳转,导致两次预测错误。如果一次错误不切换,只有两次错误才切换,那么内循环结束时仍是预测不跳转,下一次进入内循环将会预测正确,总共只有一个错误预测。
- 静态预测(规则不变)
- 解决方案3:提前判断
- 直接无条件转移:例如j Target
- 在取指阶段即可获得转移目标地址(流水线不停顿)
- 间接无条件转移:例如 jr $r1
- 在译码阶段才能获得转移目标地址(流水线停顿1 周期)
- 直接有条件转移:例如 beq $r1, $r2, Target
- 在执行阶段才能获得转移目标地址(流水线停顿2 周期)
- 在寄存器堆输出端增加额外的比较电路(流水线停顿1 周期)
- 直接无条件转移:例如j Target
- 解决方案4:交换指令顺序
- 原因:指令的执行顺序被更改