计算机组成原理12——冒险和预测

冒险和预测

流水线的设计,会带来性能的提升,也会带来相应的冒险。冒险有三种:结构冒险、数据冒险、控制冒险。

结构冒险

在这里插入图片描述

  • 如上图在第一条指令执行到访存的时候,第四条指令执行取指操作。而访存和取指,都要进行内存数据的读取,但是内存只有一个地址译码器作为地址输入,所以没办法同时执行第一条指令的访存和第四条指令的取指操作。

内存的访问速度比CPU慢的多,所以现代CPU不会直接读取主内存。它会从主内存把指令和数据加载到高速缓存中,所以后序的访问就都是访问高速缓存。可以通过这一点来解决结构冒险。

解决方法:

直观的解决方法就是把我们的内存分成两部分,分别是存放指令的程序内存存放数据的数据内存。但我们不这样干。类似的我们在CPU的高速缓存中,把高速缓存分成指令缓存和数据缓存。这样我们的CPU在进行数据和指令的同时访问时,不会再发生资源冲突。

在这里插入图片描述

数据冒险

就是同时在执行多个指令之间,有数据依赖的情况。这些数据依赖有三大类,先写后读、先读后写、写后再写

  • 先写后读

    int main(){
    	int a = 1;
    	int b = 2;
    	a = a + 2;
    	b = a + 3;
    }
    

    ​ 我们需要保证在完成代码“b = a + 3”时必须要完成它的上一条代码。这个顺序如果保证不了,程序就会出错。

  • 先读后写

    int main(){
    int a = 1;
    int b = 2;
    a = b + a;
    b = a + b;
    }
    

在这里插入图片描述

在内存地址为15的汇编指令中,要将eax中的值读出来加到rbp-0x4的内存地址里。然后内存地址为18的汇编指令又跟新了eax寄存器中的值。

如果先更新了寄存器中的值,那么程序计算就会出错。

  • 写后再写

    int main(){
    	int a = 1;
    	a = 2;
    }
    

    如果先执行第二行,那么程序就会出错。

流水线架构的核心,就是在前一个指令还没有结束的时候,后面的指令就要开始执行。而我们的数据冒险,都有明确强制的顺序要求,我们该如何解决?

解决方法:流水线停顿

流水线停顿,也叫流水线冒泡。我们在指令译码的时候,就能够判断出来是否有数据冒险。如果前后指令之间有数据依赖,我们可以通过“等待”来解决这个问题。

在这里插入图片描述

这里的停顿/冒泡就是插入一个NOP操作——什么都不干的操作。

NOP操作和指令对齐

以MIPS+5级流水线为例,有的指令是不需要流水线阶段中每一个阶段。这样就可能导致结构冒险发生。我们可以通过NOP操作和指令对齐来解决这个问题。

在这里插入图片描述
在这里插入图片描述

解决方法:操作数前推

先来看两条指令

add $t0,$s2,$s1
add $s2,$s1,$t0

第一条指令是把寄存器s1和s2数据相加,存到t0寄存器

第二条指令是把寄存器t0和s1数据相加,存到s2寄存器,流水线如下图

在这里插入图片描述

可以看出,我们先将数据写入了t0,然后再从t0中读。我们是否可以把这个过程简化?

我们完全可以在第一条指令的执行阶段完成后,直接将结果数据传输给到下一条指令的ALU,就省略了写入t0和读出t0的这两步操作。这样我们就不需要再插入两个NOP阶段。这样的解决方法叫做,操作数前推

在这里插入图片描述

不管是流水线停顿还是操作数前推,还是会有NOP操作拉低CPU的吞吐率,如何能让NOP时候的CUP运作起来?

答:乱序执行

来看这三行代码

a = b + c
d = a * e
x = y * z

计算x,根本不需要等待a和d都计算完成。x没有数据依赖,完全可以先把x计算出来。

在这里插入图片描述
可以看到第三条指令没有数据依赖,在第二条指令等待第一条指令的访存和写回阶段的时候,第三条指令已经执行完成。这样的解决方案是乱序执行

使用乱序执行的技术后,CPU里的流水线长什么样子?

在这里插入图片描述

  1. 在取指和译码阶段,乱序执行的CPU和其他使用流水线架构的CPU是一样的。
  2. 但是在译码完后就不一样了。CPU不会直接进行指令执行,而是进行一次指令分发,把指令分发到一个叫保留站地方。
  3. 这些指令不会立即执行,而是等待它们要操作的数据,传递给它们才会执行。
  4. 一旦数据都到齐之后,就移交给ALU执行。但是不同的ALU能够支持的指令并不相同。
  5. 指令的执行阶段完成后,不把他们马上写回寄存器,而是把结果存到一个叫重排缓冲区的地方。
  6. 在重排缓冲区里,CPU会按照取指的顺序,对指令的计算结果重新排序,只有排在前面的指令都完成,才会提交指令,完成整个指令的运算结果(上述程序的乱序运算顺序是 x->a->d,提交顺序仍然是 a->d->x)。
  7. 最后指令的计算结果,不直接写到内存或者高速缓存里,而是先写入存储缓冲区,最终才会写入到高速缓存和内存里。

控制冒险

jmp指令执行的时候,CPU可能会跳转去执行其他指令,jmp指令后面的那一条指令是否按顺序执行,在流水线里面进行取指令的时候,我们没法知道。也就是说必须等待jmp指令执行完成,更新了PC寄存器我们才能知道是否执行下一条指令

为了确保得到正确的指令,我们必须等待。这就是控制冒险

解决方法:

  • 缩短延迟时间

    这是一种改造硬件的办法,通过增加旁路,将执行阶段的条件判断,地址跳转,提前到指令译码阶段。这样就能缩短延迟的时间了。

  • 静态预测

    就是让CPU预测一下,下一条指令是否执行。我们规定**“假装分支部分发生”**。这样就会有50%的正确率。如果预测正确,那么就节省了时间。如果没有成功,就需要把后面已经执行的指令的部分丢弃掉。

  • 动态预测

    • 一级分支预测,也叫1比特饱和记数。就是用一个比特来记录当前分支的情况,去预测下一次分支的情况。(今天下雨,就预测明天也一定会下雨。今天不下雨,明天也一定不下雨)
    • 二级分支预测,就是用两个比特位记录四种状态。
      在这里插入图片描述
  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
计算机组成原理模板块容量: 模板块容量是指一个存储芯片中存储单元的数量。在计算机组成原理中,模板块通常是指存储器芯片。存储器芯片中存储单元的数量取决于芯片的物理结构和制造工艺。 常见的存储器芯片有静态随机存储器(SRAM)和动态随机存储器(DRAM)。SRAM通常比DRAM速度更快,但是成本更高。因此,在实际应用中,需要根据不同的需求选用适当的存储器芯片。 计算机组成原理习题——带答案: 1. 什么是冯·诺依曼体系结构? 答:冯·诺依曼体系结构是指一种将程序指令和数据存储在同一存储器中,并通过总线进行传输的计算机体系结构。冯·诺依曼体系结构的特点是程序和数据存储在同一存储器中,采用存储程序的方式控制计算机的运行。 2. 什么是指令周期? 答:指令周期是指执行一条指令所需的时间。指令周期包括取指周期、译码周期、执行周期和写回周期等阶段。 3. 什么是中断? 答:中断是指计算机在执行程序的过程中,由于外部事件的发生(如输入输出操作、时钟信号等)而打断原有的程序执行流程,转而去执行与中断事件相关的特殊处理程序的一种机制。 4. 什么是流水线? 答:流水线是指将一个复杂的操作分为多个子操作,并且将这些子操作以一定的次序组织起来,使得每个子操作在不同的处理器件上并行执行,从而提高处理速度和效率的一种技术。 5. 什么是Cache? 答:Cache是指高速缓存存储器,它是计算机系统中的一种存储器层次结构。Cache存储器通常位于CPU和主存储器之间,用于缓存主存中频繁访问的数据和指令,从而提高计算机系统的性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一直饿着肚子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值