要研究怎么造计算机,硬件方面要理解计算机组成原理和计算机体系结构,软件方面要理解操作系统和编译原理。计算机体系结构就是研究怎么做CPU的核心课程。信息产业的主要技术平台都是以中央处理器(Central Processing Unit,简称CPU)和操作系统(Operating System,简称OS)为核心构建起来的,如英特尔公司的X86架构CPU和微软公司的Windows操作系统构成的Wintel平台,ARM公司的ARM架构CPU和谷歌公司的Android操作系统构成的“AA”平台。龙芯正在致力于构建独立于Wintel和AA体系的第三套生态体系。
1.1 计算机体系结构的研究内容
计算机体系结构研究内容涉及的领域非常广泛,纵向以指令系统结构和CPU的微结构为核心,向下到晶体管级的电路结构,向上到应用程序编程接口(Application Programming Interface,简称API);横向以个人计算机和服务器的体系结构为核心,低端到手持移动终端和微控制器(Micro-Controller Unit,简称MCU)的体系结构,高端到高性能计算机(High Performance Computer,简称HPC)的体系结构。
1.1.1 一以贯之
为了说明计算机体系结构研究涉及的领域,我们看一个很简单平常的问题:为什么我按一下键盘,PPT会翻一页?这是一个什么样的过程?在这个过程中,应用程序(WPS)、操作系统(Windows或Linux)、硬件系统、CPU、晶体管是怎么协同工作的?
下面介绍用龙芯CPU构建的系统实现上述功能的原理性过程。
按一下键盘,键盘会产生一个信号送到南桥芯片,南桥芯片把键盘的编码保存在南桥内部的一个寄存器中,并向处理器发出一个外部中断信号。该外部中断信号传到CPU内部后把CPU中一个控制寄存器的某一位置为“1”,表示收到了外部中断。CPU中另外一个控制寄存器有屏蔽位来确定是否处理这个外部中断信号。
屏蔽处理后的中断信号被附在一条译码后的指令上送到重排序缓冲(Re-Order Buffer,简称ROB)。外部中断是例外(Exception,也称“异常”)的一种,发生例外的指令不会被送到功能部件执行。当这条指令成为重排序缓冲的第一条指令时CPU处理例外。重排序缓冲为了给操作系统一个精确的例外现场,处理例外前要把例外指令前面的指令都执行完,后面的指令都取消掉。
重排序缓冲向所有的模块发出一个取消信号,取消该指令后面的所有指令;修改控制寄存器,把系统状态设为核心态;保存例外原因、发生例外的程序计数器(Program Counter,简称PC)等到指定的控制寄存器中;然后把程序计数器的值置为相应的例外处理入口地址进行取指(LoongArch中例外的入口地址计算规则可以参见其体系结构手册)。
处理器跳转到相应的例外处理器入口后执行操作系统代码,操作系统首先保存处理器现场,包括寄存器内容等。保存现场后,操作系统向CPU的控制寄存器读例外原因,发现是外部中断例外,就向南桥的中断控制器读中断原因,读的同时清除南桥的中断位。读回来后发现中断原因是有人敲了空格键。
操作系统接下来要查找读到的空格是给谁的:有没有进程处在阻塞状态等键盘输入。大家都学过操作系统的进程调度,知道进程至少有三个状态:运行态、阻塞态、睡眠态,进程在等IO输入时处在阻塞态。操作系统发现有一个名为WPS的进程处于阻塞态,这个进程对空格键会有所响应,就把WPS唤醒。
WPS被唤醒后处在运行状态。发现操作系统传过来的数据是个键盘输入空格,表示要翻页。WPS就把下一页要显示的内容准备好,调用操作系统中的显示驱动程序,把要显示的内容送到显存,由图形处理器(Graphic Processing Unit,简称GPU)通过访问显存空间刷新屏幕。达到了翻一页的效果。
再看一个问题:如果在翻页的过程中,发现翻页过程非常卡顿,即该计算机在WPS翻页时性能较低,可能是什么原因呢?首先得看看系统中有没有其他任务在运行,如果有很多任务在运行,这些任务会占用CPU、内存带宽、IO带宽等资源,使得WPS分到的资源不够,造成卡顿。如果系统中没有其他应用与WPS抢资源,还会卡顿,那是什么原因呢?多数人会认为是CPU太慢,需要升级。实际上,在WPS翻页时,CPU干的活不多。一种可能是下一页包含很多图形,尤其是很多矢量图,需要GPU画出来,GPU忙不过来了。另外一种可能是要显示的内容数据量大,要把大量数据从WPS的应用程序空间传给GPU使用的专门空间,内存带宽不足导致不能及时传输。在独立显存的情况下,数据如何从内存传输到显存有两种不同的机制:由CPU从内存读出来再写到显存需要CPU具有专门的IO加速功能,因为显存一般是映射在CPU的IO空间;不通过CPU,通过直接内存访问(Direct Memory Access,简称DMA)的方式直接从内存传输到显存会快得多。
“计算机体系结构”课程是研究怎么造计算机,而不是怎么用计算机。我们不是学习驾驶汽车,而是学习如何造汽车。一个计算机体系结构设计人员就像一个带兵打仗的将领,要学会排兵布阵。要上知天文、下知地理,否则就不会排兵布阵,或者只会纸上谈兵地排兵布阵,只能贻误军国大事。对计算机体系结构设计来说,“排兵布阵”就是体系结构设计,“上知天文”就是了解应用程序、操作系统、编译器的行为特征,“下知地理”就是了解逻辑、电路、工艺的特点。永远不要就体系结构论体系结构,要做到应用、系统、结构、逻辑、电路、器件的融会贯通。就像《论语》中说的“吾道一以贯之”。
给出了常见通用计算机系统的结构层次图。该图把计算机系统分成应用程序、操作系统、硬件系统、晶体管四个大的层次。注意把这四个层次联系起来的三个界面。第一个界面是应用程序编程接口API(Application Programming Interface),也可以称作“操作系统的指令系统”,介于应用程序和操作系统之间。API是应用程序的高级语言编程接口,在编写程序的源代码时使用。常见的API包括C语言、Fortran语言、Java语言、JavaScript语言接口以及OpenGL图形编程接口等。使用一种API编写的应用程序经重新编译后可以在支持该API的不同计算机上运行。所有应用程序都是通过API编出来的,在IT产业,谁控制了API谁就控制了生态,API做得好,APP(Application)就多。API是建生态的起点。第二个界面是指令系统ISA(Instruction Set Architecture),介于操作系统和硬件系统之间。常见的指令系统包括X86、ARM、MIPS、RISC-V和LoongArch等。指令系统是实现目标码兼容的关键,由于IT产业的主要应用都是通过目标码的形态发布的,因此ISA是软件兼容的关键,是生态建设的终点。指令系统除了实现加减乘除等操作的指令外,还包括系统状态的切换、地址空间的安排、寄存器的设置、中断的传递等运行时环境的内容。第三个界面是工艺模型,介于硬件系统与晶体管之间。工艺模型是芯片生产厂家提供给芯片设计者的界面,除了表达晶体管和连线等基本参数的SPICE(Simulation Program with Integrated Circuit Emphasis)模型外,该工艺所能提供的各种IP也非常重要,如实现PCIE接口的物理层(简称PHY)等。
需要指出的是,在API和ISA之间还有一层应用程序二进制接口(Application Binary Interface,简称ABI)。ABI是应用程序访问计算机硬件及操作系统服务的接口,由计算机的用户态指令和操作系统的系统调用组成。为了实现多进程访问共享资源的安全性,处理器设有“用户态”与“核心态”。用户程序在用户态下执行,操作系统向用户程序提供具有预定功能的系统调用函数来访问只有核心态才能访问的硬件资源。当用户程序调用系统调用函数时,处理器进入核心态执行诸如访问IO设备、修改处理器状态等只有核心态才能执行的指令。处理完系统调用后,处理器返回用户态执行用户代码。相同的应用程序二进制代码可以在相同ABI的不同计算机上运行。
学习计算机体系结构的人一定要把图1.1装在心中。从一般意义上说,计算机体系结构的研究内容包括指令系统结构、硬件系统结构和CPU内部的微结构。但做体系结构设计而上不懂应用和操作系统,下不懂晶体管级行为,就像带兵打仗排兵布阵的人不知天文、不晓地理,是做不好体系结构的。首先,指令系统就是从应用程序算法中抽取出来的“算子”。只有对应用程序有深入的了解,才能决定哪些事情通过指令系统由硬件直接实现,哪些事情通过指令组合由软件实现。其次,硬件系统和CPU的微结构要针对应用程序的行为进行优化。如针对媒体处理等流式应用,需要通过预取提高性能;CPU的高速缓存就是利用了应用程序访存的局部性;CPU的转移猜测算法就是利用了应用程序转移行为的重复性和相关性;CPU的内存带宽设计既要考虑CPU本身的访存需求,也要考虑由显示引起的GPU访问内存的带宽需求。再次,指令系统和CPU微结构的设计要充分考虑操作系统的管理需求。如操作系统通过页表进行虚存管理需要CPU实现TLB(Translation Lookaside Buffer)对页表进行缓存并提供相应的TLB管理指令;CPU实现多组通用寄存器高速切换的机制有利于加速多线程切换;CPU实现多组控制寄存器和系统状态的高速切换机制有利于加速多操作系统切换。最后,计算机中主要的硬件实体如CPU、GPU、南北桥、内存等都是通过晶体管来实现的,只有对晶体管行为有一定的了解才能在结构设计阶段对包括主频、成本、功耗在内的硬件开销进行评估。如高速缓存的容量是制约CPU主频和面积的重要因素,多发射结构的发射电路是制约主频的重要因素,在微结构设计时都是进行权衡取舍的重要内容。
什么是计算机
什么是计算机?大多数人认为计算机就是我们桌面的电脑,实际上计算机已经深入到我们信息化生活的方方面面。除了大家熟知的个人电脑、服务器和工作站等通用计算机外,像手机、数码相机、数字电视、游戏机、打印机、路由器等设备的核心部件都是计算机,都是计算机体系结构研究的范围。也许此刻你的身上就有好几台计算机。
看几个著名的计算机应用的例子。比如说美国国防部有一个ASCI(Accelerated Strategic Computing Initiative)计划,为核武器模拟制造高性能计算机。20世纪90年代,拥有核武器的国家签订了全面禁止核试验条约,凡是签这个条约的国家都不能进行核武器的热试验,或者准确地说不能做“带响”的核武器试验。这对如何保管核武器提出了挑战,核武器放在仓库里不能做试验,这些核武器放了一百年以后,拿出来还能不能用?会不会放着放着自己炸起来?想象一下一块铁暴露在空气中一百年会锈成什么样子。这就需要依靠计算机模拟来进行核武器管理,核武器的数字模拟成为唯一可以进行的核试验,这种模拟需要极高性能的计算机。据美国国防部估计,为了满足2010年核管理的需要,需要每秒完成1016∼10171016∼1017次运算的计算机。现在我们桌面电脑的频率在1GHz的量级(词头“G”表示109109),加上向量化、多发射和多核的并行,现在的先进通用CPU性能大约在10111011的运算量级,即每秒千亿次运算,10161016运算量级就需要10万个CPU,耗电几十兆瓦。美国在2008年推出的世界上首台速度达到PFLOPS(每秒千万亿次运算,其中词头“P”表示10151015,FLOPS表示每秒浮点运算次数)的高性能计算机Roadrunner就用于核模拟。高性能计算机的应用还有很多。例如波音777是第一台完全用计算机模拟设计出来的飞机,还有日本的地球模拟器用来模拟整个地球的地质活动以进行地震方面的研究。高性能计算已经成为除了科学实验和理论推理外的第三种科学研究手段。
计算机的另外一个极端应用就是手机,手机也是计算机的一种。现在的手机里至少有一个CPU,有的甚至有几个。
希望大家建立一个概念,计算机不光是桌面上摆的个人计算机,它可以大到一个厅都放不下,需要专门为它建一个电站来供电,也可以小到揣在我们的兜里,充电两个小时就能用一整天。不管这个计算机的规模有多大,都是计算机体系结构的研究对象。计算机是为了满足人们各种不同的计算需求设计的自动化计算设备。随着人类科技的进步和新需求的提出,最快的计算机会越来越大,最小的计算机会越来越小。
1.1.3 计算机的基本组成
我们从小就学习十进制的运算,0、1、2、3、4、5、6、7、8、9十个数字,逢十进一。计算机中使用二进制,只有0和1两个数字,逢二进一。为什么用二进制,不用我们习惯的十进制呢?因为二进制最容易实现。自然界中二值系统非常多,电压的高低、水位的高低、门的开关、电流的有无等等都可以组成二值系统,都可以用来做计算机。二进制最早是由莱布尼茨发明的,冯·诺依曼最早将二进制引入计算机的应用,而且计算机里面的程序和数据都用二进制。从某种意义上说,中国古人的八卦也是一种二进制。
计算机的组成非常复杂,但其基本单元非常简单。打开一台PC的机箱,可以发现电路板上有很多芯片。如图1.2所示,一个芯片就是一个系统,由很多模块组成,如加法器、乘法器等;而一个模块由很多逻辑门组成,如非门、与门、或门等;逻辑门由晶体管组成,如PMOS管和NMOS管等;晶体管则通过复杂的工艺过程形成。所以计算机是一个很复杂的系统,由很多可以存储和处理二进制运算的基本元件组成。就像盖房子一样,再宏伟、高大的建筑都是由基本的砖瓦、钢筋水泥等材料搭建而成的。在CPU芯片内部,一根头发的宽度可以并排走上千根导线;购买一粒大米的钱可以买上千个晶体管
图: 芯片、模块、逻辑门、晶体管和器件
现在计算机结构的基本思想是1945年匈牙利数学家冯·诺依曼结合EDVAC计算机的研制提出的,因此被称为冯·诺依曼结构。
我们通过一个具体的例子来介绍冯·诺依曼结构。比如说求式子(3×4+5×7)的值,人类是怎么计算的呢?先计算3×4=12,把12记在脑子里,接着计算5×7=35,再计算12+35=47。我们在计算过程中计算和记忆(存储)都在一个脑袋里(但式子很长的时候需要把临时结果记在纸上)。
计算机的计算和记忆是分开的,负责计算的部分由运算器和控制器组成,称为中央处理器,就是CPU;负责记忆的部分称为存储器。存储器里存了两样东西,一是存了几个数,3、4、5、7、12、35、47,这个叫作数据;二是存储了一些指令。也就是说,操作对象和操作序列都保存在存储器里。
我们来看看计算机是如何完成(3×4+5×7)的计算的。计算机把3、4、5、7这几个数都存在内存中,计算过程中的临时结果(12、35)和最终结果(47)也存在内存中;此外,计算机还把对计算过程的描述(程序)也存在内存中,程序由很多指令组成。表1.1a给出了内存中在开始计算前数据和指令存储的情况,假设数据存在100号单元开始的区域,程序存在200号单元开始的区域。
表 1.1: 程序和数据存储在一起
100 |
3 |
3 |
|
101 |
4 |
4 |
|
102 |
5 |
5 |
|
103 |
7 |
7 |
|
104 |
12 |
||
105 |
35 |
||
106 |
47 |
||
…… |
…… |
||
200 |
读取100号单元 |
读取100号单元 |
|
201 |
读取101号单元 |
读取101号单元 |
|
202 |
两数相乘 |
两数相乘 |
|
203 |
存入结果到104号单元 |
存入结果到104号单元 |
|
204 |
读取102号单元 |
读取102号单元 |
|
205 |
读取103号单元 |
读取103号单元 |
|
206 |
两数相乘 |
两数相乘 |
|
207 |
存入结果到105号单元 |
存入结果到105号单元 |
|
208 |
读取104号单元 |
读取104号单元 |
|
209 |
读取105号单元 |
读取105号单元 |
|
210 |
两数相加 |
两数相加 |
|
211 |
存入结果到106号单元 |
存入结果到106号单元 |
|
a) |
b) |
计算机开始运算过程如下:CPU从内存200号单元取回第一条指令,这条指令就是“读取100号单元”,根据这条指令的要求从内存把“3”读进来;再从内存201号单元取下一条指令“读取101号单元”,然后根据这条指令的要求从内存把“4”读进来;再从内存202号单元取下一条指令“两数相乘”,乘出结果为“12”;再从内存203号单元取下一条指令“存入结果到104号单元”,把结果“12”存入104号单元。如此往复直到程序结束。表1.1b是程序执行结束时内存的内容。
大家看看刚才这个过程,比我们大脑运算烦琐多了。我们大脑算三步就算完了,而计算机需要那么多步,又取指令又取数据,挺麻烦的。这就是冯·诺依曼结构的基本思想:数据和程序都在存储器中,CPU从内存中取指令和数据进行运算并把结果也放到内存中。把指令和数据都存在内存中可以让计算机按照事先规定的程序自动地完成运算,是实现图灵机的一种简单方法。冯·诺依曼结构很好地解决了自动化的问题:把程序放在内存里,一条条取进来,自己就做起来了,不用人来干预。如果没有这样一种自动执行的机制,让人去控制计算机做什么运算,拨一下开关算一下,程序没有保存在内存中而是保存在人脑中,就成算盘了。计算机的发展日新月异,但70多年过去了还是使用冯·诺依曼结构。尽管冯·诺依曼结构有很多缺点,例如什么都保存在内存中使访存成为性能瓶颈,但我们还是摆脱不了它。
虽然经过了长期的发展,以存储程序和指令驱动执行为主要特点的冯·诺依曼结构仍是现代计算机的主流结构。笔者面试研究生的时候经常问一个问题:冯·诺依曼结构最核心的思想是什么?结果很多研究生都会答错。有人说是由计算器、运算器、存储器、输入、输出五个部分组成;有人说是程序计数器导致串行执行;等等。实际上,冯·诺依曼结构就是数据和程序都存在存储器中,CPU从内存中取指令和数据进行运算,并且把结果也放在内存中。概括起来就是存储程序和指令驱动执行。
1.2 衡量计算机的指标
怎么样来衡量一台计算机的好坏呢?计算机的衡量指标有很多,其中性能、价格和功耗是三个主要指标。
1.2.1 计算机的性能
计算机的第一个重要指标就是性能。前面说的用来进行核模拟的高性能计算机对一个国家来说具有战略意义,算得越快越好。又如中央气象台用于天气预报的计算机每天需要根据云图数据解很复杂的偏微分方程,要是计算机太慢,明天的天气预报后天才算出来,那就叫天气后报,没用了。所以性能是计算机的首要指标。
什么叫性能?性能的最本质定义是“完成一个任务所需要的时间”。对中央气象台的台长来说,性能就是算明天的天气预报需要多长时间。如果甲计算机两个小时能算完24小时的天气预报,乙计算机一个小时就算完,显然乙的性能比甲好。完成一个任务所需要的时间可以由完成该任务需要的指令数、完成每条指令需要的拍数以及每拍需要的时间三个量相乘得到。完成任务需要的指令数与算法、编译器和指令的功能有关;每条指令需要的拍数与编译器、指令功能、微结构设计相关;每拍需要的时间,也就是时钟周期,与结构、电路设计、工艺等因素有关。
完成一个任务的指令数首先取决于算法。我们刚开始做龙芯的时候,计算所的一个老研究员讲过一个故事。说20世纪六七十年代的时候,美国的计算机每秒可以算一亿次,苏联的计算机每秒算一百万次,结果算同一个题目,苏联的计算机反而先算完,因为苏联的算法厉害。以对N个数进行排序的排序算法为例,冒泡排序算法的运算复杂度为O(N*N),快速排序算法的运算复杂度为O(N*log2(N)),如果N为1024,则二者执行的指令数差100倍。
编译器负责把用户用高级语言(如C、Java、JavaScript等)写的代码转换成计算机硬件能识别的、由一条条指令组成的二进制码。转换出来的目标码的质量的好坏在很大程度上影响完成一个任务的指令数。在同一台计算机上运行同一个应用程序,用不同的编译器或不同的编译选项,运行时间可能有几倍的差距。
指令系统的设计对完成一个任务的指令数影响也很大。例如要不要设计一条指令直接完成一个FFT函数,还是让用户通过软件的方法来实现FFT函数,这是结构设计的一个取舍,直接影响完成一个任务的指令数。体系结构有一个常用的指标叫MIPS(Million Instructions Per Second),即每秒执行多少百万条指令。看起来很合理的一个指标,关键是一条指令能干多少事讲不清楚。如果甲计算机一条指令就能做一个1024点的FFT,而乙计算机一条指令就算一个加法。两台计算机比MIPS值就没什么意义。因此后来有人把MIPS解释为Meaningless Indication of Processor Speed。现在常用一个性能指标MFLOPS(Million FLoating point Operations Per Second),即每秒做多少百万浮点运算,也有类似的问题。如果数据供不上,运算能力再强也没有用。
在指令系统确定后,结构设计需要重点考虑如何降低每条指令的平均执行周期(Cycles Per Instruction,简称CPI),或提高每个时钟周期平均执行的指令数(Instructions Per Cycle,简称IPC),这是处理器微结构研究的主要内容。CPI就是一个程序执行所需要的总的时钟周期数除以它所执行的总指令数,反之则是IPC。处理器的微结构设计对IPC的影响很大,采用单发射还是多发射结构,采用何种转移猜测策略以及什么样的存储层次设计都直接影响IPC。表1.2给出了龙芯3A1000和龙芯3A2000处理器运行SPEC CPU2000基准程序的分值。两个CPU均为64位四发射结构,主频均为1GHz,两个处理器运行的二进制码相同,但由于微结构不同,IPC差异很大,总体上说,3A2000的IPC是3A1000的2~3倍。
表 1.2: 龙芯3A1000和龙芯3A2000的SPEC CPU2000分值
SPEC程序 |
3A1000 |
3A2000 |
||
运行时间/秒 |
分值 |
运行时间/秒 |
分值 |
|
164.gzip |
503 |
279 |
323 |
433 |
175.vpr |
389 |
360 |
222 |
632 |
176.gcc |
206 |
533 |
110 |
1,003 |
181.mcf |
480 |
375 |
195 |
925 |
186.crafty |
166 |
604 |
122 |
822 |
197.parser |
707 |
254 |
266 |
676 |
252.eon |
159 |
815 |
141 |
924 |
253.perlbmk |
418 |
431 |
279 |
644 |
254.gap |
338 |
325 |
155 |
711 |
255.vortex |
291 |
652 |
125 |
1,520 |
256.bzip2 |
383 |
391 |
285 |
527 |
300.twolf |
421 |
712 |
364 |
824 |
SPEC_INT2000 |
447 |
764 |
||
168.wupwise |
338 |
473 |
123 |
1,296 |
171.swim |
1,299 |
239 |
324 |
957 |
172.mgrid |
1,045 |
172 |
169 |
1,062 |
173.applu |
900 |
233 |
197 |
1,067 |
177.mesa |
244 |
574 |
156 |
896 |
178.galgel |
507 |
572 |
143 |
2,022 |
179.art |
173 |
1,504 |
97 |
2,686 |
183.equake |
457 |
285 |
96 |
1,353 |
187.facerec |
288 |
659 |
146 |
1,306 |
188.ammp |
538 |
409 |
274 |
803 |
189.lucas |
716 |
279 |
181 |
1,104 |
191.fma3d |
550 |
382 |
203 |
1,034 |
200.sixtrack |
553 |
199 |
276 |
399 |
301.apsi |
1,159 |
224 |
235 |
1,108 |
SPEC_FP2000 |
367 |
1,120 |
主频宏观上取决于微结构设计,微观上取决于工艺和电路设计。例如Pentium III的流水线是10级,Pentium IV为了提高主频,一发猛就把流水级做到了20级,还恨不得做到40级。Intel的研究表明,只要把Cache和转移猜测表的容量增加一倍,就能抵消流水线增加一倍引起的流水线效率降低。又如,从电路的角度来说,甲设计做64位加法只要1ns,而乙设计需要2ns,那么甲设计比乙设计主频高一倍。相同的电路设计,用不同的工艺实现出来的主频也不一样,先进工艺晶体管速度快,主频高。
可见在一个系统中不同层次有不同的性能标准,很难用一项单一指标刻画计算机性能的高低。大家可能会说,从应用的角度看性能是最合理的。甲计算机两个小时算完明天的天气预报,乙计算机只要一小时,那乙的性能肯定比甲的好,这总对吧。也对也不对。只能说,针对算明天的天气预报这个应用,乙计算机的性能比甲的好。但对于其他应用,甲的性能可能反而比乙的好。
1.2.2 计算机的价格
计算机的第二个重要指标是价格。20世纪80年代以来电脑越来越普及,就是因为电脑的价格在不断下降,从一味地追求性能(Performance per Second)到追求性能价格比(Performance per Dollar)。现在中关村卖个人电脑的企业利润率比卖猪饲料的还低得多。
不同的计算机对成本有不同的要求。用于核模拟的超级计算机主要追求性能,一个国家只需要一两台这样的高性能计算机,不太需要考虑成本的问题。相反,大量的嵌入式应用为了降低功耗和成本,可能牺牲一部分性能,因为它要降低功耗和成本。而PC、工作站、服务器等介于两者之间,它们追求性能价格比的最优设计。
计算机的成本跟芯片成本紧密相关,计算机中芯片的成本包括该芯片的制造成本和一次性成本NRE(如研发成本)的分摊部分。生产量对于成本很关键。随着不断重复生产,工程经验和工艺水平都不断提高,生产成本可以持续地降低。例如做衣服,刚开始可能做100件就有10件是次品,以后做1000件也不会做坏1件了,衣服的总体成本就降低了。产量的提高能够加速学习过程,提高成品率,还可以降低一次性成本。
随着工艺技术的发展,为了实现相同功能所需要的硅面积指数级降低,使得单个硅片的成本指数级降低。但成本降到一定的程度就不怎么降了,甚至还会有缓慢上升的趋势,这是因为厂家为了保持利润不再生产和销售该产品,转而生产和销售升级产品。现在的计算机工业是一个不断出售升级产品的工业。买一台计算机三到五年后,就需要换一台新的计算机。CPU和操作系统厂家一起,通过一些技术手段让一般用户五年左右就需要换掉电脑。这些手段包括:控制芯片老化寿命,不再更新老版本的操作系统而新操作系统的文档格式不与老的保持兼容,发明新的应用使没有升级的计算机性能不够,等等。主流的桌面计算机CPU刚上市时价格都比较贵,然后逐渐降低,降到200美元以下,就逐步从主流市场中退出。芯片公司必须不断推出新的产品,才能保持盈利。但是总的来说,对同一款产品,成本曲线是不断降低的。
1.2.3 计算机的功耗
计算机的第三个重要指标是功耗。手机等移动设备需要用电池供电。电池怎么用得久呢?低功耗就非常重要。高性能计算机也要低功耗,它们的功耗都以兆瓦(MW)计。兆瓦是什么概念?我们上大学时在宿舍里煮方便面用的电热棒的功率是1000W左右,几个电热棒一起用宿舍就停电了。1MW就是1000个电热棒的功率。曙光5000高性能计算机在中科院计算所的地下室组装调试时,运行一天电费就是一万多块钱,比整栋楼的电费还要高。计算机里产生功耗的地方非常多,CPU有功耗,内存条有功耗,硬盘也有功耗,最后为了把这些热量散发出去,制冷系统也要产生功耗。近几年来,性能功耗比(Performance per Watt)成为计算机非常重要的一个指标。
芯片功耗是计算机功耗的重要组成部分。芯片的功耗主要由晶体管工作产生,所以先来看晶体管的功耗组成。图1.3是一个反相器的功耗模型。反相器由一个PMOS管和一个NMOS管组成。其功耗主要可以分为三类:开关功耗、短路功耗和漏电功耗。开关功耗主要是电容的充放电,比如当输出端从0变到1时,输出端的负载电容从不带电变为带电,有一个充电的过程;当输出端从1变到0时,电容又有一个放电的过程。在充电、放电的过程中就会产生功耗。开关功耗既和充放电电压、电容值有关,还和反相器开关频率相关。
短路功耗就是P管和N管短路时产生的功耗。当反相器的输出为1时,P管打开,N管关闭;输出为0时,则N管开,P管闭。但在开、闭的转换过程中,电流的变化并不像理论上那样是一个方波,而是有一定的斜率。在这个变化的过程中会出现N管和P管同时部分打开的情况,这时候就产生了短路功耗。
漏电功耗是指MOS管不能严格关闭时发生漏电产生的功耗。以NMOS管为例,如果栅极有电N管就导通;否则N管就关闭。但在纳米级工艺下,MOS管沟道很窄,即使栅极不加电压,源极和漏极之间也有电流;另外栅极下的绝缘层很薄,只有几个原子的厚度,从栅极到沟道也有漏电流。漏电流大小随温度升高呈指数增加,因此温度是集成电路的第一杀手。
优化芯片功耗一般从两个角度入手——动态功耗优化和静态功耗优化。升级工艺是降低动态功耗的有效方法,因为工艺升级可以降低电容和电压,从而成倍地降低动态功耗。芯片工作频率跟电压成正比,在一定范围内(如5%~10%)降低频率可以同比降低电压,因此频率降低10%,动态功耗可以降低30%左右(功耗和电压的平方成正比,和频率成正比)。可以通过选择低功耗工艺降低芯片静态功耗,集成电路生产厂家一般会提供高性能工艺和低功耗工艺,低功耗工艺速度稍慢一些但漏电功耗成数量级降低。在结构和逻辑设计时,避免不必要的逻辑翻转可以有效降低翻转率,例如在某一流水级没有有效工作时,保持该流水级为上一拍的状态不翻转。在物理设计时,可以通过门控时钟降低时钟树翻转功耗。在电路设计时,可以采用低摆幅电路降低功耗,例如工作电压为1V时,用0.4V表示逻辑0,用0.6V表示逻辑1,摆幅就只有0.2V,大大降低了动态功耗。
芯片的功耗是一个全局量,与每一个设计阶段都相关。功耗优化的层次从系统级、算法级、逻辑级、电路级,直至版图和工艺级,是一个全系统工程。近几年在降低功耗方面的研究非常多,和以前片面追求性能不同,降低功耗已经成了芯片设计一个最重要的任务。
信息产业是一个高能耗产业,信息设备耗电越来越多。根据冯·诺依曼的公式,现在一位比特翻转所耗的电是理论值的10101010倍以上。整个信息的运算过程是一个从无序到有序的过程,这个过程中它的熵变小,是一个吸收能量的过程。但事实上,它真正需要的能量很少,因为我们现在用来实现运算的手段不够先进,不够好,所以才造成了10101010倍这么高的能耗,因此我们还有多个数量级的优化空间。这其中需要一些原理性的革命,材料、设计上都需要很大的革新,即使目前在用的晶体管,优化空间也是很大的。
有些应用还需要考虑计算机的其他指标,例如使用寿命、安全性、可靠性等。以可靠性为例,计算机中用的CPU可以分为商用级、工业级、军品级、宇航级等。比如北斗卫星上面的计算机,价格贵点没关系,慢一点也没关系,关键是要可靠,我国放了不少卫星,有的就是由于其中的元器件不可靠报废了。因此在特定领域可靠性要求非常高。再如银行核心业务用的计算机也非常在乎可靠性,只要一年少死机一次,价格贵一千万元也没关系,对银行来说,核心计算机死机,所有的储户就取不了钱,这损失太大了。
因此考评一个计算机好坏的指标非常多。本课程作为本科计算机体系结构基础课程,在以后的章节中主要关注性能指标。