来源:AI科技评论
摘要:2017 年图灵奖的两位得主 John L. Hennessy 和 David A. Patterson 就是这个新浪潮的见证者和引领者。
近几年来,不论是普通消费者还是科研人员们都可以感受到两种浪潮,一种是CPU速度的提升越来越不显著了,我们说 CPU 制造商又在「挤牙膏」;另一方面,在深度学习的刺激下,各个半导体巨头和一群 AI 初创企业都开始宣传自己的 AI 芯片。我们仿佛看到一类芯片逐渐走向慢车道,另一类芯片则准备搭台唱戏、跃跃欲试。
这种柳暗花明的背后,显示的正是计算机计算架构的时代变革;新的方法、新的思维、新的目标引领了新的浪潮。2017 年图灵奖的两位得主 John L. Hennessy 和 David A. Patterson 就是这个新浪潮的见证者和引领者。近日他们在 ACM 通讯(Communications of the ACM)发表了一篇长报告《A New Golden Age for Computer Architecture》,详细描述了引发计算机架构新时代到来的种种变化,他们也展望未来的十年将是计算机体系架构领域的「新的黄金十年」。
我们把这篇文章全文编译如下。另外二位还有过一次轻松的访谈,可以参见这里。
ISCA 2018 ,2017 图灵奖颁奖现场,John L. Hennessy(左) 和 David A. Patterson(右)与 Alan Turing 的半身像合影
2018年6月4日,我们回顾了自20世纪60年代以来计算机架构的发展,并以此开始了我们的图灵讲座。除了那个回顾,我们还在讲座中介绍了当前的难题和未来机遇。计算机体系结构领域将迎来又一个黄金十年,就像20世纪80年代我们做研究那时一样,新的架构设计将会带来更低的成本,更优的能耗、安全和性能。
“不能铭记过去的人注定要重蹈覆辙”
——George Santayana,1905
软件与硬件的对话,是通过一种称为指令集的体系结构进行来的。在20世纪60年代初,IBM拥有四条互不兼容的计算机系列,分别针对小型企业,大型企业,科研单位和即时运算,每个系列都有自己的指令集、软件栈和I/O系统。
IBM的工程师们,也包括ACM图灵奖获奖者Fred Brooks在内,希望能够创建一套新的ISA,将这四套指令集有效统一起来,为此他们需要一种可以让低端的8位计算机和高端的64位计算机共享一套指令集的解决方案。
实际上,数据通路的加宽和缩小相对是比较容易的,当时的工程师们面临的最大挑战是处理器中的控制器部分。受软件编程的启发,计算机先驱人物、图灵奖获得者Maurice Wilkes提出了简化控制流程的思路,即将控制器部分定义为一个被称为“控制存储器”的二维数组,可通过内存实现,比使用逻辑门的成本要低得多。数组的每一列对应一条控制线,每一行对应一条微指令,写微指令的操作称为微编程,控制存储器包含使用微指令编写的指令集解释器,因此执行一条传统指令需要多个微指令完成。
下图列出了IBM在1964年4月7日发布的新System/360系列计算机的指令集,四种型号之间的数据通路宽度相差8倍,内存容量相差16倍,频率相差近4倍,最终性能相差50倍。其中M65机型的控制存储器容量最大,成本和售价也最昂贵,而最低端M30机型的控制存储器容量最小,因此也需要有更多的微指令来执行System/360的指令。
IBM将公司的未来押在了这套新指令集上,寄希望其能革新计算行业,赢得未来。而最终IBM也如愿以偿,成功主宰了这一市场,并将其影响力延续至今,这些55年前机型的后代产品现在仍能为IBM带来每年100亿美元的收入。
现在看来,尽管市场对技术问题做出的评判还不够完善,但由于硬件系统架构与商用计算机之间的密切联系,市场最终成为计算机架构创新的是否成功的关键性因素,这些创新往往需要工程人员方面的大量投入。
集成电路,CISC,432,8086,IBM PC
当计算机进入集成电路时代,摩尔定律的力量可以使控制存储器被设计的更大,而这反过来又催生了更复杂的指令集,如Digital Equipment公司于1977年发布的VAX-11/780机型,其控制存储器容量就达到了5120指令字*96bit,而其前代型号仅为256指令字*56bit。
于此同时,一些制造商开始设计可记录控制存储器(WCS),放开微编程功能以使客户可以自行定制功能,其中最有名的机型是图灵奖得主Chuck Thacker和Butler Lampson 和他的同事在1973年为施乐公司Palo Alto研究中心开发的Alto计算机。这是第一台个人计算机,配备有首款点阵显示器和首个以太网局域网,其控制器存储在一个容量为4096指令字*32bit的WCS中。
另一边,20世纪70年代的微处理器仍处于8位时代(如Intel的8080处理器),主要采用汇编语言编程,各家公司的设计师会不断加入新的指令来超越竞争对手,并通过汇编语言展示他们的优势。
戈登·摩尔认为,Intel的下一代指令集将会伴随Intel的一生,他聘请了大批聪明的计算机科学博士,并将他们送到波特兰的一个新工厂,以打造下一个伟大的指令集架构。这个被Intel最初命名为8800的计算机架构项目雄心勃勃,它具有32位寻址能力、面向对象的体系结构,可变位长的指令以及用当时最新编程语言Ada编写的操作系统,是20世纪80年代最具挑战性的一个项目。可惜天不遂愿,这个项目在几年间再三延期,迫使Intel在圣克拉拉启动了一项紧急更换计划,要在1979年推出一款16位处理器,也就是后来的8086。Intel给了新团队52周时间来开发新的指令集以及设计和构建芯片。由于时间紧迫,这个团队实际上是把 8080 的 8 位寄存器和指令集扩展成了 16 位,设计ISA部分仅仅花了10个人3周时间。最终8086如期完成,但在发布时却没引起什么关注。
这一次Intel很走运,当时IBM正在开发一款对位Apple II的个人计算机,正需要16位处理器。IBM一度对Motorola 68000处理器很感兴趣,它拥有类似于IBM 360的指令集,但性能表现却无法满足IBM激进的需求,故转而使用Intel 8086的8位总线版。IBM于1981年8月12日宣布推出该机型,全球销量高达1亿台,为Intel这套指令集铺垫了一个非常光明的未来。
Intel原本的8800项目更名了为iAPX-432,并最终在1981年推出,但它需要多块芯片并且存在严重的性能问题,最终于1986年终止。同样在这一年,Intel推出了80386处理器,将8086指令集的寄存器从16位扩展到了32位。戈登•摩尔的预言成为了现实,Intel的下一代指令集确实一直存续下来,但市场做出的选择是临危上马的8086,而不是被寄予厚望的iAPX-432,这对摩托罗拉68000和iAPX-432的架构师来讲,都是个现实的教训,市场永远是没有耐心的。
从CISC到RISC
20世纪80年代初,人们开始研究CISC(复杂指令集计算机)控制存储器中的大型微程序,而Unix系统的诞生则证明了可以使用高级语言来编写操作系统,因此随后问题的关键从“编程者会使用什么汇编语言”变成了“编译器会生成什么指令”,软硬件接口的显著改进为架构创新带来了机会。
图灵奖得主John Cocke和他的同事为小型计算机开发了更简单的指令集和编译器,并将编译器的目标设定为“仅使用 IBM 360指令集中简单的寄存器到寄存器操作,只以简单的Load和Store操作访问内存”。他们发现,这样简化的流程可以让程序运行速度快上3倍。Emer和Clark发现,VAX指令中有20%的常用指令需要60%的微代码(microcode),但仅占据0.2%的执行时间。
David Patterson把在DEC一次学术休假投入到了研究减少VAX指令中的漏洞上。他认为,如果处理器制造商想要设计更庞大的复杂指令集,就免不了需要一种修复微代码漏洞的方法。Patterson就此问题写了一篇论文,但《Computer》期刊却拒绝刊登,审稿人认为,使用如此复杂以至于需要修补的指令集来设计处理器是很糟糕的。
虽然现在来看,现代的CISC处理器确实包含微代码修复机制,但当时的这次拒稿却让人们怀疑复杂指令集在处理器方面的价值,这也启发了他去开发更简单的精简指令集,以及RISC(精简指令集计算机)。
这些观点的产生,以及由汇编语言向高级语言的转变,为CISC向RISC的过渡创造了条件。首先,精简指令集是经过简化的,其指令通常和微指令一样简单,硬件可以直接执行,因此无需微代码解释器;第二,之前用于微代码解释器的快速存储器被用作了RISC的指令缓存;第三,基于Gregory Chaitin图染色法的寄存器分配器,使编译器能够更简易、高效地使用寄存器,这指令集中那些寄存器到寄存器的操作有很大好处;最后,集成电路规模的发展,使20世纪80年代的单块芯片足以包含完整的32位数据路径以及相应的指令和数据缓存。
下图是加州大学伯克利分校1982年研发的RISC-I处理器和斯坦福大学1983年研发的MIPS处理器,两颗芯片充分展示了RISC的优势,并最终发表在1984年IEEE国际固态电路会议上。加州大学和斯坦福大小的研究生研发出了比行业内现有产品更优秀处理器,这是非常了不起的时刻。
这些由学术机构开发的芯片,激励了许多企业开始发力RISC处理器,并成为此后15年中发展最快的领域。其原因是处理器的性能公式:
时间/程序=操作数/程序*(时钟周期)/指令*时间/(时钟周期)
DEC公司的工程师后来表明,CISC处理器执行每个程序的操作数大约为RISC处理器的75%(上式第一项),在使用类似的技术时,CISC处理器执行每个指令要多消耗5到6个时钟周期(上式第二项),使得RISC处理器的速度大约快了3倍。
这样的公式在20世纪80年代还没有进入计算机体系结构的书中,所以我们在1989年编写了《Computer Architecture: A Quantitative Approach》一书,使用测量和基准测试来对计算机架构进行量化评估,而不是更多地依赖于架构师的直觉和经验,使用的量化方法也受到了图灵奖得主Donald Knuth关于算法的书的启发。
VLIW、EPIC、Itanium
指令集架构的下一次创新试图同时惠及RISC和CISC,即超长指令字(VLIW)和显式并行指令计算机(EPIC)的诞生。这两项发明由Intel和惠普共同命名,在每条指令中使用捆绑在一起的多个独立操作的宽指令。与RISC一样,VLIW和EPIC的目的是将工作负载从硬件转移到编译器上,它们的拥护者认为,如果用一条指令可以指定六个独立的操作(两次数据传输,两次整数操作和两次浮点操作),并且编译器技术可以有效地将操作分配到六个指令槽,则硬件可以变得更简单。
Intel和惠普合作设计了一款基于EPIC理念的64位处理器Itanium(安腾),想用其取代32位x86处理器。Intel和惠普对Itanium抱有很高的期望,但实际情况却与他们的预期并不相符,EPIC虽然适用于高度结构化的浮点程序,但却很难在可预测性较低的缓存丢失或难以预测分支的整型程序上实现高性能。
Donald Knuth后来指出,Itanium的设想非常棒,但事实证明满足这种设想的编译器基本上不可能写出来。开发人员注意到Itanium的延迟和性能表现不佳,并借鉴泰坦尼克号事件重新将其命名为“Itanic”。不过正如前面所提到的,市场永远是没有耐心的,最终64位的x86-64成为了继承者,没有轮到Itanium。
不过一个好消息是,VLIW仍然小范围应用于数字信号处理等对分支预测和缓存要求不高的领域。
RISC vs. CISC,PC和后PC时代的宿命对决
Intel和AMD依靠500人的设计团队和卓越的半导体技术来缩小x86和RISC之间的性能差距,而受到精简指令相对于复杂指令性能优势的启发,Intel和AMD将RISC微指令的执行流程化,使指令解码器在运行中将复杂的x86指令转换成类似RISC的内部微指令,从而让x86处理器可以吸收RISC在性能分离指令、数据缓存、芯片二级缓存、深度流水线以及同时获取和执行多个指令等许多优秀的设计。在2011年PC时代的巅峰时期,Intel和AMD每年大约出货3.5亿颗x86处理器。PC行业的高产量和低利润率也意味着价格低于RISC计算机。
在Unix市场中,软件供应商会为不同的复杂指令集(Alpha、HP-PA、MIPS、Power和SPARC)提供不同的软件版本,而PC市场上绝对主流的指令集只有一套,软件开发人员只需兼容x86指令集即可。全球每年出货数亿台PC,软件就成为了一个巨大的市场。更大的软件基础、相似的性能和更低的价格使得x86处理器在2000年之前同时统治了台式机和小型服务器市场。
苹果公司在2007年推出了iPhone,开创了后PC时代。智能手机公司不再购买处理器,而是使用其他公司的设计来构建自己的SoC。移动设备设计人员需要对芯片面积和能效以及性能进行综合评估,CISC处理器在这一点上处于劣势。此外,物联网的到来需要海量的处理器,更加需要在芯片尺寸、功率、成本和性能上做权衡。这种趋势增加了设计时间和成本的重要性,进一步使CISC处理器处于不利地位。在今天这个“后PC时代”,x86处理器的出货量自2011年达到峰值以来,每年下降近10%,而RISC处理器的出货量则飙升至200亿。如今,99%的32位和64位处理器都是RISC处理器。
总结这些历史,可以说市场已经解决了RISC和CISC宿命之争。CISC赢得了PC时代的后期阶段,但RISC正在后PC时代占据主导。复杂指令集领域已经几十年没有新的指令集出现了,对于今天的通用处理器来说,最佳的选择仍然是精简指令集。
处理器架构当前面临的挑战
“如果一个问题无解,那它可能不是一个问题,而是一个事实,我们不需要解决,而是随着时间的推移来处理。”
——Shimon Peres
虽然前面的部分聚焦在指令集架构的设计上,但大部分计算机架构师并不设计新的指令集,而是利用当前的实现技术来实现现有的ISA。自20世纪70年代后期以来,选择的技术一直是基于MOS(金属氧化物半导体)的集成电路,首先是 nMOS(n型金属氧化物半导体),然后是CMOS(互补金属氧化物半导体)。
戈登·摩尔在1965年预测,集成电路的晶体管密度会每年翻一番,1975年又改为每两年翻一番,这一预测最终被称为摩尔定律。在这一预测中,晶体管密度呈二次增长,惊人的进化速度使架构师可以用更多晶体管来提高性能。
摩尔定律和登纳德缩放定律的失效
如图2所示,摩尔定律已经持续了几十年,但它在2000年左右开始放缓,到了 2018 年,实际结果与摩尔定律的预测相差了15倍,但摩尔在2003年做的判断已不可避免(可参考GE Moore 的《No exponential is forever: But 'forever' can be delayed!》论文)。基于当前的情况,这一差距还将持续增大,因为CMOS已经接近极限。
图2 单个英特尔微处理器上的晶体管数量 vs. 摩尔定律
与摩尔定律相伴的是由罗伯特·登纳德(Robert Dennard)预测的登纳德缩放定律(Dennard scaling;又称作MOSFET缩放定律)。Robert Dennard 在 1974 年提出,晶体管不断变小,但芯片的功率密度不变。随着晶体管密度的增加,每个晶体管的能耗将降低,因此硅芯片上每平方毫米上的能耗几乎保持恒定。由于每平方毫米硅芯片的计算能力随着技术的迭代而不断增强,计算机将变得更加节能。不过,登纳德缩放定律从 2007 年开始大幅放缓,大概在2012 年接近失效(见图 3)。
图3每个芯片上的晶体管及每平方毫米的功率
1986 年至 2002 年间,利用指令级并行(ILP)是提高架构性能的主要方法,伴随着晶体管速度的提高,其性能每年能提高约50%。登纳德缩放定律的终结意味着架构师必须找到更有高效的方法利用并行性。
要理解增加ILP 所带来高效率,可以看一看当前的处理器核心比如ARM、英特尔、AMD。假设该芯片有15级流水线(管线),每个时钟周期可以发送 4 条指令,那么它在任何时刻都有多达60条指令,包括大约15个分支,它们占执行指令的大约25%。为了能够充分利用流水线,需要预测分支,并根据推测将代码放入流水线以便执行。推测的使用同时是 ILP高性能和低能效的源头。如果分支预测达到完美,推测就能提高 ILP 性能,但能耗会增加一些(也可能节约能耗),但如果分支预测出现失误,处理器就必须放弃错误的推测指令,计算所耗能量就会被浪费。处理器的内部状态也必须恢复到错误预测分支之前的状态,这将消耗额外的能量和时间。
要理解这种设计的挑战性,想一想正确预测15个分支就可知道其中的难度。如果处理器架构想把性能的浪费控制在10%以内,那么它必须在 99.3%的时间里正确预测每个分支。很少有通用程序能够如此准确地预测。
要理解性能浪费叠加的结果,可以参见图4中,图中显示了有效执行的指令,但由于处理器推测错误而被浪费。对英特尔酷睿 i7 基准测试上,19%的指令都被浪费了,但能量的浪费情况更加严重,因为处理器必须使用额外的能量才能恢复到推测失误前的状态。这样的测试导致许多人得出结论,架构师需要一种不同的方法来实现性能改进。于是迎来了多核时代的诞生。
图4 不同的SPEC整型数基准测试,英特尔酷睿 i7 浪费的指令占完成指令总数的百分比
多核将识别并行性和决定如何利用并行性的任务转移给程序员和编程语言。多核并未解决节能的挑战,而这种挑战因登纳德缩放定律终结更加严峻。每个活跃的核都会消耗能量,无论其对计算是否有有效贡献。一个主要的障碍可以用阿姆达尔定律(Amdahl's Law)表述,该定理认为,在并行计算中用多处理器的应用加速受限于程序所需的串行时间百分比。这一定律的重要性参见图5,与单核相比,多达64个核执行应用程序速度的差别,假设串行执行的不同部分只有一个处理器处于活动状态。例如,如果只有1%的时间是串行的,那么 64核的配置可加速大约35倍,当然能量也与64个处理器成正比,大约有45% 的能量被浪费。
图5 阿姆达尔定律对程序加速的影响
真实的程序当然会更加复杂,部分组件允许在给定时刻使用不同数量的处理器。然而,需要定期性通信和同步意味着大部分应用仅可高效使用一部分处理器。尽管阿姆达尔定律已经出现 50 多年了,这仍然是一个很大的困难。
随着登纳德缩放定律的终结,芯片内核数量的增加意味着能耗也随之增加。不幸的是,进入处理器的电能有一部分会转化为热能,因此多核处理器受限于热耗散功率(TDP),即封装和冷却系统在最大负载时的驱散热量的最大限度。尽管一些高端数据中心可能使用更先进的封装和冷却技术,但没有一个计算机用户想要在自己桌子上放置小型热交换器,或者为手机增加散热器。TDP 的限制性直接导致了暗硅时代,也就是处理器通过降低时钟频率或关闭空闲内核来防止处理器过热。这种方法的另一种解释是:一些芯片可将其宝贵的能量从空闲内核转移到活跃内核。
登纳德缩放定律的结束,摩尔定律放缓以及阿姆达尔定律正当其时,意味着低效性将每年的性能改进限制在几个百分点(如6所示)。想获得高的性能改进(像 20 世纪八九十年代那样)需要新的架构方法,新方法应能更加高效地利用集成电路。接下来我们将讨论现代计算机的另一个主要缺陷——计算机安全的支持以及缺乏,之后再继续探讨有效利用集成电路的新方法。
图6 计算机性能的提升(SPECintCPU)
被忽略的计算机安全
20 世纪 70 年代,处理器架构师主要专注于计算机安全,涉及保护环和功能安全。架构师们意识到,大部分漏洞都存在于软件中,但他们认为架构能会有所帮助。这些功能大部分未被操作系统使用,这些操作系统有意专注于所谓的良性环境(如个人电脑),并且这些功能涉及大量消耗,因此被淘汰。在软件社区中,很多人认为正式验证技术如微内核等技术会为构建高度安全的软件提供有效保障。不幸的是,我们的软件系统规模和性能驱动器意味着此类技术无法跟上处理器性能。结果就是大型软件系统仍然有很多安全漏洞,且由于海量在线个人信息和云计算的使用,其影响被放大。
登纳德缩放定律的终结意味着架构师必须找到利用并行化的更高效方式。
架构师们和其他人很晚才意识到安全的重要性,但他们已经开始对虚拟机和加密提供硬件支持。不幸的是,推测给许多处理器带来了未知但明显的安全缺陷。特别是,Meltdown和Spectre安全漏洞导致新漏洞利用位体系结构中的漏洞,使受保护信息较快地遭到泄露,这两种漏洞都使用了旁路攻击。2018 年,研究者展示了在攻击者不将代码加载到目标处理器的情况下,如何利用 Spectre 变体导致网络信息泄露。尽管这次名为NetSpectre的攻击泄露信息速度较慢,但它会使同一局域网(或云中同一集群)中的所有机器都受到攻击,这会产生许多新的漏洞。还有两个被报告的漏洞存在于虚拟机架构,其中一个叫Foreshadow,会影响专门保护高风险数据(如加密密钥)的英特尔SGX 安全机制。现在,每个月都会发现新的漏洞。
旁路攻击并非新鲜事,但在最早期的大多数情况,软件漏洞是攻击成功的关键。但在Meltdown、Spectre 等攻击中,硬件的缺陷导致受保护信息泄露。处理器架构师如何定义什么是正确的ISA是一个源头的难题,因为标准中并未说明执行指令序列的性能影响,而仅仅涉及 ISA-visible 执行架构状态。架构师需要重新思考ISA正确实现的定义,以避免类似的安全漏洞。与此同时,他们还应该重新思考对计算机安全关注的侧重点,以及架构师如何与软件设计师一起实现更加安全的系统。架构师(以及所有人)都过于依赖信息系统,以至于对安全的重视程度不如对一流设计的关注。
「我们面前有一些令人目瞪口呆的机会,不过它们把自己伪装成了看似无法解决的困难」。 -John Gardner
不论是对于 ILP 的技术或者多核心处理器,由于为通用计算设计的微处理器注定了效率较低,再加上Dennard Scaling定律和摩尔定律走向终结,所以在我们看来,处理器架构师和设计师们很有可能再也无法让通用处理器的性能以之前那样的速度继续大幅提高。但是我们仍然需要想办法继续提升硬件性能、为未来的新的软件功能留下发展空间,我们就必须仔细思考这个问题:有没有其他的有潜力的方案?
比较明显的方案有两种,以及把这两种方案合并在一起的话我们还可以得到第三种方案。
执行性能优化
第一种方案是,现代软件的编写中大量使用了高级语言,其中有动态类型和动态存储管理。然而不幸的是,这些语言的编译和执行是非常低效的。Leiserson 等人用矩阵乘法的小例子说明了这种低效性。
Python 是一种当前火热的编程语言,也是一种典型的高级、动态类型语言。如下面图 7,仅仅是把本来用 Python 编写的程序用 C 语言重新写一遍,就可以把程序的性能提高 47 倍。在多核心处理器上并行运行多个循环可以继续得到大约 7 倍的性能提升。优化程序的存储布局,让程序使用处理器中的缓存(而不是外部安装的内存)可以提升 20 倍性能,最后,如果加入拓展的计算硬件,用能够在每个指令周期内计算 16 次 32 位运算的单指令多数据并行(SIMD)计算单元进行运算的话,我们还可以再把性能提高9倍。把以上这些改进全部用起来的话,
一个运行在英特尔多核处理器上的、经过高度优化过的程序可以比最初的 Python 版本快超过 6 万倍。
这当然只是一个很小的例子,一般的程序员可能自己就会使用一个有优化作用的库来享受这种提升。虽然这个例子把性能的变化展现得很夸张,但是在许许多多的程序中,提升 100 倍或者 1000 倍的性能还是完全可以实现的。
有一个有趣的研究方向是,考虑其中的一些性能差距是否可以用更好的编译器技术来补上,当然了也可以同时搭配一些计算架构的改进。虽然高效的语言翻译、以及高效实现 Python 这类的高级脚本语言确实有很大困难,但潜在的性能收益也是巨大的。即便我们只实现了这些潜力中的 25% 就已经可以让 Python 程序的运行速度提高数十倍甚至一百倍。这个简单的例子就清晰地展示了关注软件工程师的生产力的现代编程语言和关注程序性能表现的传统方法之间的巨大鸿沟。
设计专用硬件
领域专用的计算架构。除了改进软件执行效率的第一种方案之外,第二种方案更加以硬件为中心,那就是为某个特定的领域问题设计专用的计算架构,从而为这些问题带来显著的性能(和效率)提升。这种方案的名字,DSA,「domain-specific architectures」,描述的就是这种为特定的领域问题而专门定制设计的处理器,它们可编程,同样也是图灵完备的,但只适用于特定的某一类问题。从这个角度来讲,它们和专用集成电路 ASIC 之间也有所不同,ASIC 只执行单一的功能,对应的程序代码几乎从不变化。DSA 则常被称为加速器,相比于把程序的所有功能都在为通用计算的 CPU 上执行,DSA 可以让程序中的一部分计算运行得更快。更重要的是,DSA 可以让一些程序得到明显更高的性能,因为它们就是为了贴近这些程序的计算需求而设计的。图像处理单元 GPU、深度学习中使用的神经网络芯片、软件定义网络处理器 SDN 都是典型的例子。DSA 可以达到高得多的性能表现和高得多的能量效率,是由于以下四个原因:
第一点,也是最重要的一点,DSA 可以为具体的领域问题采用更为高效的并行计算设计。比如,单指令多数据并行(SIMD)就比多指令多数据并行(MIMD)的效率高得多,因为它只需要获取一条指令流就可以让处理单元在锁定步骤内执行运算。SIMD 的灵活性固然不如 MIMD 高,但是它很符合许多 DSA 的需求。DSA 中还有可能使用 VLIW 方案来实现 ILP,而不是使用更复杂的乱序执行机制。正如前面提到的,VLIW 无力与通用计算代码竞争,但是在有限制条件的领域中它就可以高效得多,因为它的控制机制简单得多。尤其是,多数的高端通用计算处理器都是乱序执行的超标量处理器,对于指令初始化和指令完成都需要复杂的控制逻辑。相比之下,VLIW 在编译的时候就已经执行好了必需的分析和流程规划,在显示并行的程序中就可以起到很好的效果。
第二,DSA 可以更高效地利用不同层次的存储器。Horowitz 指出,读写存储器的成本已经变得高于数学运算的成本了。比如,从一个 32KB 容量的缓存里读取一个块需要消耗的能量差不多要比执行一次 32 位整型加法高 200 倍。正因为这种差别的存在,想要达到高的能源效率,优化存储器的读写就至关重要。通用计算处理器执行代码的方式是,一般来说存储器的读写都具有时间和空间上的局部性,但是其他状况是在程序编译时很难预测的。所以 CPU 会配合使用多级缓存,以便增加存储器带宽,同时缓解相对较慢的片外存储(内存,DRAM)的高延迟问题。CPU 消耗的电能里,常常有一半都是花在了这些多级缓存上面,不过它们的作用也就是避免了大多数对片外 DRAM 的访问,要知道,读写 DRAM 消耗的能源要比读写最后一级缓存还要高差不多 10 倍。
缓存的缺点会在这两种情况下暴露出来:
当数据集非常大的时候,缓存的时间和空间局部性都很差;
当缓存表现得非常好的时候,也就是说局部性非常高的时候,这其实说明大多数缓存都是空闲的。
在那些存储器的读写模式有良好定义、在编译时就可以发现的应用中(典型的 DSL 都符合),程序员和程序的编译器都可以优化存储器的使用,效果要比动态分配缓存更好。所以 DSA 通常会使用一个层次式的存储器,它的操作也是由软件明确定义的,这和向量处理器的运行方式很类似。对于适合的应用,用户控制的存储器消耗的能源要比缓存低多了。
第三,在适当的时候,DSA 可以用更低的精度做运算。通用计算 CPU 一般支持 32 位和 64 位整型以及浮点数据运算。不过对于机器学习和图形领域的许多应用来说,这样的精度都高于实际需求了。比如在深度神经网络中,推理任务经常使用 4 位、8 位或者 16 位的整型,以获取更高的数据吞吐量、更高的计算吞吐量。类似地,在深度神经网络的训练中需要使用浮点类型,32 位就已经够用了,16 位很多时候都可以。
第四,如果程序是用领域专用语言(DSL)编写的,由于语言本身对并行化有更好的支持,DSA 也就可以从中受益。这改进了存储器读取的结构和表示,也可以更容易地把应用程序映射到一个领域专用的处理器上去。
领域专用语言
DSA 需要把编程语言中的高级操作对应到硬件架构上去,但是想要从 Python、Java、C、Fortan 这样的为通用型计算设计的语言中提取这样的结构和信息实在是太难了。领域专用语言(DSL)让这个过程变得可以实现,而且也让我们有机会高效地为 DSA 编程。比如,DSL 中可以定义显式的向量、稠密矩阵、稀疏矩阵操作,这样 DSL 的编译器就可以高效地把这些操作映射到处理器中。许多语言属于 DSL,比如矩阵运算语言 Matlab,深度神经网络编程用的数据流语言 TensorFlow,DSN 编程语言 P4,以及描述图像处理中高级变换操作的 Halide。
使用 DSL 的时候也有一个挑战,就是如何让硬件架构设计保持足够的独立性,这样在一种 DSL 中编写的软件可以迁移到不同的硬件架构,同时在把软件映射到下方的 DSA 的时候还能过保持足够高的效率。比如,TensorFlow 中的 XLA 系统可以把编写的程序翻译成使用不同处理器的版本,在英伟达 GPU 和谷歌 TPU 上都可以运行。在 DSA 之间平衡可迁移性的同时还要保持足够高的效率,这对语言设计师、编译器设计师、DSA 架构师们来说都是一个有意思的科研挑战。
下面用 TPUv1 这款 DSA 芯片举例做详细的解释。谷歌 TPUv1 的设计目标是加速神经网络的推理过程。这款 TPU 从 2015 年就投入了生产环境开始使用,它支持着谷歌的各种应用计算需求,包括搜索查询、语言翻译、图像识别,一直到 DeepMind 的围棋/象棋 AI AlphaGo/AlphaZero。这个芯片的设计目标就是把深度神经网络推理时的性能表现和能量效率提升 10 倍。
如下方图 8 所示,TPU 的内核结构设计和通用计算处理器完全不同。其中的主计算单元是一个矩阵计算单元,这是一个脉动列表结构,它可以在每个时钟周期进行一次 256x256 矩阵的乘法加法运算。在这项功能上联合使用的 8 位精度、高效率的脉动架构、SIMD 控制、专门划分出的一大片芯片面积,最终让这个乘法累加器的每时钟周期性能比一般的单核心通用计算 CPU 提升了大约 100 倍。而且,TPU 中并没有使用缓存,它使用的是大小为 24MB 的本地存储器,这相当于是 2015 年时期的相同功耗的 CPU 上带有的缓存空间的 2 倍。最后,激活值存储器和权重存储器(以及保留权重的 FIFO 架构)都通过一个用户控制的高带宽存储通道连接在一起。在基于谷歌数据中心的六种常见推理问题的加权性能统计中,TPU 要比通用计算 CPU 快 29 倍。由于 TPU 消耗的电能还不到 CPU 的一半,在处理这些负载时 TPU 的能量效率要比通用计算 CPU 高 80 倍还不止。
总结
我们分析了通过提高硬件效率来提升程序运行性能的两种不同的方案。方案一,改进通常是解释执行的现代高级编程语言的性能;方案二,设计领域专用的计算架构,相比于通用计算 CPU 的表现,这样可以极大改进运行速度和能源效率。DSL 也是改进硬件/软件接口,从而让计算架构设计师们可以做出 DSA 这样的创新的另一个重要例子。
想要通过这些方式取得程序性能的显著提高,需要一支垂直集成的设计团队,他们需要了解应用、了解领域专用语言以及对应的编译器技术、了解计算机架构和组件,并且了解其中蕴含的实现技术。在整个计算机产业链变得水平整合之前,计算领域的许多早期工作都表现出了强烈的「垂直集成、可以跨越多个不同的抽象层次」的特点。而在现在这个新时代中,垂直整合能力变得更为重要,能够做出重要的权衡并进行检验和优化的团队将会占有先机。
这些改进机会已经引发了计算架构创新的新浪潮,吸引了许多来自不同计算架构设计逻辑的竞争者:
GPU - 英伟达 GPU 有许多核心,每个都有很大的寄存器,有许多硬件线程,也有缓存
TPU - 谷歌 TPU 主要依赖其中的大规模二维脉动乘法累加器,以及依靠软件控制片上存储
FPGA - 微软在数据中心中部署了现场可编程逻辑阵列(FPGA),这些数据中心是专为神经网络应用优化的
CPU - 英特尔提供的 CPU 带有许多核心,然后用大容量的多级别缓存和一维 SIMD 指令增强 CPU 的性能;英特尔也提供微软使用的 FPGA,以及另一种更接近 TPU 的新型神经网络处理器。
除了这些大体量的竞争者之外,也有好几十家初创企业提出了自己的想法。为了满足不断增长的计算需求,计算架构设计师们把这样的芯片成百上千地互相连接起来,形成了为神经网络计算服务的超级计算机。
深度神经网络的瀑布式结构也为计算机架构设计带来一段有趣的时光。很难预测 2019 年中这些不同的方向中是否会出现胜利者,但是市场最终一定会为这场竞争分出胜负,就像它过去也曾分出了一场计算机架构之争的胜负一样。
受到开源软件的成功的启发,计算机架构的第二个发展机遇在于开放 ISA。为了创建一个「处理器的 Linux」,这个领域需要工业标准级别的开放 ISA,这样整个生态中才可以创建开源的核心,在不同公司持有各自的专有核心架构的环境中形成补充。如果许多组织结构都使用同样的 ISA 设计处理器,更激烈的竞争可能会带来的更快的创新和发展。这里的发展目标是为不同的使用用途提供不同规模的处理器设计,可以有 100 美元一个的处理器,也可以有几美分一个的处理器。
这里的第一个例子就是 RISC-V,UC 伯克利大学开发的第五代 RISC 架构。在 RISC-V 基金会的管理之下,RISC-V 有一整个生态维护着这个架构。选择了开放,也就让这个 ISA 也可以在公众中露面,软件和硬件专家们也可以在做出最终决定之前就展开合作。开放体系还会带来一个好处,就是 ISA 很少会出于纯市场营销的原因而扩大,相比之下专有指令集就经常会为了市场营销而增扩充指令集。
首先,RISC-V 是一个模块化的指令集。一小组基础指令首先支持整个开源软件框架的运行,然后有一些标准的拓展指令,设计师们可以根据自己的需求添加或者删除。基础指令含有 32 位和 64 位地址的版本。RISC-V 指令集的增长完全可以只依靠可选的拓展指令的增加,支持软件框架运行的基础指令不增加任何新的拓展也不会有任何问题。专有指令集的处理器架构一般都会需要向前的二进制兼容性,这意味着如果一家处理器制造商决定在某一代处理器中增加一个新的功能,那么这家制造商未来的所有处理器都需要保留对这个功能的支持。但 RISC-V 就不需要这样,所有的功能增强都是可选的,而且如果没有应用需要的话就可以随时删除。目前 RISC-V 中有如下几个标准的拓展指令集,用首字母作为它们的简称
M. 整型乘法/除法
A. 原子内存操作
F/D. 单精度/双精度浮点运算
C. 压缩指令
其次,RISC-V 有一个特色是 ISA 的简洁性。下面提供了一组 RISC-V 与 ARM 公司在近似时间开发的 ARMv8 架构的对比,虽然对比的内容不是完全可以量化的。
指令更少。RISC-V 的指令更少,基础指令只有 50 条,这个数量和这些指令的性质和最初的 RISC-I 惊人地相似。其它的几个标准拓展指令集,M、A、F 和 D,一共增加 53 条指令,再加上 C 的另外 34 条,一共也只有 137 条。ARMv8 则有超过 500 条。
指令格式更少。RISC-V 的指令格式更少,只有 6 种,而 ARMv8 至少有 14 种。
第三,RISC-V 的简洁性不仅降低了设计处理器的复杂度,也减小了验证硬件正确性的难度。由于 RISC-V 的目标就是要应用在包括数据库的高性能计算芯片到 IoT 设备上的低功耗芯片上,设计验证也可以在开发成本中占据不小的比例。
第四,RISC-V 是一个完全从头开始的设计,它是在初始设计的 25 年后开始的。它的设计师们从前几代的设计中吸取了许多错误经验。与第一代的 RISC 架构不同,RISC-V 避开了依赖微架构和依赖技术的特征(比如延迟分支和延迟载入)以及很新的创新(比如寄存器窗口),实际上这些功能都随着编译器技术的发展而被替代了。
最后,RISC-V 还可以为定制化设计的加速器提供很大的操作指令设计空间,这为 DSA 提供了良好的支持。
除了 RISC-V 之外,英伟达也在 2017 年发布了一个免费开放的架构,名为英伟达深度学习加速器(NVDLA),这是一个用于深度学习推理的标量、可配置的 DSA。它的可选配置包括数据类型(8 位整型、16 位整型、16 位浮点)以及其中的二维乘法矩阵的大小。根据不同的配置,芯片面积可以有 0.5mm2 到 3mm2 的不同大小,功耗也有 20mW 到 200mW 不同。这个架构的 ISA、软件架构、实现方案也都是全部开放的。
开放的简单架构实际上会带来安全方面的好处。首先,安全专家们并不相信模糊不清就可以带来安全,所以开放的技术实现方案对他们更有吸引力;开放的技术实现也就需要开放的架构。同等重要的是,有越来越多的人和组织机构参与,也就可以围绕安全的架构设计做出更多改进。专用的架构把参与者局限为企业的员工,而开放的架构允许全世界学术和工业界的人参与提高安全性。更重要的是,这样开放的架构、技术实现、软件架构,再加上 FPGA 的高可塑性,都意味着架构设计师们可以在线部署并评价新的解决方案,而且这个周期不再是以年计,而是以周计。虽然 FPGA 比定制化芯片慢大约 10 倍,但这样的性能表现也已经足以支持用户的在线使用,也就可以针对真正的攻击者更及时地做出安全改进。我们期待开放的计算架构未来成为架构设计师和安全专家们进行软硬件联合设计的典型范例。
Beck 等人撰写的《软件敏捷开发手册》为软件开发领域带来了一场革命,它克服了传统瀑布式开发中精心设计的开发计划和文档经常失效的问题。小的编程团队得以快速开发出包含了核心功能但并不完善的软件原型,然后在下一次迭代开始前就获得用户反馈。竞争性的敏捷开发可以让 5 到 10 人的开发团队以 2 到 4 周一次迭代的速度快速前进。
再一次,受到软件开发领域成功经验的启发,硬件领域的第三个机遇就是敏捷硬件开发。对架构设计师们来说也有一个好消息,现代电子计算机辅助设计(ECAD)工具提高了抽象级别,可以让敏捷开发以及对应的更高级别的抽象在不同的设计之间重复使用。
如果说要把软件开发中的每四周一次迭代的快速前进方式照搬到硬件开发,一听之下会觉得难以置信,毕竟从硬件设计定版到得到芯片成品就有好几个月的时间。而下面的图 9 就展示了敏捷开发过程中可以在适当的抽象级别上更改原型。最中央的抽象级别是软件模拟器,也是在迭代中做改动最简单、最快的部分。下一层是可以比细致的软件模拟器运行快数百倍的 FPGA。在 FPGA 上可以运行操作系统,也可以进行全功能的性能评测,比如 SPEC 中的测试项目;这让原型的评价更加准确。亚马逊云服务就提供了 FPGA,架构设计师们无需购买 FPGA 硬件并建立实验室就可以使用 FPGA 做自己的验证。为了获得芯片面积和功耗的具体数值,下一层的 ECAD 工具可以生成芯片的布局图。在工具运行完毕之后还需要人工进行一些步骤,对结果进行微调,确保新的处理器已经准备好投入生产了。处理器设计师们把这下一层称作「tape in」。前面的这四个级别都可以使用每四周一次的迭代速度。
如果是出于科研目的,我们在 tape in 这一步就可以停下来了,因为这时就已经可以获得非常准确的面积、能耗、性能的估计数据了。不过如果真的停下来的话,那就像参加长跑比赛,最后在重点线前 50 米停了下来,「因为可以准确地预测出最终要花多少时间了」。既然已经在比赛的准备以及前面的大部分赛程中投入了许多精力,但只要不冲过终点线,那就没办法享受到真正的兴奋和满足。所以其实,硬件工程师在有个方面比软件工程师强,就是因为他们最终会生产出切实可感的物品。把芯片成品拿回来测量、运行真正的程序、把芯片展示给他们的朋友和家人们看,这都是硬件设计工作中非常幸福的时刻。
许多研究人员会认为他们需要在芯片试产之前停下来,因为芯片的制造实在是太贵了。实际上,当芯片很小的时候,它的制造价格就非常便宜。架构设计师们委托半导体厂商制造 100 个 1mm2 面积的芯片只需要花 1.4 万美元。如果是以 28nm 工艺制作,1mm2 的面积上就可以放下数百万个晶体管,足以容纳一个 RISC-V 处理器再加一个英伟达加速器。如果要制造一个很大的芯片,那么最外面这一步可能就会花很多钱,但是如果是为了展现新的想法的话,小的芯片就可以做到。
「黎明之前正是最灰暗的时刻」-Thomas Fuller
要从历史经验中学习,有几件事架构师们必须知道:软件开发领域的创新点子同样可以启发硬件架构设计师们,提升硬件/软件接口设计的抽象级别可以为创新带来机会,以及市场最终会为计算机架构之争画上句号。iAPX-432 和 Itanium 的故事说明了硬件架构方面的投资可能无法带来对等的回报,而 S/360、8086、ARM 架构则能够年复一年地带来充沛的盈利。
Dennard Scaling 定律和摩尔定律走向终结,以及标准微处理器的性能提升越来越慢并不是什么必须解决不可的问题,而实际上,它们完全可以看作是令人激动的新机遇。高级别、领域专用的语言和架构把架构设计师们从专用指令集不断扩充的链条中解放出来,同样也释放了公众对于更高的安全性的需求,这都会带来计算机架构的新的黄金时代。另外依靠开源生态的帮助,敏捷开发的芯片也会越来越令人信服地展现出它的优势,并逐步越来越快地取得商业上的成功。对于通用处理器的设计理念,ISA 未来也将随着时间的流逝而越发显得熠熠生辉,就像 RISC 一样。在新的黄金时代中我们可以期待继续看到上个黄金时代那样的高速发展,只不过这次首当其冲的是价格、能耗以及安全,性能当然也会有继续的提高。
在未来 10 年中,我们可以期待在计算机架构领域也看到寒武纪生物大爆炸那样地充满新鲜创意,这对于学术界和工业界的计算机架构设计师们来说会是一段充满激情的时光。
未来智能实验室是人工智能学家与科学院相关机构联合成立的人工智能,互联网和脑科学交叉研究机构。
未来智能实验室的主要工作包括:建立AI智能系统智商评测体系,开展世界人工智能智商评测;开展互联网(城市)云脑研究计划,构建互联网(城市)云脑技术和企业图谱,为提升企业,行业与城市的智能水平服务。
如果您对实验室的研究感兴趣,欢迎加入未来智能实验室线上平台。扫描以下二维码或点击本文左下角“阅读原文”