多核编程的几个难题及其应对策略

发布者:陈书记最新更新时间:2014-09-02 来源: eefocus关键字:串行化  CPU  多核 手机看文章 扫描二维码
随时随地手机看文章
      随着多核CPU的出世,多核编程方面的问题将摆上了程序员的日程,有许多老的程序员以为早就有多CPU的机器,业界在多CPU机器上的编程已经积累了很多经验,多核CPU上的编程应该差不多,只要借鉴以前的多任务编程、并行编程和并行算法方面的经验就足够了。

        我想说的是,多核机器和以前的多CPU机器有很大的不同,以前的多CPU机器都是用在特定领域,比如服务器,或者一些可以进行大型并行计算的领域,这些领域很容易发挥出多CPU的优势,而现在多核机器则是应用到普通用户的各个层面,特别是客户端机器要使用多核CPU,而很多客户端软件要想发挥出多核的并行优势恐怕没有服务器和可以进行大型并行计算的特定领域简单。

串行化方面的难题

1)加速系数

衡量多处理器系统的性能时,通常要用到的一个指标叫做加速系数,定义如下:
S(p) = 使用单处理器执行时间(最好的顺序算法)/ 使用具有p个处理器所需执行时间

2)阿姆尔达定律

并行处理时有一个阿姆尔达定律,用方程式表示如下:
S(p) = p / (1 + (p-1)*f)
其中 S(p)表示加速系数
p表示处理器的个数
f表示串行部分所占整个程序执行时间的比例
当f = 5%, p = 20时, S(p) = 10.256左右
当f = 5%, p = 100时, S(p) = 16.8左右

        也就是说只要有5%的串行部分,当处理器个数从20个增加到100个时,加速系数只能从10.256增加到16.8左右,处理器个数增加了5倍,速度只增加了60%多一点。即使处理器个数增加到无穷多个,加速系数的极限值也只有20。
 
        如果按照阿姆尔达定律的话,可以说多核方面几乎没有任何发展前景,即使软件中只有1%的不可并行化部分,那么最大加速系统也只能到达100,再多的CPU也无法提升速度性能。按照这个定律,可以说多核CPU的发展让摩尔定律延续不了多少年就会到达极限。

3)Gustafson定律

        Gustafson提出了和阿姆尔达定律不同的假设来证明加速系数是可以超越阿姆尔达定律的限制的,Gustafson认为软件中的串行部分是固定的,不会随规模的增大而增大,并假设并行处理部分的执行时间是固定的(服务器软件可能就是这样)。Gustafson定律用公式描述如下:

S(p) = p + (1-p)*fts
其中fts表示串行执行所占的比例
如果串行比例为5%,处理器个数为20个,那么加速系数为20+(1-20)*5%=19.05
如果串行比例为5%,处理器个数为100个,那么加速系数为100+(1-100)*5%=95.05

        Gustafson定律中的加速系数几乎跟处理器个数成正比,如果现实情况符合Gustafson定律的假设前提的话,那么软件的性能将可以随着处理个数的增加而增加。

4)实际情况中的串行化分析

        阿姆尔达定律和Gustafson定律的计算结果差距如此之大,那么现实情况到底是符合那一个定律呢?我个人认为现实情况中既不会象阿姆尔达定律那么悲观,但也不会象Gustafson定律那么乐观。为什么这样说呢?还是进行一下简单的分析吧。
首先需要确定软件中到底有那么内容不能并行化,才能估计出串行部分所占的比例,20世纪60年代时,Bernstein就给出了不能进行并行计算的三个条件:

条件1:C1写某一存储单元后,C2读该单元的数据。称为“写后读”竞争
条件2:C1读某一存储单元数据后,C2写该单元。称为“读后写”竞争
条件1:C1写某一存储单元后,C2写该单元。称为“写后写”竞争

        满足以上三个条件中的任何一个都不能进行并行执行。不幸的是在实际的软件中大量存在满足上述情况的现象,也就是我们常说的共享数据要加锁保护的问题。

        加锁保护导致的串行化问题如果在任务数量固定的前提下,串行化所占的比例是随软件规模的增大而减小的,但不幸的是它会随任务数量的增加而增加,也就是说处理器个数越多,锁竞争导致的串行化将越严重,从而使得串行化所占的比例随处理器个数的增加而急剧增加。(关于锁竞争导致的串行化加剧情况我会在另一篇文章中讲解)。所以串行化问题是多核编程面临的一大难题。

5)可能的解决措施

        对于串行化方面的难题,首先想到的解决措施就是少用锁,甚至采用无锁编程,不过这对普通程序员来说几乎是难以完成的工作,因为无锁编程方面的算法太过于复杂,而且使用不当很容易出错,许多已经发表到专业期刊上的无锁算法后来又被证明是错的,可以想象得到这里面的难度有多大。

        第二个解决方案就是使用原子操作来替代锁,使用原子操作本质上并没有解决串行化问题,只不过是让串行化的速度大大提升,从而使得串行化所占执行时间比例大大下降。不过目前芯片厂商提供的原子操作很有限,只能在少数地方起作用,芯片厂商在这方面可能还需要继续努力,提供更多功能稍微强大一些的原子操作来避免更多的地方的锁的使用。

        第三个解决方案是从设计和算法层面来缩小串行化所占的比例。也许需要发现实用的并行方面的设计模式来缩减锁的使用,目前业界在这方面已经积累了一定的经验,如任务分解模式,数据分解模式,数据共享模式,相信随着多核CPU的大规模使用将来会有更多的新的有效的并行设计模式和算法冒出来。

        第四个解决方案是从芯片设计方面来考虑的,由于我对芯片设计方面一无所知,所以这个解决方案也许只是我的一厢情愿的猜想。主要的想法是在芯片层面设计一些新的指令,这些指令不象以前单核CPU指令那样是由单个CPU完成的,而是由多个CPU进行并行处理完成的一些并行指令,这样程序员调用这些并行处理指令编程就象编写串行化程序一样,但又充分利用上了多个CPU的优势。

负载平衡问题

多核编程中的锁竞争难题 这篇文章中讲过一个多核编程中的串行化的难题,这篇文章中再来讲解一下多核编程中的另外一个难题,就是负载平衡方面的难题。

        多核CPU中,要很好地发挥出多个CPU的性能的话,必须保证分配到各个CPU上的任务有一个很好的负载平衡。否则一些CPU在运行,另外一些CPU处于空闲,无法发挥出多核CPU的优势来。

        要实现一个好的负载平衡通常有两种方案,一种是静态负载平衡,另外一种是动态负载平衡。

1、静态负载平衡

        静态负载平衡中,需要人工将程序分割成多个可并行执行的部分,并且要保证分割成的各个部分能够均衡地分布到各个CPU上运行,也就是说工作量要在多个任务间进行均匀的分配,使得达到高的加速系数。

        静态负载平衡问题从数学上来说是一个NP完全性问题,Richard M. Karp, Jeffrey D. Ullman, Christos H. Papadimitriou, M. Garey, D. Johnson等人相继在1972年到1983年间证明了静态负载问题在几种不同约束条件下的NP完全性。

        虽然NP完全性问题在数学上是难题,但是这并不是标题中所说的难题,因为NP完全性问题一般都可以找到很有效的近似算法来解决。      

2、动态负载平衡

        动态负载平衡是在程序的运行过程中来进行任务的分配达到负载平衡的目的。实际情况中存在许多不能由静态负载平衡解决的问题,比如一个大的循环中,循环的次数是由外部输入的,事先并不知道循环的次数,此时采用静态负载平衡划分策略就很难实现负载平衡。

        动态负载平衡中对任务的调度一般是由系统来实现的,程序员通常只能选择动态平衡的调度策略,不能修改调度策略,由于实际任务中存在很多的不确定因素,调度算法无法做得很优,因此动态负载平衡有时可能达不到既定的负载平衡要求。[page]

3、负载平衡的难题在那里?

        负载平衡的难题并不在于负载平衡的程度要达到多少,因为即使在各个CPU上分配的任务执行时间存在一些差距,但是随着CPU核数的增多总能让总的执行时间下降,从而使加速系数随CPU核数的增加而增加。

        负载平衡的困难之处在于程序中的可并行执行块很多要靠程序员来划分,当然CPU核数较少时,比如双核或4核,这种划分并不是很困难。但随着核数的增加,划分的粒度将变得越来越细,到了16核以上时,估计程序员要为如何划分任务而抓狂。比如一段顺序执行的代码,放到128核的CPU上运行,要手工划分成128个任务,其划分的难度可想而知。

        负载划分的误差会随着CPU核数的增加而放大,比如一个需要16个时间单位的程序分到4个任务上执行,平均每个任务上的负载执行时间为4个时间单位,划分误差为1个时间单位的话,那么加速系数变成 16/(4+1)=3.2,是理想情况下加速系数 4的80%。但是如果放到一个16核CPU上运行的话,如果某个任务的划分误差如果为0.5个时间单位的话,那么加速系数变成16/(1+0.5) = 10.67,只有理想的加速系数16的66.7%,如果核数再增加的话,由于误差的放大,加速系数相比于理想加速系数的比例还会下降。

        负载划分的难题还体现在CPU和软件的升级上,比如在4核CPU上的负载划分是均衡的,但到了8核、16核上,负载也许又变得不均衡了。软件升级也一样,当软件增加功能后,负载平衡又会遭到破坏,又需要重新划分负载使其达到平衡,这样一来软件设计的难度和麻烦大大增加了。

        如果使用了锁的话,一些看起来是均衡的负载也可能会由于锁竞争变得不平衡起来,详细情况请看:http://blog.csdn.net/drzhouweiming/archive/2007/04/10/1559718.aspx

4、负载平衡的应对策略

        对于运算量较小的软件,即使放到单核CPU上运行速度也很快,负载平衡做得差一些并没有太大影响,实际中负载平衡要考虑的是大运算量和规模很大的软件,这些软件需要在多核上进行负载平衡才能较好地利用多核来提高性能。

        对于大规模的软件,负载平衡方面采取的应对策略是发展划分并行块的宏观划分方法,从整个软件系统层面来进行划分,而不是象传统的针对某些局部的程序和算法来进行并行分解,因为局部的程序通常都很难分解成几十个以上的任务来运行。

        另外一个应对策略是在工具层面的,也就是编译工具能够协助人工进行并行块的分解,并找出良好的分解方案来,这方面Intel已经作出了一些努力,但是还需要更多的努力让工具的功能更强大一些才能应对核数较多时的情况。

多核编程中的锁竞争问题

       在前一篇讲解多核编程的几个难题及其对策(难题一)的文章中提到了锁竞争会让串行化随CPU的核数增多而加剧的现象,这篇文章就来对多核编程的锁竞争进行深入的分析。

       为了简化起见,我们先看一个简单的情况,假设有4个对等的任务同时启动运行,假设每个任务刚开始时有一个需要锁保护的操作,耗时为1,每个任务其他部分的耗时为25。这几个任务启动运行后的运行情况如下图所示:

图1:对等任务的锁竞争示意图


        在上图中,可以看出第1个任务直接执行到结束,中间没有等待,第2个任务等待了1个时间单位,第3个任务等待了2个时间单位,第3个任务等待了3个时间单位。

        这样有3个CPU总计等待了6个时间单位,如果这几个任务是采用OpenMP里的所有任务都在同一点上进行等待到全部任务执行完再向下执行时,那么总的运行时间将和第四个任务一样为29个时间单位,加速系数为:(1+4×25)/ 29 = 3.48即使以4个任务的平均时间27.5来进行计算,加速系数=101/27.5 = 3.67,按照阿姆尔达定律来计算加速系数的话,上述应用中,串行时间为1,并行处理的总时间转化为串行后为100个时间单位,如果放在4核CPU上运行的话,加速系数=p / (1 + (p-1)*f) = 4/(1+(4-1)*1/101) = 404/104 = 3.88。

        这就产生了一个奇怪的问题,使用了锁之后,加速系数连阿姆尔达定律计算出来的加速系数都不如,更别说用Gustafson定律计算的加速系数了。
 
        其实可以将上面4个任务的锁竞争情况推广到更一般的情况,假设有锁保护的串行化时间为1,可并行化部分在单核CPU上的运行时间为t,CPU核数为p,那么在p个对成任务同时运行情况下,锁竞争导致的总等待时间为:1+2+…+p = p*(p-1)/2
耗时最多的一个任务所用时间为: p + t/p

使用耗时最多的一个任务所用时间来当作并行运行时间的话,加速系数如下

S(p) = (t+1) / (p + t/p) = p*(t+1) / (p*p+t)       (锁竞争下的加速系数公式)

        这个公式表明在有锁竞争情况下,如果核数固定情况下,可并行化部分越大,那么加速系数将越大。在并行化时间固定的情况下,如果CPU核数越多,那么加速系数将越小。

还是计算几个实际的例子来说明上面公式的效果:
令t=100, p=4, 加速系数=4×(100 +1)/ (4*4+100) = 3.48
令t=100, p=16, 加速系数=16×(100+1) / (16*16+100) = 4.54
令t=100, p=64, 加速系数=64×(100+1) / (64*64+100) = 1.54
令t=100, p=128, 加速系数=128×(100+1) / (128*128+100) = 0.78

        从以上计算可以看出,当核数多到一定的时候,加速系数不仅不增加反而下降,核数增加到128时,加速系数只有0.78,还不如在单核CPU上运行的速度。

        上面的例子中,锁保护导致的串行代码是在任务启动时调用的,其实对等任务中在其他地方调用的锁保护的串行代码也是一样的。

        对等型任务的锁竞争现象在实际情况中是很常见的,比如服务器软件,通常各个客户端处理任务都是对等的,如果在里面使用了锁的话,那么很容易造成上面说的加速系数随CPU核数增多而下降的现象。

        以前的服务器软件一般运行在双CPU或四CPU机器上,所以锁竞争导致的加速系数下降现象不明显,进入多核时代后,随着CPU核数的增多,这个问题将变得很严重,所以多核时代对程序设计提出了新的挑战。以前的多任务下的编程思想放到多核编程上不一定行得通。

        所以简单地认为多核编程和以前的多任务编程或并行计算等同的话是不切实际的,在讲串行化难题的那篇文章中提出了一些解决方面的对策,但是那些对策还有待业界继续努力才能做得到。

        当然由于目前市面上销售的多核CPU还是双核和四核的,等到16核以上的CPU大规模进入市场可能还有几年时间,相信业界在未来的几年内能够对于上面对等任务上的锁竞争问题找到更好的解决方案。

关键字:串行化  CPU  多核 引用地址:多核编程的几个难题及其应对策略

上一篇:为嵌入式处理设计选择合适的开发工具
下一篇:Linux2.6内核中的最新电源管理技术综述

推荐阅读最新更新时间:2024-03-16 13:41

高通:多核心并非绝对 单核心效能才是重点
     针对近期正式揭晓采用旗下首款64位元自主架构处理器Snapdragon 820,Qualcomm表示目前多核心设计仅落于行销术语,更重要的应该是在处理器核心本身效能设计,同时强调未来处理器产品将维持少量核心数量设计原则,并不会一昧追求多核心设计模式,似乎再次针对联发科多核心设计与多丛集 (Cluster)运作模式呛声。 相较去年推出的Snapdragon 810处理器直接取用ARM big.LITTLE架构设计,分别以Cortex-A57、Cortex-A53架构构成“4+4”核心处理器,Qualcomm在今年推出的Snapdragon 820恢复采用自主架构设计,藉由旗下首款64位元架构“Kryo”核心构成
[手机便携]
Intel重申4年搞定5代CPU工艺“1.8nm”芯片即将流片
影响了半导体行业50多年发展的黄金定律摩尔定律近年来被各种质疑,NVIDIA尤其喜欢强调摩尔定律已死,不过Intel是摩尔定律的铁杆捍卫者,在今天凌晨开始的创新大会上,CEO基辛格强调摩尔定律不会死,还会活得很好,他们将在4年内搞定5代CPU工艺。 这五代工艺分别是Intel 7、Intel 4、Intel 3、Intel 20A及Intel 18A,其中Intel 7就是去年底12代酷睿上首发的工艺,13代酷睿也会继续用,明年则会升级Intel 4,首次支持EUV光刻工艺。 不过Intel真正在工艺上再次领先的是20A及18A两代工艺,从20A开始进入埃米级节点,放弃FinFET晶体管,改用GAA晶体管,相当于友商的2n
[半导体设计/制造]
Intel重申4年搞定5代<font color='red'>CPU</font>工艺“1.8nm”芯片即将流片
关于TI设计工业机器人技术实现 CPU 板的不同子系统的解决方案
() 的工业机器人 板参考设计展示了在设计工业机器人时实现 CPU 板的不同子系统的解决方案。 基于具有卓越处理性能的 SitaraTM 处理器的设计是可用的 Sitara 处理器可以运行多种工业协议(例如 PROFINET、POWERLINK、EtherCAT、SERCOS、/IP)或专用通信协议。此外,还展示了多种其他处理器和 的设计 如果需要无线连接,TI 提供使用其广泛无线产品组合的设计 而且还展示了电源、备用电源和保护的参考设计,以解决有关 CPU 板模拟部件的问题
[机器人]
人工智能风口下的TPU/NPU/CPU/GPU
  人工智能将推动新一轮计算革命,深度学习需要海量数据并行运算,传统计算架构无法支撑深度学习的大规模并行计算需求。因此,深度学习需要更适应此类算法的新的底层硬件来加速计算过程。   芯片也为响应人工智能和深度学习的需要,在速度和低能耗方面被提出了更高的要求,目前使用的 GPU、FPGA 均非人工智能定制芯片,天然存在局限性,除具有最明显的优势GPU外,也有不少典型人工智能专用芯片出现。   一、谷歌——TPU(Tensor Processing Unit)即谷歌的张量处理器   TPU是一款为机器学习而定制的芯片,经过了专门深度机器学习方面的训练,它有更高效能(每瓦计算能力)。大致上,相对于现在的处理器有7年的领先优势
[嵌入式]
人工智能风口下的TPU/NPU/<font color='red'>CPU</font>/GPU
CPU制造全过程,你知道吗
 CPU(Centralprocessingunit)是现代计算机的核心部件,又称为“微处理器”。对于PC而言,CPU的规格与频率常常被用来作为衡量一台电脑性能强弱重要指标。Intelx86架构已经经历了二十多个年头,而x86架构的CPU对我们大多数人的工作、生活影响颇为深远。 CPU 它是计算机的核心部件,计算机进行信息处理可分为两个步骤: 将数据和程序(即指令序列)输入到计算机的存储器中。从第一条指令的地址起开始执行该程序,得到所需结果,结束运行。CPU的作用是协调并控制计算机的各个部件执行程序的指令序列,使其有条不紊地进行。因此它必须具有以下基本功能: a)取指令:当程序已在存储器中时,首先根据程序入口地址取出一条程序,为此
[嵌入式]
单芯片DC/DC变换器在CPU电源控制系统中
1 引言   CPU 的性能逐年提高,功耗也有增无减。一旦功耗略有减少,CPU的工作电压就趋于下降。现在,CPU的工作电压已经从当初的3.3V降低到1.6V、 0.9V,还可能进一步降低。CPU工作电压的降低,使其与外围电路的工作电压的失配更加明显,因而也增加了CPU工作电压的类别。例如在PⅢ-CPU 中,必须有3种不同的工作电压,需要3个DC-DC变换器,有碍于CPU乃至计算机总体尺寸的进一步缩小和总功耗的进一步降低。日本富士通公司生产的 MB3884型单芯片电源控制集成电路即DC-DC变换器可以满足CPU的不同工作电压和功耗的要求。本文扼要介绍这种电路的结构和特征,以便电脑用户使用。 2 笔记本电脑的电源系统
[电源管理]
单芯片DC/DC变换器在<font color='red'>CPU</font>电源控制系统中
CPU/显卡品牌偏好调查显示AMD超过60% 未来比例或继续上升
欧洲硬件协会最近发布了一项针对 CPU /显卡品牌偏好的硬件调查结果,显示有超过60%的被调查者首选 AMD 的CPU,而在去年,这个数字还是40%。 该调查每半年进行一次,调查数据还是具有相当的现实意义的,从下面的统计图中可以看到,在今年下半年的调查结果中,将AMD的CPU作为自己首选的被调查者占比已经超过了60%,而在去年上半年的时候,这个数字也就刚过40%而已,甚至比2017上半年还要低一些。 Zen+架构处理器的降价和今年Zen 2处理器的优秀表现应该是推动用户选择AMD CPU的主要因素,尤其是后者,它的游戏表现已经非常不错了,同时它能够在多线程负载下面提供更好的性能表现。AMD CPU的表现确确实实的征服了更多的
[半导体设计/制造]
<font color='red'>CPU</font>/显卡品牌偏好调查显示AMD超过60% 未来比例或继续上升
三星宣布与 Arm 合作,以 GAA 代工技术优化下一代 Cortex-X CPU 内核
2 月 20 日消息,三星电子旗下芯片代工部门宣布与 Arm 合作,共同开发、优化下一代 Cortex-X 核心。据介绍,此次合作涉及通过使用 Arm 最新 Cortex-X 设计和三星 GAA 工艺,旨在提升 CPU 性能和能效表现。 也就是说,Arm 下一代 Cortex-X 系列 CPU 架构将针对三星电子的 Gate-All-Around(GAA)芯片制造技术进行优化,这意味着基于下一代 Cortex-X 系列架构的 CPU 在使用三星 2nm 和 3nm GAA 工艺制造时可获得进一步优化,从而提供更高的性能和更低的功耗。 IT之家查询相关资料获悉,GAA 是目前业界公认的下一代技术,相比 FinFET 进一步改进了半导
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved