计算机组成
7 流水线处理器
7.5 数据冒险的处理
在程序当中,我们经常会对同一个变量进行反复的使用和修改。这样对于流水线处理器来说,就会经常出现数据冒险的情况,我们必须很好的应对和解决。在这一节,我们就来看一看有哪一些不同的解决方法。
我们先来看这个数据冒险的例子。产生这个数据冒险,是因为第二条加法指令会用到第一条减法指令的运算结果。但是在流水线当中,这条加法指令在读取t0寄存器的时候,它前一条减法指令还没有把运算结果写到t0寄存器当中去。所以,这里就存在一个数据冒险。要解决这个数据冒险,最简单的方法,实际上是在软件层面进行解决。
假设我们这个处理器的流水线并不能解决这样的数据冒险。那其实,我们只要通过编程的手段,人为的将这条加法指令推后执行,让他读取寄存器堆的时间推后到减法指令写寄存器堆的时间之后。那这应该怎么做呢?
我们有一条指令叫做nop,它的作用是什么也不干。我们就在这个减法指令和加法指令之间插入两个nop指令。这两个nop指令只是简单的通过流水线,并占用了相对应的时间。那这样刚才的这个数据冒险至少是不存在了。而因为这两个nop指令的作用,加法指令推后了两个周期才进入流水线,那么当这条加法指令需要读寄存器堆的时候,前面减法指令已经完成了对寄存器堆的写,那加法指令就可以从寄存器堆当中读到正确t0的值,从而完成正确的加法运算。所以,解决这个数据冒险最简单的方法就是插入nop指令,但是这个方法也有很大的问题。
首先,到底应该插入几个nop指令,这是和流水线的结构相关的。如果我们这一段程序放在一个5级流水线上是正常运行的。那过几天,又出了一个更新的处理器,它的流水线是8级的,那这个程序放上去,可能运行就会发生错误。因为流水线变深之后,解决数据冒险需要等待的周期数可能会变多。所以,插入nop的这个方法可行&