1.4 体系结构设计的基本原则
计算机体系结构发展很快,但在发展过程中遵循一些基本原则,这些原则包括平衡性、局部性、并行性和虚拟化。
1.4.1 平衡性
结构设计的第一个原则就是要考虑平衡性。一个木桶所盛的水量的多少由最短的木板决定,一个结构最终体现出的性能受限于其瓶颈部分。计算机是个复杂系统,影响性能的因素很多。例如,一台个人计算机使用起来比较卡顿,一般人会觉得主要是由于CPU性能不够,实际上真正引起性能卡顿的可能是内存带宽、硬盘或网络带宽、GPU性能,或者是CPU和GPU之间数据传输不顺,等等。又如,一般的CPU微结构研究专注于其中某些重要因素如Cache命中率和转移猜测命中率的改善,但通用CPU微结构中影响性能的因素非常复杂,重排序缓冲项数、发射队列项数、重命名寄存器个数、访存队列项数、失效队列项数、转移指令队列项数与一级Cache失效延迟、二级Cache失效延迟、三级Cache失效延迟等需要平衡设计,有关队列大小应保证一级Cache和二级Cache的失效不会引起流水线的堵塞。
通用CPU设计有一个关于计算性能和访存带宽平衡的经验原则,即峰值浮点运算速度(MFLOPS)和峰值访存带宽(MB/s)为1:1左右。表1.2给出了部分典型CPU的峰值浮点运算速度和访存带宽比。从表中可以看出,一方面,最新的CPU峰值浮点运算速度和访存带宽比逐步增加,说明带宽已经成为通用CPU的重要瓶颈,多核的发展是有限度的;另一方面,如果去除单指令流多数据流(Single Instruction Multiple Data,简称SIMD)的因素,即去除128位SIMD浮点峰值为64位浮点的2倍,256位SIMD浮点峰值为64位浮点的4倍的因素,则浮点峰值和访存带宽还是基本保持着1:1的关系,因为SIMD一般只有科学计算使用,一般的事务处理不会用SIMD的浮点性能。
表1.2 典型CPU的浮点峰值和访存带宽比
计算机体系结构中有一个著名的Amdahl定律。该定律指出通过使用某种较快的执行方式所获得的性能的提高,受限于不可使用这种方式提高性能的执行时间所占总执行时间的百分比,例如一个程序的并行加速比,最终受限于不能被并行化的串行部分。也就是性能的提升不仅跟其中的一些指令的运行时间的优化有关,还和这些指令在总指令数中所占的比例有关:
ExTimenew=Extimeold×((1-Fractionenhanced)+(Fractionenhanced/Speedupenhanced))
Speedupoverall=Extimeold/ExTimenew
在计算机体系结构设计里Amdahl定律的体现非常普遍。比如说并行化,一个程序中有一些部分是不能被并行化的,而这些部分将成为程序优化的一个瓶颈。举一个形象的例子,一个人花一个小时可以做好一顿饭,但是60个人一起做不可能用一分钟就能做好,因为做饭的过程有一些因素是不可被并行化的。
结构设计要统筹兼顾,抓住主要因素的同时不要忽略次要因素,否则当主要的瓶颈问题解决以后,原来不是瓶颈的次要因素可能成为瓶颈。就像修马路,在一个本来堵车的路口修座高架桥,这个路口不堵车了,但与这个路口相邻的路口可能堵起来。体系结构设计的魅力正在于在诸多复杂因素中做到统筹兼顾。
1.4.2 局部性
局部性是事物普遍存在的性质。一个人认识宇宙的范围受限于光速和人的寿命,这是一种局部性;一个人只能认识有限的人,其中天天打交道的熟悉的人更少,这也是一种局部性。局部性在计算机中普遍存在,是计算机性能优化的基础。
体系结构利用局部性进行性能优化时,最常见的是利用事件局部性,即有些事件频繁发生,有些事件不怎么发生,在这种情况下要重点优化频繁发生的事件。当结构设计基本平衡以后,优化性能要抓主要矛盾,重点改进最频繁发生事件的执行效率。作为设计者必须清楚什么是经常性事件,以及提高这种情况下机器运行的速度对计算机整体性能有多大贡献。例如,假设我们把处理器中浮点功能部件执行的性能提高一倍,但是整个程序里面只有10%的浮点指令,总的性能加速比是1÷0.95=1.053,也就是说即使把所有浮点指令的计算速度提高了一倍,总的CPU性能只提高了5%。所以应该加快经常性事件的速度。把经常性的事件找出来,而且它占的百分比越高越好,再来优化这些事件,这是一个基本的原理。RISC指令系统的提出就是利用指令的事件局部性对频繁发生的事件进行重点优化的例子。硬件转移猜测则是利用转移指令跳转方向的局部性,即同一条转移指令在执行时经常往同一个方向跳转。
利用访存局部性进行优化是体系结构提升访存指令性能的重要方法。访存局部性包括时间局部性和空间局部性两种。时间局部性指的是一个数据被访问后很有可能多次被访问。空间局部性指的是一个数据被访问后,它邻近的数据很有可能被访问,例如数组按行访问时相邻的数据连续被访问,按列访问时虽然空间上不连续,但每次加上一个固定的步长,也是一种特殊的空间局部性。计算机体系结构使用访存局部性原理来提高性能的地方很多,如高速缓存、TLB、预取都利用了访存局部性。
1.4.3 并行性
计算机体系结构提高性能的另外一个方法就是开发并行性。计算机中一般可以开发三种层次的并行性。
第一个层次的并行性是指令级并行。指令级并行是20世纪最后20年体系结构提升性能的主要途径。指令级并行性可以在保持程序二进制兼容的前提下提高性能,这一点是程序员特别喜欢的。指令级并行分成两种。一种是时间并行,即指令流水线。指令流水线就像工厂生产汽车的流水线一样,汽车生产工厂不会等一辆汽车都装好以后再开始下一辆汽车的生产,而是在多道工序上同时生产多辆汽车。另一种是空间并行,即多发射,或者叫超标量。多发射就像多车道的马路,而乱序执行(Out-of-Order Execution)就是允许在多车道上超车,超标量和乱序执行常常一起使用来提高效率。在20世纪80年代RISC出现后,随后的20年指令级并行的开发达到了一个顶峰,2010年后进一步挖掘指令级并行的空间已经不大。
第二个层次的并行性是数据级并行,主要指单指令流多数据流(SIMD)的向量结构。最早的数据级并行出现在ENIAC上。20世纪六七十年代以Cray为代表的向量机十分流行,从Cray-1、Cray-2,到后来的Cray X-MP、Cray Y-MP。直到Cray-4后,SIMD沉寂了一段时间,现在又开始恢复活力,而且用得越来越多。例如X86中的AVX多媒体指令可以用256位通路做四个64位的运算或八个32位的运算。SIMD作为指令级并行的有效补充,在流媒体领域发挥了重要的作用,早期主要用在专用处理器中,现在已经成为通用处理器的标配。
第三个层次的并行性是任务级并行。任务级并行大量存在于Internet应用中。任务级并行的代表是多核处理器以及多线程处理器,是目前计算机体系结构提高性能的主要方法。任务级并行的并行粒度较大,一个线程中包含几百条或者更多的指令。
上述三种并行性在现代计算机中都存在。多核处理器运行线程级或进程级并行的程序,每个核采用多发射流水线结构,而且往往有SIMD向量部件。
1.4.4 虚拟化
所谓虚拟化,就是“用起来是这样的,实际上是那样的”,或者“逻辑上是这样的,物理上是那样的”。计算机为什么好用?因为体系结构设计者宁愿自己多费点事,也要尽量为用户提供一个友好界面的用户接口。虚拟化是体系结构设计者为用户提供一个友好界面的基本方法,虚拟化的本质就是在不好用的硬件和友好的用户界面之间架一座“桥梁”。
架得最成功的一座“桥梁”是20世纪60年代工艺的发展使处理器中可以包含像TLB这样较为复杂的结构,操作系统可以支持虚拟空间,大大解放了程序员的生产力。早期的计算机程序员编程的时候要直接跟物理内存和外存打交道,非常麻烦,虚拟存储解决了这个问题。每个进程都使用一个独立的、很大的存储空间,具体物理内存的分配和数据在内存和外存的调入调出都由操作系统自动完成。这座桥架得太漂亮了,给它评分肯定是“特优”。
如果说虚拟存储技术“虚拟”了内存,那么多线程和虚拟机技术则“虚拟”了CPU。多线程技术,尤其是同时多线程(Simultaneous Multi-Threading,简称SMT)技术,通过微结构的硬件支持,如设立多组通用寄存器等,使得在同一个CPU中实现两个或多个线程中的指令在流水线中混合地执行,或在同一个CPU中实现线程的快速切换,使用户在一个CPU上“同时”执行多个线程。虚拟机技术则通过微结构的硬件增强,如设立多组控制寄存器和系统状态等,实现多个操作系统的快速切换,达到在同一台计算机上“同时”运行多个操作系统的目的。这座桥架得也不错,作用没有虚拟存储那么明显,给它评分可以得“优”。
流水线和多发射结构也是架得很成功的一座“桥梁”。20世纪七八十年代以来,工艺的发展使得像流水线和多发射这样的结构得以实现,在维持串行编程模型的情况下提高了速度。但由于程序中相关性的存在,流水线和多发射的效率难以做得很好,例如在单发射结构中IPC达到0.5就不错了,在四发射结构中IPC达到1.5就不错了。流水线和多发射这座桥的评分可以得“优”。
另外一座比较成功的“桥梁”是Cache技术。CPU速度越来越快,内存大但是慢,通过Cache技术可以使程序员看到一个像Cache那么快、像内存那么大的存储空间,不用改应用程序就能提高性能。这座桥也对程序员屏蔽了结构细节(虽然程序员往往针对Cache结构进行精雕细刻的程序设计以增加局部性),但代价太大,现代处理器往往80%以上的晶体管都用在Cache上了,所以Cache这座桥的评分只能得“良好”。
还有一座比较典型的“桥梁”是分布式共享存储系统中的Cache一致性协议。Cache一致性协议可以在分布式存储的情况下给程序员提供一个统一的编程空间,屏蔽了存储器物理分布的细节;但Cache一致性协议并不能解决程序员需要并行编程、原有的串行程序不能并行运行的问题。因此Cache一致性协议这座桥评分可以得“及格”。如果哪天编译技术发展到程序员只要写串行程序,计算机能够自动并行化并在成千上万个处理器中运行该程序,那这座桥的评分可以得“特优”。