使用SIMD技术提高C++程序性能(上)

作者:张银奎 来源:程序员杂志

有人说这两年Java语言很火,Java程序员的工资不断上升,已超过了C++程序员,但我觉得这只是通过模糊比较得出的模糊结论。程序员之间的差异太大了,Java程序员可以分为很多等,C++程序员也有很多等,拿前者的高等与后者的低等比当然前者高。无论如何,我还是喜欢听到圈里圈外的人谈论程序员或者软件,这说明软件在越来越深地走进公众视野。

今天和C++同行谈谈如何提高自己的身价。编程语言只是工具,要把工具用到最合适的地方,扬其长且避其短,打造出有价值的软件产品,那么使用这工具的人自然身价就高了。

C++语言的优势

C++语言有哪些优势呢?当然有很多,不然早消亡了。但泛泛地说“有很多”没意义。到底有哪些呢?不同人可能有不同的回答。同一个人在不同时间也可能回答不同。这里我们不妨听听C++之父Bjarne Stroustrup先生如何说。

在前不久举办的“2016 C++及系统软件技术大会”上,Bjarne先生做了题为《What C++ is and what it will become》的主题演讲。Bjarne先生很深刻地阐释了到底什么是C++,解说了C++语言的根本特征和优势。有一页讲稿的题目叫“C++ in two lines”(用两行话来描述C++),可谓画龙点睛之笔。这两行是什么呢?第一行是“Direct map to hardware”,第二行是“Zero overhead abstraction”。粗浅的翻译一下,那么就是“直接映射到硬件”和“0负担抽象”。

“直接映射到硬件”是说C++语言和硬件之间直接对应,C++的语句可以直接对应到CPU的指令,C++的数据类型也可以直接对应到CPU支持的数据类型。也就是说,C++语言的代码和数据可以很直接地翻译到CPU支持的指令和数据,不需要做这样那样的转换。概言之,就是效率很高。

单纯从效率来讲,最直接的语言当然要属汇编语言,但汇编语言的问题是缺乏高级抽象,代码难以组织。所以Bjarne先生的第二行是“0负担抽象”,我想这一行又包含两层意思,第一层意思是C++是有抽象的,第二层意思是支持抽象的负担为0。在今天的软件大生产时代,即使是比较小型的软件项目,使用抽象也是必须的。

今天流行的编程语言几乎无不支持抽象,不论Java还是C#、F#。虽然都支持抽象,但有些语言为了抽象付出的代价很大,资源消耗多,运行速度慢,也就是额外开销高。而C++是0负担抽象,0额外开销。Bjarne先生一定也知道Java的流行,一定也听见过关于C++和Java孰是孰非的争论。说C++是0额外开销略微有些夸张,但相对其他额外开销高的语言来说,相当于是0了。不这样说的话,说抽象负担远远低于其他语言,岂不啰嗦?一代宗师此言一出,言简意赅,料也无人敢出来说半个不是。

这两行话简单有力,一个是效率高,一个是负担小,加起来一起托出C++的核心优势:锐利无比,性能一流。

使用SIMD技术提高C++程序性能(上)_第1张图片
图1 C++之父Bjarne先生在介绍C++的根本优势

怀着虔诚的心,我一边聆听Bjarne先生论述上面两行话,一边用手机拍下了这个历史瞬间。地点是上海浦东外高桥的喜来登酒店。时间是2016年10月28日上午10点12分左右。

大师的话值得反复体味,每个C++程序员都应该牢记。在做设计时,我们应该用这两句话来检查自己的设计,是否大道至简,能否发挥硬件的性能。编写和检查代码时,我们更应该想起这两句话,把杂乱的逻辑理顺,把冗余的代码删掉,反复优化每行代码,把硬件的性能发挥到极致。不然的话,怎么对得起C++语言,怎么对得起Bjarne先生?

有人说,硬件太强大了,写代码时不需要那么在意性能问题。这话真是放屁。每一位有责任心的C++程序员都应该站出来痛斥这样的言论。

在Bjarne先生介绍C++的未来发展时,他谈到了最希望加入到C++17中的语言特征。在这个包含十项内容的列表中,第8项是SIMD向量和并行化算法。刚好与我为准备的讲题不谋而合。

使用SIMD技术提高C++程序性能(上)_第2张图片
图2 C++之父Bjarne先生希望加入到C++17中的语言特征

SIMD简史

SIMD是Single Instruction,Multiple Data的缩写——意为单指令多数据。我是在Intel工作期间听说这个技术的,好多年前了,什么场合已经记不清,但仍记得当时眼前一亮,仿佛看到一束霞光照进脑洞,心中赞叹这种做法太美妙了。SIMD思想的最大特色和魅力是简单自然——人法地,地法天,天法道,道法自然。为什么如此说呢?因为SIMD思想的应用实例在我们的生活中随处可见,其出现年代或许可以追溯到原始社会。

我喜欢吃面包,因此以面包作坊为例。假设某面包作坊要做1000个面包,每个面包要经过成型、入炉、烘烤、取出等步骤。如果每次只操作一个面包,那么大多数基本动作都要重复1000次。但如果使用一个图3所示的简单模具,上面有四个“包厢(面包之厢,姑且称此名)”,那么便可以一次操作四个面包。这样一来,很多操作便都是成批的了,一次成型四个,向烤箱里放时,一次四个,拿出来时,又是一次四个,于是很多操作的重复次数便从1000次下降到了250,生产效率大大提高。


使用SIMD技术提高C++程序性能(上)_第3张图片
图3 SIMD思想源于生活

走进生活,其实有很多类似例子,小时候看过用黄泥做土坯的劳动场面,一个称为坯模子的木框,上面有多个格子,每个格子对应一块土坯。如果到工厂里看一下,那么就更多了。很多工序都在使用SIMD思想,成批地生产。劳动激发智慧,软件同行们应该好好向现实社会学习。

SIMD在计算机领域应用也有很多年了,目前比较普遍地认为著名的ILLIAC IV大型机是SIMD思想的在现代计算机中的最早实现。ILLIAC IV由美国Illinois大学设计,宝来公司(Burroughs)建造,项目从1965年开始,经历六年时间耗资四千万美元完成,安装在美国国家航空航天局(NASA),服役多年,直到1981年才停机退役。

源于ILLIAC IV使用手册的图4既描述了ILLIAC IV的核心部件,又阐释了它的工作原理。图中的PE是Processor Element的缩写,即处理器单元,其功能和命名都与我们今天所说的Execution Unit(EU)(GPU内的基本执行单元)非常类似。PEM是Processing Element Memory,即处理单元记忆体,用来存放要计算的数据和计算结果。

ILLIAC IV有64个PE(处理器单元),可以同时做64个计算。图中演示的便是把数组B和数组C相加,结果放到数组A,一次便完成64个元素。


使用SIMD技术提高C++程序性能(上)_第4张图片
图4 ILLIAC IV工作原理

在ILLIAC IV手册里,还可以看到一些有趣的插图,比如图5这幅卡通画非常形象地描绘了ILLIAC IV可以成批处理数据的能力,工作人员用大叉子把文件一大摞一大摞地投给ILLIAC IV的大嘴。ILLIAC IV的众多计算单元排成一行在等待“喂食”。


使用SIMD技术提高C++程序性能(上)_第5张图片
图5 描述ILLIAC IV强大并行处理能力的卡通画

IA CPU上SIMD实现

刚才介绍了SIMD的思想以及最早的实现,接下来先总览Intel架构(简称IA)上的SIMD实现,然后再给出实例。

很多人不知道SIMD是什么,但知道MMX。MMX是MultiMedia

eXtensions的缩写,意思是多媒体扩展。1997年推出的基于P5架构的奔腾处理器是包含MMX技术的第一款IA CPU。从硬件角度来看,MMX技术包含8个64位的寄存器,称为MM0-MM7,可以对8个单字节整数,或者4个字,或者2个双字做各种组合操作。MMX仅支持整数类型,不支持浮点数。

1999年随同奔腾II处理器推出的SSE(Streaming

SIMD Extensions)技术弥补了MMX不支持浮点数的不足,并对MMX做了很多改进,包括把寄存器的宽度扩展为128位,并且不再复用x87寄存器,并引入了70条新的指令。

2008年公布的AVX(Advanced Vector Extensions)进一步把寄存器的宽度扩展为256位,并且革新了指令格式,支持三目运算符。2011年发布的Sandy Bridge处理器包含了AVX技术。


使用SIMD技术提高C++程序性能(上)_第6张图片
图6 IA CPU上的SIMD实现

“天河二号”是由国防科学技术大学研制的超级计算机系统,峰值计算速度可以达到每秒5.49亿亿次、持续计算速度每秒3.39亿亿次。在2014年11月17日公布的全球超级计算机500强榜单中,“天河二号”名列冠军。天河二号是个庞大的系统,由数以万计的计算节点组成,据说每个节点包含两颗Xeon处理器和三块Xeon Phi协处理计算卡。Xeon Phi具有强大的并行计算能力,其核心技术便是名为AVX-512的SIMD技术。AVX-512是对AVX的再扩展,寄存器的宽度扩展为512位,数量也加大一倍,从16个提高到32个。

至此我们已经介绍了SIMD的思想、历史以及在X86架构CPU的实现,接下来将通过一个具体的图像处理实例来介绍如何把SIMD技术应用到C++项目里,探讨难易不同的多种方案、以及如何衡量所取得的性能提升。但因篇幅所限,我们将在下一期详细分解。

想跟张银奎老师学习软件开发技能,强化解决复杂问题的能力?

好消息,张老师三年后又一次开班了,欢迎报名“软件调试高级研习班2016-庐山秀峰站”。

中国软件开发调试第一人张银奎老师亲授,三天两晚闭门修炼,秉烛夜谈。

教你写高质量代码,软件开发能力进阶,强化复杂问题处理技能。

报名:http://event.3188.la/527839310

或加微信群咨询

你可能感兴趣的:(使用SIMD技术提高C++程序性能(上))