嵌入式C语言自我修养:从芯片、编译器到操作系统
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.6 多核CPU

半导体工艺和架构是提升CPU性能的双驾马车。CPU的发展史,其实就是处理器架构和半导体工艺交互升级、协同演进的发展史。半导体工艺采用更先进的制程,晶体管尺寸变小了,芯片面积降低了,CPU的主频就可以做得更高;在相同的工艺制程下,通过不断优化CPU架构,从Cache、流水线、乱序执行、SIMD、多发射、指令预测等方面不断更新迭代,就可以设计出比别家公司性能更高、功耗更低的处理器。

2.6.1 单核处理器的瓶颈

在相同的半导体工艺制程下,芯片的面积越大,芯片的良品率就越低,芯片的成本就会越高,功耗也会越大。美国加利福尼亚州有家名叫Cerebras的创业公司发布了一款专为人工智能打造、号称史上最大的AI芯片,这款名为Wafer Scale Engine(WSE)的芯片由1.2万亿个晶体管构成,采用台积电16nm工艺,芯片面积比一个iPad还大,功耗15 000W,比6台电磁炉的总功率还大。如果把这款处理器用在你的手机上,“充电5小时,通话2分钟”,绝对不是梦想。现在处理器的发展趋势就是在提升性能的情况下,功耗越做越低,这样的产品在市场上才有竞争力。

而在相同的工艺下,提升芯片性能和减少功耗之间往往又是冲突的。以Cache为例,我们可以通过增加L1、L2、L3级Cache的容量来增加Cache的命中率,提高CPU的性能,但芯片的面积和功耗也会随之增加。流水线同样如此,我们可以通过增加流水线级数、减少每一级流水的时间延迟,来提高处理器的主频,但随之而来的就是芯片电路的复杂性增加。鱼与熊掌不可兼得,很多厂家在发布自己的处理器时,都会根据产品的市场定位在性能、成本和功耗之间反复做平衡,或者干脆发布一系列低、中、高端产品:要么追求高性能,要么追求低功耗,要么追求能效比。

单核时代的玩法玩得差不多了,就要换种新玩法,才能让消费者有欲望和动力扔掉旧机器,刷着花呗白条更新换代。于是,一个更加缤纷多彩的多核大战时代来临了。

2.6.2 片上多核互连技术

现代的计算机,无论是PC、手机还是服务器,一般都是多个任务同时运行,单核CPU的性能再强劲,其实也是在串行执行这几个任务,多个任务轮流占用CPU运行。只要任务切换得足够快,就可以以假乱真,让用户觉得多个程序在同时运行。

多核处理器则可以让多个任务真正地同时执行。在单核处理器通过指令级并行性能提升空间有限的情况下,通过多核在任务级做到真正并行,可以进一步提升CPU的整体性能。

单核处理器芯片内部除了集成CPU的各个基本电路单元,还集成了各级Cache。当在一个芯片内部集成多个核(Core)时,各个Core之间怎么连接呢?Cache是每个Core独享,还是共享?不同架构的处理器,甚至相同架构不同版本的处理器,其连接方式都不一样。

早期的计算机比较简单,CPU和内存、I/O模块直接相连,这种连接也称为星型连接。星型连接通信效率最高,但是浪费的资源也多。举一个简单的例子,如邮局,如图2-44左侧图所示。

图2-44 星型连接与总线型连接

计算机的CPU和其他模块,如果像邮局一样采用星型连接,通信效率确实高效,快递员到每家都有专门的道路,永不堵车。但星型连接成本高、可扩展性差:如果老王家的小王结婚盖了新房,则还需要专门修一条新公路,从邮局通到小王家;小李家拆迁了,乔迁新居,原来的公路就浪费了,还得继续修公路通到新家。为了解决这种缺陷,如图2-44右侧图所示,总线型连接就产生了:各家共享公路资源,邮局对他们各家进行编址管理。总线型连接可以随意增加或减少连接模块,兼容性和扩展性都大大增强。在单核处理器时代,总线型连接是最理想和最经济的,但是到了多核时代就未必如此了。

总线型连接也有缺陷,在某一个时刻只允许一对设备进行通信,如图2-45所示,当多个Core同时想占用总线与外部设备通信时,就会产生竞争,进而影响通信效率。

一个解决方法是使用线性阵列,分段使用总线,就像高速公路上的不同收费点一样,多个处理器可以分段使用总线资源进行通信,如IBM的Cell处理器。另一个解决方法是使用交叉开关(Crossbar),如图2-46左侧图所示。

图2-45 多核CPU的总线型连接

图2-46 交叉开关型连接

交叉开关像路由器一样有多个端口,多个Core可以通过交叉开关的端口互连,并行通信。相互通信的各对节点都是独立的,互不干扰。交叉开关可以提高通信效率,但其自身也会占用芯片面积,功耗很大,尤其当连接设备很多,交叉开关的端口很多时,芯片面积和功耗会急剧上升。为了缓解这一矛盾,我们可以使用层次化交叉开关(如图2-46右侧图),通过层次化交叉开关可以在局部构建一个节点的集群,然后在上一层将每个局部的集群看成一个节点,再通过合适的方式进行连接。

层次化交叉开关利用网络通信的局部特征,缓解了单个开关在连接的节点上升时产生的性能下降,在性能、芯片面积和功耗之间达到一个平衡。交叉开关两两互连,处理器的多个Core之间通过开关可以相互独立通信,效率很高(如图2-47左侧图)。但随之而来的问题是,随着连接节点增多,交叉开关的互连逻辑也越来越复杂,功耗和占用的芯片面积也越来越大,所以这种连接结构一般适用于四核以下的CPU。四核以上的CPU可以采用Ring Bus结构(如图2-47右侧图):将总线和交叉开关结合起来,连成一个环状,相邻的两个Core通信效率最高,远离的两个Core之间可以通过开关路由通信。Intel的八核处理器一般都是采用这种结构的。

Ring Bus结构结合了总线型连接和开关型连接两者的优点,在成本功耗和通信效率之间达到一个平衡,但是也有局限性,当这个环上连接的Core很多时,通信延迟又会带来效率下降。面向服务器的处理器一般都是16核以上的,这种众核结构如果再使用以上连接方式则都会有局限性,影响多核整体性能的发挥。面向众核处理器领域,目前比较流行的一种片上互连技术叫作片上网络(Net On Chip,NoC)。现在比较常用的二维Mesh网络如图2-48所示。

图2-47 交叉开关型结构与Ring Bus结构

图2-48 二维Mesh网络

当处理器的Core很多时,我们不再使用总线型连接,而是使用网络节点的方式连接。每个节点包括计算单元、通信单元及其附属电路。计算和通信实现了分离,每一个节点中的处理单元可以是一个Core,也可以是一个小规模的SoC。Core与Core之间的通信基于通信协议进行,数据包在网络中按照设定的路由算法传输,通过网络通信的分布化来避免总线的竞争。

当2D Mesh网络连接的Core很多时,距离较远的两个Core,因为经过太多的路由,通信延迟也会对处理器整体性能产生一定影响。将网络路径中每一条线的首尾路由节点相连,就变成了二维的Ring Bus结构,即Torus网络,可以进一步减少路由路径较远时带来的通信延迟。

NoC根据连接的节点类型,可分为同构和异构两种类型。同构指网络上连接的节点处理器类型都是一样的,如都是CPU的Core;而异构则指网络上可以连接不同类型的处理单元,如GPU、DSP、NPU、TPU等。随着人工智能、大数据、物联网等技术的发展,我们需要在同一个处理器中集成不同类型的运算单元,如CPU、GPU、NPU等。如何更方便地连接它们,如何让它们更高效地协同工作,如何避免“一核有难,八核围观”的尴尬局面,如何提升处理器的整体性能,成为目前NoC领域研究的热点。

2.6.3 big.LITTLE结构

多个Core集成到一个处理器上,当CPU负载很大时,多个Core一起上阵确实可以提高工作效率,但是当工作任务不是很多时,如只开一个QQ,然后八个核一起跑,只有一个Core在工作,其他Core也开始跟着空转打酱油,随之带来的就是功耗的上升。为了避免这种情况,ARM推出了big.LITTLE架构,也就是大小核架构:一个处理器内部集成的有高性能的Core,也有低功耗的Core。当CPU工作负载很重时,启动高性能的Core工作;当CPU很闲时,则切换到低功耗的Core上工作。根据不同的应用场景和工作负载,CPU分配不同的Core工作,可以在性能和功耗之间达到一个平衡。

ARM处理器针对多核采取了分层设计,如图2-49所示,将所有的高性能核放到一个簇(Cluster)里,构成一个big Cluster,将多个低功耗核放到另一个Cluster里,构成LITTLE Cluster。处理器中的每个Core都有自己独立的数据Cache和指令Cache,每个Cluster共享L2 Cache。为了保证多个Core运行时Cache和RAM中的数据相同,两个Cluster之间通过缓存一致性接口相连,不仅保证多个Core之间的高效通信,还通过检测电路,保证了多个Cache之间、Cache和RAM之间的数据一致性,避免程序运行出错。

图2-49 ARM处理器的big.LITTLE架构

操作系统运行时,可以根据CPU的负载情况灵活地在两个Cluster之间来回切换。为了更好地在性能和功耗之间达到平衡,我们甚至可以进行更精细的调度:当CPU负载较轻时,使用小核;当CPU负载一般时,大核和小核混合使用;只有当CPU负载较高时,才全部使用大核工作。随着ARM的大小核设计技术越来越成熟,在软件上的优化越来越得心应手,越来越多的厂家开始使用这项技术去设计自己的处理器,大小核设计目前已经成为ARM多核处理器的标配。

2.6.4 超线程技术

在多核处理器设计中,还有一种技术叫超线程技术(Hyper-Threading,HT),目前主要应用在Intel、AMD的X86多核处理器上。大家买计算机时,经常会看到4核8线程、6核12线程的说明,带有这些字眼的处理器一般都采用了超线程技术。

什么是超线程技术呢?网上有个例子讲得很形象,这里就拿来跟大家分享一下:假如你是一个餐馆的老板,雇了一个厨师烧菜,顾客点了两道菜:老鸭汤和宫保鸡丁。厨师接单后,开始做起来。如图2-50所示,老鸭汤从备菜到出锅需要14min,宫保鸡丁从备菜到出锅需要10min,两道菜总共需要24min。

图2-50 厨师的做菜流水线

为了提高上菜速度,老板有两个方法:一是再雇一个厨师,每个厨师同时各做一道菜;二是在厨房里再增加一个灶台,让厨师分别在两个灶台上同时做这两道菜。只要老板智商没问题,肯定会选第二种,因为老板发现厨师在煲汤的十分钟里一直闲着没事干,顾客早就等得不耐烦了,厨师却在那里刷抖音。再雇一个厨师的成本太高,如图2-51所示,再添一个灶台,就可以让厨师一直忙,既节省了人力成本,又可以将做两道菜的时间缩减到14min。

图2-51 改进后的流水线

如果把厨师看作CPU,则选择第一种方案就是双核处理器,选择第二种方案是单核双线程处理器。超线程技术通过增加一定的控制逻辑电路,使用特殊指令可以将一个物理处理器当两个逻辑处理器使用,每个逻辑处理器都可以分配一个线程运行,从而最大限度地提升CPU的资源利用率。超线程技术在CPU内部的实现原理也很简单,我们以学校旁边打印店里的打印机为例,如图2-52所示。

当打印店的生意很火爆时,老板一般会多购买几台打印设备(计算机+打印机)。如果每台计算机配一台打印机,成本会很高,而且打印机也不是一直在用,大部分时间都在闲着,因为大部分时间都花费在文档的输入、修改和设计上了。为了充分利用打印机资源,节省成本,老板可以只买一台打印机,然后将两台计算机通过虚拟打印机设置都连接到这台打印机上。如果把打印机看作CPU的Core,那么这种共享打印机的设置其实就是超线程技术。

图2-52 打印机的超线程技术

超线程技术的实现原理和打印机类似:如图2-53所示,在CPU内部很多资源其实也是可以共享的,如ALU、FPU、Cache、总线等,也有很多资源是每个线程独有的,如寄存器状态、堆栈等。我们通过增加一些控制逻辑电路,保存各个线程的状态,共享ALU、Cache等共享资源,就可以在一个物理Core上实现两个逻辑Core,操作系统可以给每个逻辑Core都分配1个线程运行。

图2-53 CPU的超线程技术

这里需要注意的是,在同一个物理Core上的两个线程并不是同时运行的,因为每个线程都需要使用物理Core上的共享资源(如ALU、Cache等)。但是两个线程之间可以互相协助运行,一般处理器上的两个线程上下文切换需要20 000个时钟周期,而超线程处理器上的两个线程切换只需要一个时钟周期就可以了,上下文切换的时间开销大大减少。超线程技术其实就是“欺骗”操作系统,让操作系统认为它有更多的Core,给它分配更多的任务执行,通过减少CPU的空闲时间来提高CPU的利用率。因为线程在两个逻辑处理器上并不是真正的并行,所以也不可能带来2倍的性能提升,但是通过增加5%左右的芯片面积换来CPU 15%~30%的性能提升,还是很划算的。

超线程技术的使用也离不开硬件和软件层面的支持。首先主板和BIOS要支持超线程技术,操作系统也需要对超线程技术有专门的优化。Windows操作系统从Windows XP以后开始支持超线程技术,GNU/Linux操作系统则从Linux-2.6以后开始支持超线程技术。除此之外,应用层面也需要支持超线程技术,如NPTL库等。

并不是所有的场合都适合使用超线程技术,你可以根据自己的实际需求选择开启或关闭超线程。在高并发的服务器场合下,使用超线程技术确实可以提升性能,但在一些对单核性能要求比较高的场合,如大型游戏,开启超线程反而会增加系统开销,影响性能。在Intel和AMD的处理器产品系列中,你会发现并不是所有的处理器都使用了超线程技术,甚至某代处理器全部放弃使用,而最新的Intel 10代处理器则又卷土重来,全面开启超线程。截至目前,市面上还没有发现使用超线程技术的ARM处理器。

2.6.5 CPU核数越多越好吗

在多核处理器时代,如何打造一款爆款CPU芯片,在市场上大卖?

工厂一定得选最好的黄金地段,雇法国的设计师,建就得建最高档次的厂房!

电梯直接入户,户型最小也得四万平方米,什么宽带啊、光缆啊、卫星啊,能安的都安上。

楼下建一个商场,楼里建一个咖啡馆,厂门口站一个英国保安,戴假发、穿皮靴、特绅士的那种。

工人一进门儿,甭管有事没事,都得跟人家说:Happy 996,Sir!一口地道的伦敦腔,倍儿有面子!

再建一个单晶硅生产车间,沙子要用澳洲黄金海岸的,光刻机要用ASML的。

Cache要上GB级别,CPU流水线要30级起步,什么分支预测、乱序执行、超线程、SIMD、多发射,能用的全给它用上。

CPU要64核起,什么GPU、TPU、NPU、DPU啊,可劲儿往里堆。

别管有用没用,就是一个字儿:贵,流一次片就得先花一个亿。

周围的同事不是耶鲁的就是哈佛的,你要是211毕业的,都不好意思和人家打招呼。

你说这样的配置,造出来的CPU得多少钱?

至少也得两千美元吧!

两千美元?两千美元那是成本,四千美元起,你别嫌贵,还不打折。

你得研究玩家的购物心理,愿意掏两千美元攒机的家伙,根本不在乎再多掏两千。

知道什么是发烧友吗?发烧友就是买什么东西,只买贵的,不买对的!

所以,我们生产CPU的口号就是:不求最好,但求最贵!

相关研究表明,单核处理器主频每升1GHz,平均就要增加25W的功率。通过增加处理器核数,将大量繁重的计算任务分配到更多的Core上,可以提高处理器的整体性能。而根据阿姆达尔定律,程序中并行代码的比例又决定了增加处理器核数所能带来的性能提升上限,CPU的核数不一定越多越好,任务分配不当就可能造成“一核有难,八核围观”的尴尬场面。消费者在配置计算机时,建议根据自己的实际需求来选择性价比最高的处理器。

大型游戏一般侧重单核性能,主频越高,游戏体验越佳;而服务器则更倾向于多核多线程。例如你要玩《绝地求生》游戏,6核12线程的E5 2689不一定比得上双核四线程的奔腾G5400。目前大部分游戏优化满载时能跑到四核就已经不错了,如果你在玩游戏时还运行其他软件,六核已经足够,八核就算高端配置了。当然,如果你是发烧友玩家或者土豪,一直在追求极致的体验,上面所说的一切无效,挑最贵的下单,保证没错。

如果你想犁一块地,你会选择哪种方式?两头健壮的小公牛,还是1024只小鸡?

——超级计算机之父,Seymour Cray

如果想继续提升极致的游戏体验,在多核提升性能有限的情况下,就要从内存、显卡、计算机周边配件着手了。此时已经到了后摩尔时代,异构计算已经悄然崛起。