【CO101】计算机组成原理笔记6 —— 流水线处理器冒险问题

笔者:YY同学

生命不息,代码不止。好玩的项目尽在GitHub



为什么会产生冒险?

流水线以多周期处理器为基础,按照阶段划分,单个周期内可能会同时处理多条指令。在这样复杂而又紧密快速的运行环境下,就会出现一些不可能避免的冲突,也就是我们所说的冒险。


三类冒险问题

1. 结构冒险(Structural Hazard)
  • 同 cycle 同阶段冲突
    在这里插入图片描述

因指令不同导致 clock cycle 不同,导致相同阶段在同一个 clock cycle 中出现。然而在同一 cycle 内,一个阶段仅允许处理一条指令,因此会产生冲突。例如,上图中第三条 lw 指令与第四条 or 指令在 cycle 7 时都是 WB,则会产生结构冒险。


如何解决?
其实非常容易,只需要保证每一条指令永远都有 5 个阶段就可以了,对于那些缺失阶段数的指令,我们插入一条 NOP 指令。NOP 指令是一条空指令,例如 or $0, $0, $0 这条指令就是空指令,因为它的机器码产生的控制信号全部为0,所以处理器相当于不会干任何事情。
在这里插入图片描述


  • Memory 访问冲突
    在这里插入图片描述

事实上,在 IF 阶段,指令获取将会访问内存,而 MEM 阶段(如有)指令也会访问内存,此时就有可能造成冲突。


解决方案:采用哈佛结构设计理念,将程序指令存储和数据存储分开,使得各自独立访问,从而解决冲突。


  • Register 读写访问冲突
    在这里插入图片描述

对于同一寄存器而言,ID 阶段会读取寄存器的值,而 WB 阶段需要将值写回寄存器,因此产生访问冲突。


解决方案:我们规定用时钟上升沿触发 Write,下降沿触发 Read,从而将这两类冲突完全分开。


2. 数据冒险(Data Hazard)
  • Register 数据读写顺序引起的冒险
    在这里插入图片描述

如图,第一条指令的 $2 地址在 WB 阶段被赋值,但是第二条指令在 ID 阶段就需要获取 $2 的值,理论上 WB 阶段需要在 ID 阶段之前执行,但是我们能很清楚地发现在 clock cycle 图中,ID 阶段显然位于 WB 阶段之前,此时就会造成读写顺序不符合逻辑而引起的数据错误。


怎么办?
其实通过观察我们发现,第一条指令中 $2 的值其实在 EX 阶段就已经计算得出了(参考单周期处理器流程)。而对于第二条指令,$2 真正被使用的阶段也是在 EX 阶段,而这两个阶段位于不同的 cycle,并且顺序也是完全正确的。
在这里插入图片描述
那么如何将上一个 EX 阶段的数据传递到下一个 EX 阶段呢?
这里就需要介绍一下我们的转发(Forwarding)技术:相当于将计算好的数据通过额外的一条数据通路输送到对应的地方,并且这条数据通路由控制信号严格把控,如下图:
在这里插入图片描述
这样问题就解决了。需要注意的是,lwsw 这两条指令可以如下图方式转发:
在这里插入图片描述


  • 真正的数据冒险(True Data Hazard)
    在这里插入图片描述

有一类数据冒险是不能通过转发的方式解决的,此类冒险我们称之为 真正的数据冒险。在图中我们可以发现:lw 指令中,$2 最早产生于 WB 阶段,但是在 and 指令中最迟 EX 阶段就需要使用,很明显 EX 阶段在 WB 阶段之前,因此无法使用转发来解决问题。


那么有没有解决方案呢?
答案是有的,那就是停顿流水线(stall)。流水线停顿对于冒险问题虽然是一个万能的 solution,但是停顿流水线将意味着处理器宕机,停顿次数越多,处理器的效率就会越低下。因此不到万不得已,我们一般不采用流水线停顿的做法来解决冒险问题。
在这里插入图片描述
如图,lw 指令和 and 指令之间有一个停顿。


3. 控制冒险(Control Hazard)
  • Jump 指令停顿
    在这里插入图片描述

在流水线处理器中如果遇到 jump 指令,处理器是没有办法 100% 找到需要跳转指令的准确地址,因为有可能这条指令已经被清空了(flush),也有可能甚至还没有进入 IF 阶段。因此此类冒险只能通过停顿流水线解决。


解决方案:流水线停顿。


  • Branch 指令预测
    在这里插入图片描述

对于 Branch 指令,我们在 ID 阶段就能准确知道需要跳转指令的地址(不同于 jump,branch 的跳转地址是根据离自己的距离而定的),但是我们不知道两个比较的寄存器的值是否存在数据冒险,因此无法立刻判断是否要跳转。
在这里插入图片描述
解决方案:
分支预测。我们一般采用动态预测(Dynamic Prediction)方式给出控制信号来提前决定此时此刻是否需要跳转指令。由于判断比较的两个寄存器值的延后性,预测结果可能正确也可能错误。如果预测正确,那显然就是我们希望的结果;但如果预测错误,则改用流水线停顿的方法进行补救。采用这种 预测+停顿 双管齐下的方式,相比于单纯的让流水线停顿,平均效率要提升不少。这就好比考试时面对不会做选择题,乱蒙一个答案可能比交白卷的分数要高。


小结

三类冒险问题各有特点:
结构冒险是完全可以被解决的冒险,现在几乎所有的处理器在制成上都已经完全解决了结构冒险;对于数据冒险,大部分可以通过转发的方式轻松解决,仅有少部分 lw 指令和 R-Type 指令连续出现的情况需要通过停顿流水线来解决;由于 JumpBranch 指令本身出现的概率比较低(大概在10%~15%左右),控制冒险本身出现的机会也比较少,因此不管是停顿流水线还是分支预测,对流水线处理器的处理效率影响也非常小。

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
1. 处理器的基本结构 处理器是计算机中最重要的组成部分之一,它负责执行指令、存储和处理数据。处理器的基本结构包括运算器、控制器、寄存器、存储器和总线。 - 运算器:负责执行算术和逻辑运算,包括加法、减法、乘法、除法、与、或、非等操作。 - 控制器:负责管理指令的执行顺序和处理器的操作模式,包括指令译码、指令执行、分支控制、中断处理等。 - 寄存器:处理器内部的一种高速存储器,用于暂时存储指令和数据。常见的寄存器包括累加器、程序计数器、指令寄存器等。 - 存储器:计算机用于存储程序和数据的设备,包括内存、硬盘、U盘等。 - 总线:计算机内部各个组成部分之间传输数据和指令的通道,包括地址总线、数据总线和控制总线。 2. 处理器的指令集和编程模型 处理器的指令集是处理器能够执行的操作的集合,包括算术操作、逻辑操作、传输操作等。不同的处理器有不同的指令集,例如x86指令集、ARM指令集等。 编程模型是指程序员在编写程序时所使用的抽象模型,它描述了程序员如何使用处理器的指令集来编写程序。常见的编程模型包括传统的CISC模型和现代的RISC模型。 3. 处理器的性能指标 处理器的性能指标包括时钟频率、IPC、吞吐量和延迟等。 - 时钟频率:处理器内部时钟的运行频率,通常以GHz为单位。 - IPC(Instructions Per Cycle):每个时钟周期内处理器执行的指令数量。 - 吞吐量:单位时间内处理器能够执行的指令数量。 - 延迟:指令从发出到执行完成所需要的时间。 4. 处理器的发展历程 处理器的发展历程经历了从单核心到多核心的演变,以及从CISC模型到RISC模型的转变。 - 单核心处理器:早期的计算机使用单核心处理器处理器的性能主要依赖于时钟频率的提升。 - 多核心处理器:随着计算机应用的发展,多核心处理器逐渐被引入计算机中,可以同时执行多个任务,提高了计算机的并行处理能力。 - RISC模型:在处理器的指令集设计上,RISC模型强调简洁、规范的指令集,使得处理器的设计更加高效,提高了处理器的性能。 5. 处理器的未来发展方向 处理器的未来发展主要集中在以下几个方向: - 集成度的提高:将更多的处理器核心、缓存、内存控制器等集成到处理器中,提高处理器的性能。 - 异构计算:在处理器中引入异构计算单元,例如GPU、FPGA等,提高处理器的计算能力。 - 量子计算:引入量子计算的技术,实现更高效的计算处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值