




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
使用英特尔编译器进行自动向量化 作者:Yang Wang (Intel)自动向量化是英特尔编译器提供的一个可以自动的使用SIMD指示的功能。 在处理数据时, 编译器自动选择MMX, Intel Streaming SIMD 扩展(Intel SSE, SSE2, SSE3 和SSE4)等指令集, 对数据进行并行的处理。 使用编译器提供的自动向量化功能是提高程序性能的一个非常有效的手段。自动向量化在IA-32和Intel 64的平台上均提供很好的支持。英特尔编译器提供的自动向量化相关的编译选项如下所示。”/Q”开头的选项是针对Windows平台的, “-“开头的选项是针对Linux*和Mac平台的。-x, /Qx按照该选项指定的处理器类型生成相应的优化代码。 比如-xSSE3, 该选项指定编译器生成Intel SSE3指令的代码。 又比如-xSSE3_ATOM, 该选项针对Intel Atom 处理器进行优化。-ax, /Qax如果指定该选项, 在生成的单一目标文件中, 不但会生成专门针对指定的处理器类型进行优化的代码, 同时也生成通用的IA-32架构的代码。 该选项主要是为了生成代码的兼容性考虑。-vec, /Qvec打开或者关闭编译器的向量化优化。 默认情况下自动向量化是打开的。-vec-report, /Qvec-report该选项用户控制在编译过程中产生的向量化消息报告。编译器提供的自动向量化优化默认情况下是打开的。 在编译过程中我们可以使用-vec-report选项来打开向量化诊断消息报告。 这样编译器可以告诉我们有哪些循环被向量化了, 有哪些循环没有被向量化已经无法向量化的原因。在编译程序的过程中, 有时候我们会发现编译器报告说某个循环无法被向量化。 很多时候无法向量化的原因都是因为循环中存在的变量依赖关系。 有时候我们可以修改程序来消除这种依赖关系,有的时候我们可以使用编译器提供的一些编译指示来显示的告诉编译器如何处理这种依赖关系。 即使在某个循环已经可以被自动向量化的时候, 使用编译器提供的对向量化的语言支持和编译指示还可以提高编译器向量化的效率, 提高程序执行的性能。下面我们来详细解释一下编译器提供的编译指示以及这些指示对编译器编译的影响。在Intel编译器中, 我们提供下面这样一些对自动向量化的语言支持和编译指示。_declspec(align(n)指导编译器将变量按照n字节对齐_declspec(align(n,off)指导编译器将变量按照n字节再加上off字节的编译量进行对齐restrict消除别名分析中的二义性_assume_aligned(a,n)当编译器无法获取对齐信息时,假定数组a已经按照n字节对齐#pragma ivdep提示编译器忽略可能存在的向量依赖关系#pragma vector aligned|unaligned|always指定向量化的方式#pragma novector指定不做向量化下面我们就这些编译指示做一些详细的了解。 _declspec(align(n)首先我们来看看如何使用_declspec(align(n)来进行自动向量化。该指示主要是用来告诉编译器一个变量的对齐方式。 当一个变量的对齐方式为16字节对齐时, 生成的向量化指令是最高效的。 当编译器不知道一个变量的对齐方式的时候, 他可能没有办法对该变量的使用进行向量化, 或者编译器会不得不生成条件语句来进行有条件的向量化。 我们来看一下下面这个例子。File: vec1.cchar a;void vec1(void)int i;for(i=0;i1024;i+)ai = 1;使用下面命令编译该程序:icl vec1.c -O2 -c /Qvec-report:3这时编译器输出:vec1.cvec1.c(10) (col. 2): remark: LOOP WAS VECTORIZED.我们可以看到编译器对上面这个程序进行了自动向量化。 但是实际上, 由于编译器不知道a的对齐字节数, 所以他对变量a数据进行了一些条件处理。 我们可以在编译的时候加上-S选项来查看编译器生成的汇编代码。 实际上, 编译器对该程序做了如下处理:temp = a&0x0f;if(temp != 0)temp = 16-temp;for(i=0;itemp;i+) ai = 1;/*下面是对齐的访问*/for(i=temp;i1024;i+) ai = 1;如果我们指定了a的对齐方式, 比如我们使用_declspec(align(16)来定义变量a, 如下所示:_declspec(align(16) char a;void vec1(void)int i;for(i=0;i1024;i+)ai = 1;对于上面这段程序, 编译器做了自动向量化。 如果我们检查生成的汇编代码可以发现,对于a的对齐方式的条件处理代码已经不见了。正确使用_declspec(align(n)以及其他align相关编译指示可以帮助编译器进行自动向量化以及提高编译器自动向量化的效率。 restrict使用restrict关键字可以显式的告诉编译器取消指针之间的二义性。 我们还是用下面这个例子来说明restrict的使用。File: vec2.cvoid vec2(char* a, char* b, int n)int i;for(i=0;in;i+)ai = bi;使用以下命令进行编译:icl vec2.c -O2 -c /Qvec-report:3编译器输出:vec2.crestrict.c(5) (col. 2): remark: LOOP WAS VECTORIZED.restrict.c(5) (col. 2): remark: loop skipped: multiversioned.此时编译器输出multiversioned向量化代码, 对同一个循环产生了多个版本的实现。实际上编译器对代码进行了条件处理, 如下所示:void vec2(char* a, char* b, int n)int i;if(a+nb | b+na)for(i=0;in;i+) ai = bi; /*向量化循环*/elsefor(i=0;in;i+) ai = bi; /*串行循环*/可以看出,由于编译器不知道指针a 和b之间是否存在重叠, 所以他对循环进行了条件处理。 如果我们从语义上能够保证a和b是不会发生重叠的, 那么我们就可以使用restrict关键字来显式的告诉编译器这一点。void vec2(char* restrict a, char* restrict b, int n)int i;for(i=0;in;i+)ai = bi;此时编译器输出没有multiversioned。restrict.crestrict.c(5) (col. 2): remark: LOOP WAS VECTORIZED.注意C90里面不支持restrict关键字, 在windows平台编译的时候我们需要加上选项/Qrestrict来让编译器认识restrict关键字。 #pragma vector使用#pragma vector编译指示来显式告诉编译器使用某种方式来进行自动向量化。 比如在下面这个例子中, 我们可以保证变量a的地址是16字节对齐的,那么我们就可以使用#pragma vector aligned来显式的告诉编译器不需要考虑非对齐的情况。这样产生的向量化代码是最高效的。File: vec3.c#include void vec3(void)int i;char* a=_aligned_malloc(1024, 16);#pragma vector alignedfor(i=0;i1024;i+)ai = 1;在上面这个例子中, 如果我们不加上#pragma vector aligned, 编译器会对循环进行条件处理后的向量化。 大家可以对比一下两种情况下生成的汇编代码的区别。请注意我们在使用#pragma vector aligned的时候需要保证被处理变量的对齐方式是16字节对齐的, 否则在使用了该编译指示后可能会产生错误的结果。在上面这个例子中, 我们稍作如下修改:#include void vec3(void)int i;char* a=_aligned_malloc(1024, 16);char* b = a+1;#pragma vector alignedfor(i=0;i1023;i+)bi = 1;循环中的b的地址不是16字节对齐的, 但是如果我们还是按照aligned的方式来做向量化, 产生的结果是编译出来的可执行程序运行时异常。 在上面的例子中, 我们需要使用#pragma vector unaligned 编译指示来正确的引导编译器。 #pragma ivdep使用#pragma ivdep显式的告诉编译器忽略向量之间可能存在的依赖关系。参考下面这个例子。File: vec4.cvoid vec4(int* a, unsigned int n, unsigned int m)int i;for(i=0;in;i+)ai = ai+m;使用编译器编译该程序:icl vec4.c O2 -c /Qvec-report:3编译器输出:vec4.cvec4.c(6) (col. 2): remark: loop was not vectorized: existence ofvector dependence.vec4.c(7) (col. 3): remark: vector dependence: assumed ANTI dependence between a line 7 and a line 7.vec4.c(7) (col. 3): remark: vector dependence: assumed FLOW dependence between a line 7 and a line 7.vec4.c(7) (col. 3): remark: vector dependence: assumed FLOW dependence between a line 7 and a line 7.vec4.c(7) (col. 3): remark: vector dependence: assumed ANTI dependence between a line 7 and a line 7.如果我们可以保证a0到an-1和am到am+n-1之间不存在重叠, 那么我们就可以使用#pragma ivdep来显式的告诉编译器可以忽略ai和ai+m之间的依赖关系, 修改程序如下:void vec4(int* a, unsigned int n, unsigned int m)int i;#pragma ivdepfor(i=0;i Compiler Options. Many library routines that are part of Intel Compiler are more highly optimized for Intel microprocessors than for other microprocessors. While the compilers and libraries in Intel Compiler offer optimizations for both Intel and Intel-compatible microprocessors, depending on the options you select, your code and other factors, you likely will get extra performance on Intel microprocessors.While the paragraph above describes the basic optimization approach for Intel Compiler, with respect to Intels compilers and associated libraries as a whole, Intel Compiler may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors. These optimizations include Intel Streaming SIMD Extensions 2 (Intel SSE2), Intel Streaming SIMD Extensions 3 (Intel SSE3), and Supplemental Streaming SIMD Extensions 3 (Intel SSSE3) instruction sets and other optimizations. Intel does not guarantee the availability, functionality, or effectiveness of any optimization on microprocessors not manufactured by Intel. Microprocessor-dependent optimizations in this product are intended for use with Intel microprocessors.Intel recommends that you evaluate other compilers to determine which best meet your requirements.使用#pragma simd进行自动向量化#pragma simd该编译指示(SIMD)是12.0编译器最新提供的功能。他可以强制性的让编译器做自动并行化。 对于其他编译指示比如#pragma ivdep来说, 如果编译器编译时发现用户提供的编译指示条件不满足, 那么编译器是不会根据编译指示来进行自动向量化的。也就是说, 编译器实际上还是会进行编译时的依赖关系检查。 而对于#pargam simd来说, 无论编译时条件如何, 编译器总是会进行自动向量化。这种情况下, 用户需要自己去保证被向量化的循环上语义的正确性, 需要自己保证被向量化变量之间的依赖关系的正确性。我们用一个例子来说明编译器的行为区别。File vec5.cvoid vec5(int* a, int n)int i;for(i=0;in;i+)ai = ai-1;对上面这个例子, 由于存在flow-dependence关系, 程序中的循环明显是不能被向量化的。vec5.cC:testvec5.c(6) (col. 2): remark: loop was not vectorized: existence of vector dependence.C:testvec5.c(7) (col. 3): remark: vector dependence: assumed FLOW dependence between a line 7 and a line 7.此时我们加上#pragma ivdep想让编译器忽略循环之间的依赖关系(当然这种操作是不符合原始语义的)。void vec5(int* a, int n)int i;#pragma ivdepfor(i=0;in;i+)ai = ai-1;这时编译该程序, 程序的输出与不加#pragma ivdep时相同。 编译器在进行编译的时候检查发现了循环之间不可避免的依赖关系, 即使有#pragma ivdep存在, 编译器也还是不会对该循环进行向量化。如果我们加上#pragma simd, 重新编译程序:void vec5(int* a, int n)int i;#pragma simdfor(i=0;in;i+)ai = ai-1;这时编译输出:vec5.cC:testvec5.c(6) (col. 2): remark: SIMD LOOP WAS VECTORIZED.程序中的循环被向量化了, 但是此时我们显然不会得到一个正确的结果。我们再看一个用SIMD的正确的例子。 比如下面这个程序:void vec5(int* a, int n, int m)int i;for(i=0;in;i+)ai = ai-m;编译该程序: icl /O2 /c /Qvec_report:3, 编译器会报告该程序因为存在向量依赖关系而不能被向量化。在该程序中, 如果我们可以保证m大于等于4, 那么我们可以加入#pragma simd指示如下所示:void vec5(int* a, int n, int m)int i;#prgama simdfor(i=0;i Compiler Options. Many library routines that are part of Intel Compiler are more highly optimized for Intel microprocessors than for other microprocessors. While the compilers and libraries in Intel Compiler offer optimizations for both Intel and Intel-compatible microprocessors, depending on the options you select, your code and other factors, you likely will get extra performance on Intel microprocessors.While the paragraph above describes t
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 电铲初级工练习题(附参考答案)
- 2025员工拒绝签订劳动合同企业应对策略全解析
- 商业信息咨询和辅导服务协议规定事项
- 智能硬件产品设计与制造合同协议
- 知识产权转让合同协议书要求专业版
- 设备采购合同协议条款
- 经济师专业试题及答案
- 2025湖南省低空经济发展集团有限公司招聘12人(第二次)笔试参考题库附带答案详解
- 2025江西南昌市信阳鼎信产业投资集团有限公司及所属二级公司招聘24人笔试参考题库附带答案详解
- 2025广西旅发大健康产业集团有限公司招聘278人笔试参考题库附带答案详解
- 2025年二级风力发电运维值班员职业技能鉴定考试题库(浓缩500题)
- 9.2严格执法 课件-高中政治统编版必修三政治与法治
- 生命健康教育智慧树知到期末考试答案章节答案2024年温州医科大学
- 2023年河北高中学业水平考试物理试卷真题及答案详解
- 重症患者的容量管理
- 工控培训教程、手册合集倍福plc从入门到精通
- 三年级下册美术教案-第11课 门票设计-非遗馆|浙美版
- I-am-a-bunny-绘本教学课件
- 养老院 入住申请表
- TwinCAT-CNC-入门教程
- 基于android平台的实时公交查询系统方案
评论
0/150
提交评论