Intel公司即将推出的奔腾IV CPU是该公司在电脑业投放的又一颗重磅炸弹,当该产品还没有正式推出时,就有许多关于此产品的介绍。但是Intel到底应用了什么技术使得这款CPU具有强大计算和处理能力呢?下面就该CPU的流水线与 CPU 时钟频率进行技术分析。
为了弄清CPU的流水线与 CPU 时钟频率,先得了解CPU 到底做了些什么工作?坦白地说,并不是很多。处理器只能做一些简单的运算和一些简单的逻辑处理。举个例子,把一个值“A”加到一个值“B”中去,或者判断“A”是否比“B”大。当然,要让处理器能够操作这些数值,它必须知道(1)这些数值放在什么地方;(2)要对这些数值进行什么操作(比如说加,乘)。一旦指令和数据都已定位,接下来,解释并执行,结果保存在内存中供以后使用。
现在,我们简单地模拟处理器完成一条指令要做的工作。要处理一条指令,处理器必须:
[1] 定位并从内存中读取数据,这一步通常称为“提取(数据)”(Fetch)
[2] 解释或者编译软件中的指令,这一步通常称为“译码” (Decode)
[3] 在给定的数据上完成给定的指令,这一步叫做“执行” (Execute)
[4] 把结果数据放回到内存的特定位置,又叫“存储”数据 (Store)
当然,上面只是处理过程一个非常简化的说明,事实上不会如此简单,不过它清楚地说明,每完成一条指令,处理器都必须要提取数据,翻译指令,执行指令,存储结果。
现在,我们已经清楚了处理器到底做了些什么,可以开始着眼于什么是流水线,为什么要用流水线了。先让我们来看一看没有流水线的处理器。
┌────────────────────────────────┐
│ 提取 译码 执行 存储 │
└────────────────────────────────┘
├──────────── 1 个时钟周期 ────────────┤
├──────────── △T = 1秒 ────────────┤
上面是一个单时钟周期的例子。处理器只有一个阶段,指令被逐步提取,译码,执行,存储。这就是说,我们上面的这个处理器能在一个时钟周期内做所有的事情(提取、译码、执行、存储)。我们假设这个特别的处理器工作频率是 1 Hz,或者说一个时钟周期是 1 秒。
同时,很容易看出我们这个虚构的处理器的 IPC(Instructions-Per-Clock)是 1。IPC 就是处理器在一个时钟周期内能够完成的指令数。处理器的 IPC 为 1,工作频率是1 Hz。因此,举个例子,10 秒钟时间,IPC 为 1,工作频率为 1 Hz 时,我们能够完成 10 条指令。
无流水线处理器:10 秒 X (1 时钟周期/1 秒) X (1 指令/1 时钟周期) = 10 指令
现在,我们开始探讨流水线。流水线能够提升时钟频率和整体性能(记住,更快的时钟频率并不能直接转化成更快的性能)。
提升时钟频率:
首先,我们将来探讨流水线是怎样提升处理器操作的最大时钟频率的。
假设我们想把我们的处理器的频率由原来的 1 Hz 提升到 2 Hz。我们该怎么做呢?很明显,答案就是要制造一个工作得更快的处理器。比如说,我们可以收缩管芯尺寸,这样可以使我们的处理器中的晶体管切换的更快,因此,完成一个“提取-译码-执行-存储”循环也更快一些。这是一个完全可行的选择,而且经常被采用,但迄今为止,它已经很难再有所进步了。在任何时候,目前的制作工艺只允许我们把管芯尺寸消减到某一临界点,但不可能无限减下去。必须要有另外的选择。
如果我们已经无法再让处理器更快地完成它的任务,当初我们为什么不让它做的“少”一些呢?取代这种在一个时钟周期内存完成“提取-译码-执行-存储”的方法,假设我们把它分成两步:提取和译码在一个时钟周期,执行和存储在另一个时钟周期。现在我们已经设计出了我们的拥有两-段流水线的处理器。
两段流水线处理器:
┌───────────────┬────────────────┐
│ 提取 译码 │ 执行 存储 │
└───────────────┴────────────────┘
├─── 1 个时钟周期 ────┤
├──────────── △T = 1秒 ────────────┤
现在,“提取-译码-执行-存储”已经不再是在一个时钟周期内完成了,我们的处理器在一个时钟周期内提取和翻译指令,在另一个时钟周期内执行指令,存储结果。既然进行一半的操作本质上只需要一半的时间,它立刻就能以两倍的时钟频率工作了,不再需要担心如何收缩管芯尺寸和其它一些因素了。(我们要再次说明,这是一个过度简化的模型――比如说,在现实情况下,提取和译码所要花的时间是不可能相同的,但为了便于说明问题,我们假设它们是相同的。)
同样,我们可以把我们的处理器细分为四-段流水线。在这种情况下,每一个操作(提取,译码,执行,存储)都在一个独立的时钟周期内完成,可以让我们重新设计的处理器的时钟频率升到 4 Hz。
四段流水线处理器:
┌───────┬────────┬────────┬────────┐
│ 提取 │ 译码 │ 执行 │ 存储 │
└───────┴────────┴────────┴────────┘
├ 1个时钟周期 ┤
├──────────── △T = 1秒 ──────────────┤
X86 系列的处理器拥有流水线已经多年了。一个很有意思的对比,奔腾 III 和目前的速龙都使用了 10段流水线。奔腾IV的流水线则要长上一倍,有 20 段。然而,我们早就说过,更高的时钟频率,并不总是等价于更高的总体性能。
让我们进一步探讨我们重新设计的四段流水线处理器。
借助于更深的四段流水线,我们现在能让我们的处理器工作在 4 Hz 下。因此,我们运行 Internet 浏览器或者玩游戏应该比我们的 1 Hz 的处理器快上四倍,对不对?错了!!!
看看上面的示意图。确实,我们在 4 Hz 下运行,但每个时钟周期,我们只做了四分之一的工作。确切来说,在第一个时钟周期,我们只能提取数据,不能再干别的事了。和我们的无流水线处理器对比一下,它在一个时钟周期内完成了提取、译码、执行、存储全部工作。我们再次假设提取、译码、执行、存储所要占用的时间相同,我们的四段流水线处理器完成这些工作需要四个时钟周期,也就是说,它的 IPC 更低。正好低四倍,是 0.25。再来考虑 10 秒钟所能完成的工作,你可以得出结论:
四段流水线处理器:10 秒 X (4 时钟周期/1 秒) X (0.25 指令/1 时钟周期) = 10 指令
实际上,在给定的时间段内,我们的四-段流水线处理器和无流水线处理器完成的指令数完全相同。它的工作频率确实是四倍,但每个时钟周期内却只做了四分之一的工作。
因此,如果实际上并不能更快,那么我们当初为什么要费神来设计流水线呢?
首先,它或许确实不会更快,但我们可以在包装盒上写上“4 Hz”而不是“1 Hz”。很不幸,数字是一个卖点。给一个电脑盲出示一个 4 Hz 的处理器和一个 1 Hz 的处理器,他将认为 4 Hz 的那一个更快,即使事实并非如此。
其次,也是更重要的,我们实际上还是能够利用流水线的优势,因此,毕竟能够使处理器运行的更快。但是怎么做呢?
装配线
举个例子,我们考虑一下汽车工厂的装配线。首先我们要做的就是把钢架焊接到一起。一旦焊接完毕之后,钢架向前传递,我们可以开始安装侧面板。完成之后,车身可以继续向前传递进行其它处理。
现在,让我们联系汽车装配线来类推一下,我们前面的那个四-段流水线模型有点小小的失误。这个错误就是:我们假定我们的处理器同时只能处理提取、译码、执行“或者”存储中的一项工作。因此,它首先提取,然后译码,接着执行,最后存储。这就好比是我们的汽车车间只有一名工人,他跑来跑去,先焊接,再上螺丝,接着安装轮胎,等等。
实际上,我们的处理器能够同时处理提取、译码、执行“以及”存储 ―― 就象是在一个汽车车间,同时有许多工人在不断地焊接、上螺丝、安装轮胎。一旦第一个工人焊好了钢架(提取指令),他会坐在那里发呆,直到这辆车装好侧面板(译码)等等工作吗?他一完成,就把这辆车传给下一个工人,并且马上开始焊接“下一辆”车的骨架。
事实上,流水线的不同段更象是工人们本身。这就是说,有一个提取单元,一个译码单元,一个执行单元,等等,每一个操作都占用处理器的一个时钟频率。没有哪一个单元做全部四件事情,一个接一个,每一段都是一个独立的单元。在前面,我们假设提取单元在一个时钟周期内提取指令,然后在其它每个单元完成它们那部分工作时什么事都没做。但是,就象装配线上焊钢架的工人,提取单元并没有在那儿发呆直到执行和存储单元工作完毕,它立刻开始提取下一条指令了!看一看下面这张图表:
提取单元 译码单元 执行单元 存储单元
时钟周期一 指令1
时钟周期二 指令2 指令1
时钟周期三 指令3 指令2 指令1
时钟周期四 指令4 指令3 指令2 指令1
时钟周期五 指令5 指令4 指令3 指令2
第一个时钟周期之后(1/4 秒,@ 4 Hz),提取单元完成了第一条指令的工作,把它交给译码单元在下一个时钟周期进行处理。但是,提取单元并没有在那儿等待,它立即开始提取第二条指令。这样做的结果是,第一条指令仍然需要四个时钟周期才能完成,但是以后却能每一个时钟周期都完成一条指令。(当然,实际情况要比这复杂的多...)
因此,在 10 秒钟时间段里(40 个时钟周期),我们的 4 Hz、4 段流水线处理器实际上将处理完 37 条指令(四个周期完成第一条指令,后来的 36 个周期每个周期完成一条指令),并不是我们前面预测的 10 条指令。这实际上是说,我们的四-段流水线处理器的 IPC 大约是每个时钟周期 0.9 条指令,比我们前面说的0.25 要大得多(显然比无流水线处理器的 1.0 IPC 还是要小一点)。虽然 IPC 要比 1 Hz 无流水线处理器低 10%,但是时钟频率要快上 400%,因此我们的四-段流水线处理器实际上还是一个快的多的设计。
依赖性
这样看来,既然流水线这么好,为什么不制造一个 500 段流水线的处理器呢?不幸的是,有很多问题令我们无法这么做。最大的问题是成本和复杂性 ―― 以当今的技术,一条 500 段的流水线还是有点过分。就象你需要一间能够容纳 500 个而不是 4 个汽车生产工人的厂房,相对我们的无流水线处理器,你也需要一个 500 倍大的管芯,用我们目前的技术,这样的处理器太昂贵了,产量也将低的可怜。当然,还有其它一些问题。
经常会出现这样的情况,一条指令依赖前一条指令的结果。比如说,视第一条指令的执行结果而定,第二条指令可能不一样。看看下面这个例子:
[1] 指令1 ―― 判断 c 的值,给定的 c = a + b
[2] 指令2 ―― 如果 c 大于 4,c 的值乘以 2,d = 2c
[3] 指令2 ―― 如果 c 小于 4,c 的值乘以 -2,d = -2c
据估计,x86 代码集中大约有 10-20% 包含了上述分支。在这种情况下,不知道第一条指令的结果,我们无法执行第二条指令。因此,提取单元将一直死等到第一条指令执行完毕之后才能开始处理第二条指令。这就浪费了时钟周期,将大大降低效率,这种情况是无法接受的。那么,怎么解决这个问题呢?
有一种可行的解决方案被称为分支预测。本质上说,就是处理器根据经验猜测一下结果可能是什么,并且按照这种假设进行处理。就拿上面那个例子,它可能预测,第一条指令的执行结果可能是 3,于是就按照小于 4 的情况继续执行。因为大多数代码使用了类似的重复循环,所以分支预测也并不是一件极其困难的事。实际上,目前的分支预测单元预测正确率超过 90%。
但是,这 10% 的错误预测时间里会发生些什么呢?(还有其它方法也可以处理指令的依赖性,比如说乱序执行,但这我们留到以后再说)
分支预测错误
让我们再来看看前面那个例子:
提取单元 译码单元 执行单元 存储单元
时钟周期一 指令1
时钟周期二 指令2 指令1
时钟周期三 指令3 指令2 指令1
时钟周期四 指令4 指令3 指令2 指令1
时钟周期五 指令5 指令4 指令3 指令2
假设指令2,3,4等等都依赖于指令1的执行结果,并且都已经按照一个预测的结果执行了。假设这个预测时错误的。因此,指令2基于一个错误的数据,必须按照正确的数据重新处理,指令3,4等等同样如此。这时就要清洗流水线。既然流水线上的所有数据都是根据一个错误的假设计算出来的,结果,处理器必须放弃所有流水线上的数据。用在这些指令上的时钟周期都浪费了。
现在来看,一个两-段流水线,只有另一条指令的一半被清洗了,因此时钟周期的浪费还不算很过分。再看看一条 10 段流水线。因为完成指令1需要 10 个时钟周期,处理器在错误的假设下正在处理的九个时钟周期全都白费了。同样,一个 20 段的流水线(比如 Willamette),一旦分支预测出错,将浪费 19 个时钟周期。
据估计这些低于 10% 的分支预测错误使奔腾 III 的性能降低了 20-40%,你对这种影响应该有一点初步认识了。考虑到大约只有 10-20% 的指令会出现分支,这就是说平均每 50-100 条指令(10-20% 的分支指令的 10%)才会出现一次分支预测错误。重申一遍,如果这 50 到 100 条指令都预测正确了的话,奔腾 III 的性能将会快上 20-40%。现在,你应该能够认识到一个好的分支预测算法的重要性了。并且,你现在能够清楚,如果我们试图实现一条 500段的流水线,一旦分支预测出错,性能的损失将非常的恐怖。
流水线能够,也正在被用于提升系统性能,提高处理器的时钟频率。但事情不是制造尽可能长的流水线这么简单 ―― 长流水线也有它的一些固有缺点和问题。物理空间的大小是一个例子(奔腾 IV 的尺寸要比奔腾 III 差不多大上一倍)。另外,随着流水线长度的增加,分支预测出错带来的惩罚也就越发的沉重。
结合我们前面的序言,不得不担心奔腾 IV 的 20 段流水线是否太长了,虽然时钟频率可以更高,但可能实际上妨碍了性能。虽然 Intel 做了打量的工作来改进分支预测算法以减少预测出错的频率,可是一旦分支预测出错,惩罚太沉重了。据估计,因为流水线太长,在相同的时钟频率下, 奔腾 IV 的性能可能要比奔腾 III 慢 20%。Intel 还有其它一些先进的体系机构,因此这种说法有可能是真的,也有可能不是真的 ―― 但是有一点可以确定,得益于 20 段的流水线,奔腾 IV 可以达到奔腾 III 所无法达到的高得多的时钟频率。要知道,时钟频率是一大卖点。可能少数熟悉内情的专业技术人员不会去选择时钟频率更高的处理器,但对大多数人来说,他们一定会这样做。总之,目前有关奔腾 IV 性能的猜测终究只能是猜测。它有可能比同频的奔腾 III 快,也有可能比它慢。手上没有最终的那块硅晶片,我们无法确定到底会是个什么结果。
|