新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 从4004到core i7:处理器的进化史(3)-4-第一次加速

从4004到core i7:处理器的进化史(3)-4-第一次加速

作者: 时间:2014-02-19 来源:摘自《果壳小组》网 收藏

  假设我们的带流水线恰好就有5个环节分别完成以上的5个步骤,那么在上面的代码中,某时刻:

本文引用地址:https://www.eepw.com.cn/article/233547.htm

  [ID] mov reg2,reg1
  [OC] mov reg1,1
  [EX] nop
  [WB] nop

  下一时刻如果是这样:

  [OC] mov reg2,reg1
  [EX] mov reg1,1
  [WB] nop

  就会产生错误:在OC环节进行的是读,我们本来应该读到reg1=1,但是上面的情况中由于reg1=1没有WB,我们读到了reg=0!

  正确地处理应该是这样:

  [ID] mov reg2,reg1
  [OC]nop
  [EX] mov reg1,1
  [WB] nop

  ----------------------------

  [ID] mov reg2,reg1
  [OC]nop
  [EX] nop
  [WB] mov reg1,1

  -----------------------------

  [OC] mov reg2,reg1
  [EX] nop
  [WB] nop

  ----------------------------

  [EX] mov reg2,reg1
  [WB]nop
  ...

  上面的情况叫做数据依赖(data dependency),是降低流水线性能的主要原因。我们对数据依赖的解决办法很简单:

  对流水线中的指令更改的、内存都做记录。在OC环节进行审查,如果该指令读取的、内存没有挂起的更改(没有还没有WB的更改),就执行读取,否则便要等待直到最近的一条更改读取的指令的WB执行之后才能执行。

  对于内存的更改的实际情况要更复杂些,在这个帖子中先不讲,留到后面和超标量网络一起叙述。

  在上面的等待过程中,我们在流水线中插入了一些nop指令,这种现象叫做空泡(bubble)。不难想象,在某些有着20多级流水线的中的bubble常常长达十几个环节。

  数据依赖产生的最严重的空泡莫过于分支(branch)。你可能经常在C源代码中这样写:

  if(sel==1)
  {
  proc1();
  }
  else
  {
  proc2();
  }

  放到上面的5级流水线中考虑时,我们惊讶地发现:

  sel==1这一判断(CMP指令)的结果(常常是状态寄存器的ZF位)要到WB的时候才能知晓,但它影响的却是PC(程序指针)的值,也就是说产生数据依赖的是IF阶段!分支指令可能产生长达5个环节的空泡!

  正是由于分支指令对性能的极大损害,现代的常常费尽心思地进行分支预测(branch prediction),期望尽量猜中分支指令执行的结果,尽可能减少极端的长空泡。

  不幸的是,分支是任何语言必不可少,甚至是最有用的部分:一个只能顺序向下执行的程序有什么用呢?

  你可以想象早期的CPU面对分支语句有多么无力。更加不幸的是,最爱用分支语句的程序恰恰是必不可少的:编译器!传说GCC中就有超过4000个if语句。

  下面再从电路的层面上说说pipleline这件事:

  CPU的执行引擎(execution engine)可以被看成一个巨大的逻辑电路。它有一个传输延时t_pd,logic,即它从输入(IF开始)到输出(WB结束)的耗时。

  在寻找最高时钟频率,即最小时钟周期间隔时,自然有:



评论


相关推荐

技术专区

关闭