CPU加速技术解密

栏目:线程与并发 作者:admin 日期:2018-02-24 评论:0 点击: 928 次

本文我们就以Intel CPU的发展为例为各位同学简要阐述一下CPU的加速技术是怎么一点点被开发出来的。

原始级,蛮荒状态-1987年
Intel在1978-06-08创造了8086处理器,这时处理器的执行流程非常简单,就是从内存中读取操作码后将操作码译码解析成微指令,并由微指令驱动逻辑电路去完成具体计算操作,然后再读取下一条指令。以上操作可被概括为取指令、译码和执行这三步,而且每次都要等到这三个步骤都完成后才能执行下一条指令。

上古级,指令缓存-1982年
由于CPU的执行速度远高于内存的读取速度,因此Intel发现整个CPU的性能瓶颈出现在内存读取这一环节上。而又因为绝大多数指令编译的操作码仅几个字节大小,所以Intel在1982年发布了一款新CPU 80186,并且增加了指令缓存机制。80186拥有一个6字节的指令缓存器,在每次剩余空间大于等于3字节时,80186就会自动提前将下一条指令从内存中读取进来,进而大大降低了操作码的读取延迟。

古代级,数据缓存-1985年
由于指令缓存机制在80186上取得了巨大成功,因此Intel在1985年发布的80386上面将指令缓存提高到了最大8KB,相较80186增加了1300余倍,并增加了数据缓存机制。除此之外,Intel为了进一步降低因内存读取而造成的高延时,还为80386增加了最高64KB的数据缓存,使得80386有能力预先将一部分数据从内存读取到CPU的数据缓存区域,从而极大的降低因为CPU需要频繁访问内存而造成的延迟,例如:
int nArray[100] = {1,2,3,4,5,6,7,8,9,10, ... };
for (int i=0; i<100; i++)
    printf("%02d ", nArray[i]);  //重复访问100次数组nArray

以上这段代码编译运行后,我们会发现访问数组的速度特别快,其主要原因就是数据缓存起到的作用。应用程序以为它是在访问物理内存中的一块栈空间的内容,而实际上它是在访问CPU的数据缓存。

近代级,多流水线-1989年
由于内存的延迟已经被Intel在80386上尽可能的优化,因此Intel的工程师们这一次将优化的目光锁定在指令执行的流程上,他们首先将指令的执行细分为五个步骤,分别为:
Step1:取指令,将操作码从指令缓存中取出;
Step2:译码,将操作吗翻译为具体的微指令;
Step3:转址,将内存地址和偏移进行转换;
Step4:执行,指令在该阶段真正执行运算(由微指令控制硬件逻辑电路去完成);
Step5:退出,将执行结果写回到寄存器或者内存。
一个指令必须要经过这5步才能执行完成,而CPU执行这5步所需要占用的CPU时间就被称之为这条指令执行所需的时钟周期,需要时钟周期越短的指令,其在一秒钟内可以执行的次数就越多,效率就越高。
而Intel工程师之所以将一条指令的执行分为以上5个步骤,就是因为在绝大多数情况下以上五步可以被并行执行。也就是说第一条指令在Step4处执行时,第二条指令可以在Step3执行,而第三条指令则可能在Step2中被执行,这样每一步都像是一条流水线上的工人,而分为5步就可以被看作一个指令被5个工人分别处理,因此理论上来讲,在同一时间内,这条拥有5个工人的五级流水线可以同时并行执行5条指令,而需要占用的CPU时间相对于以前执行一条指令来说并未因此有太大的增加,具体如下图所示。

Intel在1989年第一次将五级流水线技术应用到了80486处理器中,使得新处理器在频率仅为上代一倍多的情况下获得了数倍于上代CPU的理论执行速度。

现代级,超流水线-1993年
既然流水线这么强悍,那么为什么不多搞一些呢?其实Intel的工程师们也是这么想的,因此Intel在1993年推出的首代奔腾(因为586这个代号被占用,所以启用了新名字Pentium)处理器时,第一次将超标量流水线结构应用到自己的产品中。
新款奔腾处理器的超标量流水线由两条五级流水线构成,但是限于一些底层逻辑限制,第二条流水线能够执行的指令类别有所受限,并且在遇到类似于JMP、CALL等转移指令时会使得第二条流水线失效,但是即便如此,启用超流水线结构的CPU也比其他同等工况下快了近1倍。

次代级,乱序执行-1995年
通过流水线的优化让Intel的工程师们尝到了甜头,但是因为程序代码的前后顺序逻辑等问题,再增加过多的流水线对于指令的执行速度不会再有明显的提高,因此Intel的工程师们将优化目标锚定在流水线本身逻辑的修改及加强上。
通过了解多级流水线可知,如果执行指令时各环节工况基本一致,那么越靠后处理的操作码所需的绝对执行时间就越长。那么能否将译码时间长但执行时间短,和一条译码时间短但执行时间长的指令合并为前后两条进行执行呢,因为这样就可以极大的利用好流水线中的每一级,如下图所示。

Intel在1995年推出的奔腾Pro处理器中首次应用了可以极大改进流水线工作效率的乱序执行(Out-of-Order, OOO)技术,并且为了缓解因JMP、JNZ等转移指令对超标量流水线的影响而推出了指令预测(猜测执行/分支预测)技术,这两种技术的出现使得Intel的流水线已经被优化到了极致。除此之外,奔腾Pro更是将原先的五级流水线升级到了12级,这使得奔腾Pro处理器中的每条流水线理论上可同时执行12条指令。

经过如此优化的流水线已经明显不符合当时的主流情况,进而导致奔腾Pro上的流水线在大多数情况下实际是在等待新指令的传入,而正是由于Intel这次跨时代的流水线优化,使其早在23年前便为今天的“熔毁”与“幽灵”漏洞埋下了祸根,并且使其养成了挤牙膏的坏习惯,看来车开的太快果然容易出问题。

后现代级,超线程-2002年
由于上次乱序执行与指令预测的双剑合璧,使得CPU处理指令的速度飙涨,进而导致指令被执行的速度比处理器能够提供指令的速度更快,因此CPU的超标量流水线部件在大部分时间处于空闲状态。为了让整套流水线部件能够完全发挥其应有的作用,Intel在2002年为奔腾4处理器加入了第二套前端部件(例如寄存器、译码器等),这样对于操作系统来说,它就能看到两个处理器了。这样来自两套前端部件的所有的指令被一个共享的流水线部件执行,进而充分的发挥了其本来作用,而这种技术就被称之为超线程。