目录
前言
之前都在准备蓝桥杯,天天嗯刷leetcode,故咕了好久 。。。 蓝桥杯总结也咕了
彳亍
今天还是来更一下实验。这次的实验虽然操作简单,但是其背后的思想却值得回味,让我们对流水线处理的理解更进一步。
流水线处理思想
以洗衣服为例,假设我们有三个步骤:
- 浸泡
- 冲洗
- 烘干
同时我们有三台不同的设备(浸泡桶,洗衣机,干衣机)负责上述的三个步骤。
假设今天有很多件衣服要洗,那么一般的思路是这样的,我们按照顺序一步一步处理每一件衣服:
但是这样顺序执行,有一个缺陷,你看 1 时刻我们进行浸泡操作,而直到 4 时刻 才有新的衣服进来,这意味着浸泡桶摸鱼摸了三个时刻。
要尽量地压榨计算性能,就意味着每个时刻不能有器件在摸鱼!(虽然这很不人道但是二极管是这个世界上最纯粹的打工人,并且缺乏把我们吊路灯的风险。我们只管压榨就完事了。。。)
对于每个器件,我们按照步骤顺序,一但其执行完工作,马上塞新工作给它:
你看:对于浸泡桶来说,在整个洗衣服的流程中,从 1 时刻到 3 时刻,它一直在工作。 这是我们希望看到的!
因为一刻不停的忙活,老板开上了法拉利 我们洗三件衣服的时间开销,由 9 个时刻降低为 5 个时刻,这便是流水线思想的威力!
mips指令之五步走
mips指令为了实现并行地流水线结构,严格地将指令拆分为5个抽象的步骤,他们分别是:
- IF
- ID
- EX
- MEM
- WB
下面给表格,解释一下:
缩写 | 全称 | 解释 |
---|---|---|
IF | instruction fetch | 从内存中取指令 |
ID | instruction decode | 指令解码 或 读寄存器 |
EX | execute | 指令执行 |
MEM | memory | 内存访问操作 |
WB | write back | 将结果写回寄存器 |
流水线冒险
一条完美的流水线就像上文中图片展示的那样,大家各司其职一刻不停。可是实际上并不是这么回事,因为计算机执行指令,不像洗衣服那般简单,因为洗衣服流水线中,衣服之间没有相互的依赖关系!
指令的执行往往依赖于其之前的指令的执行结果!
因为依赖关系的存在,有时候并不能马上执行一条指令,往往得等到其所有用到的条件(比如数据或者硬件)准备就绪,才能开始 。这种流水线阻塞的现象,称之为冒险。
好🐔 儿怪啊这名字
冒险又分为三种,下面细🔒:
数据冒险
当前的指令需要依赖前一条指令的计算结果,比如:
add r1, r2, r3 # r1 = r2 + r3
add r4, r1, r5 # r4 = r1 + r5
第二条 add 指令的执行,依赖于第一条 add 指令运算出的 r1 寄存器的结果,这往往会造成阻塞。
如图,蓝色箭头所指的两个 RAW 即为数据冒险。我们可以看到第二个 add 的 EX 部分,必须等到第一个 add 的 WB 部分执行结束,才能够开始,这表明了数据的依赖性。
解决数据冒险也有三种方式:
- 调整顺序
- 推迟执行
- 前推(fo