从编译到执行,C++如何开发SIMD友好的代码?

一:名词解释


Flynn分类法

Flynn于1972年提出了计算平台的Flynn分类法,主要根据指令流和数据流来分类。按照Flynn分类法,计算平台共分为四种类型。

1.单指令流单数据流机器(SISD)


2.单指令流多数据流机器(SIMD)


3.多指令流单数据流机器(MISD)


4.多指令流多数据流机器(MIMD)


标量处理器

标量处理器是一种最简单的计算机处理器类型。这类处理器在同一时间内只处理一条数据(整数或浮点数)。标量处理器是一种单指令流单数据流(SISD)处理器。

向量处理器

当今大多数商业 CPU 都包括一些向量处理器指令,较为典型的是 SIMD。从运算上说,标量机只是一个数一个数地进行计算,而向量机则能够对一批数据同时进行加工处理。因此,向量机比标量机的运算速度快,更适合于演算数据量多的大型科学、工程计算问题。

并行

不同于并发的概念,并发偏重于多个任务交替执行,而多个任务之间有可能还是串行。真正意义上的“同时执行”。同时做很多事情。

SIMD

读做(sim-dee),单指令流多数据流(英语:Single Instruction Multiple Data,缩写:SIMD)是一种采用一个控制器来控制多个处理器,同时对一组数据(又称“数据向量”)中的每一个分别执行相同的操作从而实现空间上的并行性的技术。实现这种架构的并行处理机,每次都执行相同的指令,对不同的数据进行处理。这种计算机适合处理矩阵计算。

keypoints:

1.SIMD结构的CPU有多个执行部件,但都在同一个指令部件的控制之下,中央控制器向各个处理单元发送指令,整个系统只要求有一个中央控制器,只要求存储一份程序,所有的计算都是同步的。

2.以加法指令为例,单指令流单数据流(SISD)型CPU对加法指令译码后,执行部件先访问主存,取得第一个操作数,之后再一次访问主存,取得第二个操作数,随后才能进行求和运算;而在SIMD型CPU中,指令译码后,几个执行部件同时访问主存,一次性获得所有操作数进行运算。

3.SIMD不是一种具体的指令格式,经历了mmx->sse->avx这样的发展趋势,但它们都属于SIMD,SIMD更像是一种满足某种规范的技术架构总称。

SSE

Intel在1999年引入了SSE指令,SSE是"Streaming SIMD Extention"(流SIMD扩展)的缩写,SSE是Streaming SIMD Extensions(流SIMD扩展)的缩写。是由 Intel公司,在1999年推出Pentium III处理器时,同时推出的新指令集。SSE是一种SIMD指令集。SSE有8个128位寄存器,XMM0 ~XMM7。这些128位元的寄存器,可以用来存放四个32位的单精确度浮点数。SSE的浮点数运算指令就是使用这些寄存器。

keypoints:

-Intel的初代SIMD指令集是MMX,Multi-Media Extension, 即多媒体扩展,因为它的首要目标是为了支持MPEG视频解码。后来Intel进一步实现了SSE, SSE2~SSE4指令集,给了他们单独的寄存器,之后MMX就停掉了。

-SSE包含70条新的指令,其中大部分指令用于单精度 浮点数据。当对多个数据对象执行完全相同的操作时,SIMD指令可以大大提高性能。

-SSE随后被英特尔扩展为SSE2,SSE3,SSSE3和SSE4。-SSE功能历经几代,最新的版本为AVX(advanced vector extension)

-SSE中大部分指令要求地址是16byte对齐的。-要能够使用 Intel 的 SIMD 指令集,不仅需要当前 Intel 处理器的硬件支持,还需要编译器的支持。

-由于SIMD指令有多个版本,每个版本支持的指令集不同。所以如果你的软件要支持更多的CPU,就要在使用SIMD指令之前知道当前指令运行所在的CPU是否支持这条指令。

-SSE发展到SSE5戛然而止。这里有故事,2007年8月,AMD抢先宣布了SSE5指令集(之前从SSE到SSE4均为Intel制定),Intel火大,转而另起炉灶,2008年4月,Intel公布了AVX指令集规范,随后开始不断进行更新。


二:C++如何开发SIMD友好的代码?


使用SIMD技术的开发方法业内有如下几种:

1.使用著名的IPP库,IPP的全称是Intel Integrated Performance Primitives

2.方法是使用编译器的自动向量化(Auto-vectorization)支持。

3.使用编译器指示符(compiler directive),如使用英特尔的C/C++编译器(ICC)编译如下代码,那么ICC便会对#pragma simd指示符下面的for循环做向量化

4.使用Cilk技术。

5.使用编译器的内建函数(intrinsic),例如要使用要使用SSE3,#include,如果不关心使用那个版本的SSE指令,则可以包含所有#include

6.直接使用汇编语言编写汇编函数,C++调用汇编函数


编写高效程序需要做到以下几点:

第一,必须选择一组适当的算法和数据结构。

第二,必须编写出编译器能够有效优化以转换成高效可执行代码的源代码。

参考:http://sci.tuomastonteri.fi/programming/sse

三:从编译到执行,发生了什么事情?


我们刚才提到了C++代码,也提到了指令集。

提到了如何写SIMD友好的C++代码和SSE指令有多神奇。

可是,这一切是怎么发生的呢?

从C++源代码编译生成可执行代码,到CPU运行load到内存的这些代码。

这中间,发生了什么事情?

我们来聊聊CPU指令集和GCC编译的那点儿事儿。

先来温习一下计算机体系结构的基础知识:

指令 = 操作码 + 操作数

操作码:表示指令要完成的工作,如存数,取数。

操作数:操作对象的内容或者所在的单元格地址。

计算机工作的过程实际上是快速的执行指令的过程,当计算机在工作时,有两种信息流在流动。一种是数据流,通常是各种原始数据、中间结果等。一种是控制流,是由各种控制指令构成的。

指令的执行过程:

1.取指令,从内存储器取出指令到指令寄存器。

2.分析指令,对指令寄存器中存放的指令进行分析,由译码器对操作码进行译码。将指令的操作码转换成相应的控制电信号,并由地址码确定操作数的地址。

3.执行指令。由操作控制线路发出的完成该操作所需的一系列控制信息。用以完成该指令所需的操作。

4.为执行下一条指令做准备。形成下一条指令的地址。指令计数器指向存放下一条指令的地址,最后控制单元将执行结果写入内存。

上述完成一条指令的执行过程叫做一个“机器周期”;计算机在运行时,CPU从内存读取一条指令到CPU内执行,指令执行完,再从内存读取下一条指令到CPU执行。CPU不断的取指令、分析指令、执行指令,再取下一条指令,这就是程序的执行过程。

再看高级语言编译过程,是将源代码转换为机器可认识代码的过程。编译程序读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程序转换为机器语言,并且按照操作系统对可执行文件格式的要求链接生成可执行程序。

C/C++源代码编译成相应平台下的可执行文件需要经过如下步骤:

1、预处理

2、编译

3、汇编

4、链接

接下来我们探索一下C++编译的机器码如何和SIMD挂上了钩的?

首先,需要被执行的机器码先要被OS调度到内存之中, 程序执行时, 机器码依次经过了Memory--Cache--CPU fetch, 进入CPU流水线, 接着就要对它进行译码了, 译码工作生成的是CPU内部数据格式, 微码。特别需要注意的是:CPU不需要任何形式的存储介质去存储指令集, 因为"译码"这个步骤就是在对指令集里规范的机器码做解码。具体的指令编程机器码后就会变成数字电路的开关信号。其中某几段会作为控制信号,控制其他部分的数据走不同的电路以执行运算。

关键点就在这里了,从汇编到机器码这步是汇编程序翻译的。汇编程序知道某条指令要翻译成什么样的机器码。汇编的前提是一定要有格式,支持什么指令, 指令带什么限制条件, 用什么操作数, 用什么地址, 其实都是指令集规范的内容, 如果写错了, 就无法翻译成机器码。

比如C++编译后的汇编文件中某条支持SSE的某条汇编语句:

movaps  %xmm1, %xmm4

翻译成如下的机器码:

26 66 c7 84 c8 44 33 22 11 78 56

到真正执行的层面,CPU将指令(一个由0,1构成的字符串)输入译码电路,译码电路根据指令集的描述,生成各种控制信号。

控制整体晶体管逻辑电路开始工作。这个机器码就是SIMD的机器码,在单个时钟周期里能够并行的从内存中读取和计算数据。

FAQ:

1.ClickHouse怎样用到SIMD技术?

目前Clickhouse通过编译器的内建函数(intrinsic)开发的方式来利用到SIMD技术。

2. ClickHouse为什么不用更牛逼的MIMD ?

MIMD和SIMD只是体系结构的两种概念,并不是说采用SIMD支持的指令集就无法使用MIMD操作。实现SIMD概念的SSE3(举例),就支持某些MIMD操作。另外,目前笔者也没有发现有C++能够支持MIMD机器的优化。

注:由于每个执行单元的指令流都是相同的,SIMD模式将指令的获取时间均摊到每一个执行单元。但是,当指令流出现分支,指令就会被序列化。而MIMD模式的设计主要是为了处理不同指令流,当指令流出现分支,它不需要对线程进行阻塞。然而它需要更多指令存储以及译码单元,这就意味着硬件需要更多的硅,同时,为了维持多个单独的指令序列,它对指令带宽的需求也非常的高。一般使用SIMD与MIMD的混合模式才是最好的方案。用MIMD的模式处理控制流,用SIMD的模式处理大数据,在CPU上使用SSE/MME/AVX指令扩展集时就是采用的SIMD与MIMD的混合模式

3.如何编写可以自动矢量化的代码?

参考:http://www.jianshu.com/p/186339c16e8c

这个例子说明,现在处理器具备相当的计算能力,但是我们需要按照特定程式化的方式来编写程序,就可以将这些能力诱发出来。

题外话:

C++语言之父Bjarne在“2016 C++及系统软件技术大会”上。做了题为《What C++ is and what it will become》的演讲。

what is C++ --

他用两行话描述了C++是什么:

1.“Direct map to hardware” -- 直接映射到硬件

2.“Zero overhead abstraction” -- 0负担抽象

对于1,C++的字节对齐以及多指令集的支持,使之能够直接翻译对应到CPU的指令。C++的数据类型也可以直接对应到CPU支持的数据类型。无需进行转换。可谓效率奇高。

对于2,今天的JAVA、C#都有抽象,但有些语言为了抽象付出的代价很大,资源消耗多,运行速度慢,C++基本0负担,无额外开销。

what it will become --

提到了10项内容,第8项提到了在语言层面支持SIMD向量和并行化算法。

期待语言层面的SIMD支持和并行算法封装。这样,在编写能够支持SIMD优化代码时,可能就不用关注太多的细节了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容