第6章利用流水线提高性能.docx
《第6章利用流水线提高性能.docx》由会员分享,可在线阅读,更多相关《第6章利用流水线提高性能.docx(55页珍藏版)》请在冰豆网上搜索。
![第6章利用流水线提高性能.docx](https://file1.bdocx.com/fileroot1/2022-11/17/ed96dda2-6f00-4032-83d3-996b9aef5c64/ed96dda2-6f00-4032-83d3-996b9aef5c641.gif)
第6章利用流水线提高性能
第6章利用流水线提高性能
随着时间的推移,每个事物都按固有的规律发展变化,在旧的事物逝去的同时,新的事物又产生了。
RobertHerrick在1648年圣诞节前夜庆典上的讲话
流水线概述1
流水线的数据路径17
流水线的控制28
数据冒险与转发37
数据冒险与阻塞49
分支冒险53
异常60
超标量和动态流水线64
实际资料:
PowerPC64和PentiumPro的流水线72
谬误和陷阱75
结论77
历史回顾和参考文献79
重要术语83
习题85
流水线概述
决不要浪费时间。
-----一个美国的谚语。
流水线是一种实现多条指令重叠执行的技术。
目前,流水线技术是提高处理器处理速度的关键。
本节依据上述谚语提供的内涵对流水线的概念及其相关问题进行概述。
如果你只是想对流水线技术有一个大概的了解,你可以集中精力看完本节,然后直接跳到节学习流水线的工作方式以及它对程序执行性能的影响。
如果你想对基于流水线技术的计算机进行深入的了解,到详细论述了本节涉及到的内容。
任何一个经常光顾洗衣店的人都会不自觉的应用流水线技术。
非流水线方式的洗衣过程将包括如下几个步骤:
1.把一批脏衣服放入洗衣机里清洗。
2.洗衣机洗完后,把衣服取出放入脱水机中。
3.衣服被甩干后,将之从脱水机中取出,然后将衣服放在桌子上折叠起来。
4.衣服折叠好以后,请你的室友帮忙把桌子上的衣服拿走。
当你的室友把这批洗干净了的衣服从桌子上全都拿走以后,再开始洗下一批脏衣服。
采用流水线的方法将节省大量的时间。
如图所示,当把第一批脏衣服从洗衣机里取出放入脱水机之后,你就可以把第二批脏衣服放入洗衣机里进行清洗了。
当第一批衣服被甩干之后,就可以将它们折叠起来,同时把洗净的下一批湿衣服放入脱水机中,同时再将下一批脏衣服放入洗衣机里清洗。
下一步工作就是让你的室友把第一批衣服从桌子上拿走,而你开始折叠第二批衣服,这时脱水机中放的是第三批衣服,而且你就可以把第四批衣服放入洗衣机清洗了。
这样,所有的洗衣步骤(即流水线的步骤)都在同时操作。
一旦在每一操作步骤中都有独立的工作单元时,我们就可以采用流水线的方式来快速的完成任务了。
流水线的奇妙之处在于,对于单独的一批衣服来说,从它进洗衣机到脱水机,再到折叠、收拾,整个过程的总的处理时间并没有缩短。
而在有多批任务时流水线之所以快的原因是所有的工作都是在并行的进行的。
因此,单位时间内能够完成的工作量就大大的增加了。
如果流水线的所有步骤所花费的时间都相同并且有足够多的工作可以做的话,那么由于采用流水线带来的速度的提高倍数与流水线的步骤的数目相同。
一个采用流水线方式工作的洗衣房与非流水线方式工作的相比在速度上提高了四倍:
前者洗完20批衣服所需的时间是洗完1批衣服所需时间的4倍,而后者洗完20批衣服所需的时间是洗完一批衣服的20倍。
在图中,流水线方式只将处理速度提高了倍的原因是图中只显示了清洗四批衣服的处理过程。
图以洗衣店为例来类比流水线的运作过程。
安妮,布朗,凯西和唐每个人都有一些脏衣服要清洗、脱水、折叠及储存。
洗衣机、脱水机、折叠机和储存机每个都需要三十分钟来完成各自的任务。
顺序的洗衣将花费8个小时的时间洗完四批衣服,而流水线的洗涤方法只需要花费小时。
图中采用在这个二维时间轴上显示4道工作的副本的方法来表示同一时间不同的处理步骤对应的流水线步骤,而事实上我们每种洗衣设备都只有一台。
同样的原理也可以应用到处理器中,即采用流水线方式执行处理器指令。
通常,一个MIPS指令包含如下五个处理步骤:
1.从内存中读取指令。
2.指令解码的同时读取寄存器(MIPS的指令格式允许同时进行指令解码和读寄存器)。
3.执行操作或计算地址。
4.在数据内存中读取操作数。
5.将结果写回寄存器。
因此,本章讨论的MIPS流水线具有五个处理步骤。
正如流水线能加速洗衣店的工作一样,下面的例子将说明流水线如何加快指令的总体执行时间。
单周期指令模型与流水线性能
例题:
为了使问题具体化,我们首先假设一个流水线结构。
在本例以及本章所剩余的部分内容中,我们将只考虑以下的八条指令:
loadword(lw);storeword(sw);add(add);subtract(sub);and(and);or(or);set-less-than(slt)和branch-on-equal(beq)。
本实例将比较流水线指令执行与单周期指令执行的平均执行时间,其中在单周期模型中所有指令的执行都花费一个时钟周期。
本例中,主要功能单元的操作时间为内存访问:
2ns;ALU操作:
2ns;寄存器文件的读与写:
1ns。
(在第五章中我们已经说明在单周期模型中每一条指令都恰恰只花费一个时钟周期,因此,时钟的周期必须延长以满足最慢的指令。
)
解:
八条指令中每一条指令所需要的执行时间如图所示。
单周期模型的设计必须考虑到最慢的指令,在图中是lw,因此,每一条指令所需要的执行时间为8ns。
与图类似,图比较了三条loadword指令非流水线与流水线的方式的执行过程,其中在非流水线模型中,第一条与第四条指令之间时间的差距是3x8=24ns。
指令类别
指令预取
寄存器读取
ALU操作
数据访问
寄存器写
总的执行时间
Loadword(lw)
2ns
1ns
2ns
2ns
1ns
8ns
Storeword(lw)
2ns
1ns
2ns
2ns
7ns
R-format
(add,sub,and,or,slt)
2ns
1ns
2ns
1ns
6ns
Branch(beq)
2ns
1ns
2ns
5ns
图由各操作组件计算出来的八条指令总的执行时间。
假设乘法器、控制单元、PC访问和信号传递都没有延时。
图单循环、非流水线的指令执行过程(上图)与流水线的指令执行过程(下图)。
两者采用相同的硬件组件,各组件的处理时间如图。
在此种情况下,指令的执行速度提高了4倍,即从8ns降到了2ns。
将本图与图比较。
在洗衣服的例子中,我们假设所有的处理过程的完成时间都是相等的。
如果脱水机运行得最慢,那么就把抽水的时间设定为各步骤需要的处理时间。
计算机的流水线过程处理时间也是受限于最慢的处理资源,即ALU操作和内存访问。
同时我们假设对寄存器文件的写操作发生在时钟周期的前半段,对寄存器文件的读操作发生在时钟周期的后半段,并且本章所有内容都遵循这个假设。
所有的流水线步骤都只花费一个时钟周期的时间,所以,时钟周期必须能够满足最慢的操作的执行需要。
这就象在单周期模型中虽然有些快的指令的执行只需要5ns,但它必须选择在最坏情况下的8ns做为时钟周期一样,流水线执行模型的时钟周期也必须选择最坏情况下的2ns而不是有些步骤可以达到的1ns。
流水线能够将性能提高四倍:
第一与第四条指令之间的时间差距缩短为3x2=6ns。
我们可以把上面讨论的流水线模型能够获得的性能加速比归纳成一个公式。
如果流水线各阶段操作平衡,那么在流水线机器上指令执行时间为(在理想情况下):
指令执行时间(流水线)=指令执行时间(非流水线)/流水线步骤数
即在理想的情况下,流水线所带来的加速比与流水线的执行步骤的数目相同。
一个有五个执行步骤的流水线能获得加速比也是五。
这个公式说明一个有五个步骤的流水线在8ns的非流水线执行时间或者的时钟周期的基础上获得获得五倍的速度提高。
然而,在例子中显示,各个步骤间并不是完全的平衡的。
另外,流水线中还包括一些常规的额外开销。
所以,在流水线机器中每一条指令的执行时间会超过这个最小的可能值,因此流水线能够获得加速比也就小于流水线的步骤数。
此外,即使我们在前面的分析中断言能将指令的执行速度提高四倍,但本例子三条指令的执行中并没有反映出来,它实际获得的加速比为24ns/14ns。
为什么实际的加速比小了许多呢如果增加执行指令的数目将会发生什么呢我们首先将前面的图中的指令增加到1003条,也就是说再在上面的流水线例子中加入一千条指令,每一条指令都将会使整个的执行时间增加2ns,因此,整个的执行时间就变成1000x2ns+14ns,即2014ns。
在非流水线的例子中,我们也加入1000条指令,每条指令的执行时间是8ns,因此整个的执行时间为1000x8ns+24ns,即8024ns。
在这种理想的条件下,非流水线程序与流水线程序的实际执行时间的比值就非常接近与两者指令执行时间的比值,即为:
8024ns/2014ns=≈8ns/2ns
流水线所带来的性能的提高是通过增加指令的吞吐率来实现的,而不是减小单条指令的执行实现的。
由于实际程序都会执行成千上万条指令,因此,指令的吞吐率是一个很重要的参数。
设计流水线指令集
尽管上面的例子只是对流水线的最简单的说明,我们也能够通过它讨论如何设计MIPS指令集,即如何设计能以流水线方式执行的指令集。
首先,所有的MIPS指令的长度都必须相同。
这一限制将简化流水线的第一步预取指令与第二步指令解码。
在诸如80x86之类的系统的指令集中,指令的长度并不相同,从1byte到17byte不等,这样将会给流水线的执行带来更大的挑战性。
第二,MIPS只有很少的几种指令格式,并且每一条指令中的源寄存器的位置都是相同的。
这种对称性意味着流水线的第二个步骤在硬件确定提取的指令类型的同时就能够开始读寄存器文件。
如果MIPS的指令格式是非对称的,我们就需要将第二个步骤一分为二,从而使得流水线的步骤数变为六(我们不久将看到较长的流水线的缺点)。
第三,MIPS中的内存操作数仅出现在load和store操作中。
这一限制意味着可以利用执行步骤计算内存地址,就可以接着在下一个步骤访问内存。
如果我们可以在内存中操作操作数,就像在80x86中那样,那么步骤3与步骤4将会扩展为地址步骤,内存步骤,和执行步骤三步。
第四,所有操作数必须在内存中排成一列(详情请查阅第三章软硬件界面一节相关内容)。
因此,我们不需要担心一个数据传输指令需要两次内存访问的情况,所请求的数据可以在一个的流水线步骤完成在处理器与内存之间传输。
流水线冒险(pipelinehazard)
流水线有这样一种情况,在下一个时钟周期中下一条指令不能执行。
这种情况称为流水线冒险。
我们将介绍三种流水线冒险。
介绍每种流水线冒险时我们都首先利用前面关于洗衣过程的类比作一简单的描述,然后给出计算机上流水线存在的相应问题及其解决方法。
结构冒险
第一种冒险叫做结构冒险。
即硬件不支持期望的多条指令在同一个时钟周期执行。
在洗衣店例子中,如果用洗衣-脱水机代替独立的洗衣机与脱水机,或者如果我的室友正在做其它的事情而不能帮助我将衣服收拾好,都会发生结构冒险。
如果发生上述情况,那我们精心构筑起来的流水线就会被破坏。
正如我们在上面所说的那样,MIPS的指令集是为流水线设计的。
因此,它就要求设计者能够非常容易的在设计流水线时避免结构冒险。
假设图的流水线结构只有一个内存而不是两个内存,那么如果有第四个指令的话,我们将会发现,在某一个时钟周期,第一条指令在访问内存的同时第四条指令将会在同一内存中预取指令。
如果没有两个内存的话,流水线就会发生结构冒险。
控制冒险
第二种冒险叫做控制冒险。
这种冒险会在下面的情况下出现:
决策依赖于一条指令的结果,而正好其他的指令在执行中。
假设洗衣店的店员们接到了一个令人高兴的任务:
为一个足球队清洗队服。
由于衣服非常的脏,我们需要确定清洗剂的用量以及水的温度设置是否能够将衣服清洗干净,但同时要保证不是过大以避免过度的磨损衣物。
在洗衣店流水线中,店员只有等到第二步甩干衣服以后才能确定是否需要改变洗衣机的设置。
在这种情况应该怎么办呢
有两种办法可以解决洗衣店的控制冒险,同样的方法也可以应用到计算机中。