使用Intel 向量化编译器优化性能(2)

原创 2003年05月14日 14:21:00

使用Intel 向量化编译器优化性能(2)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

本文部分翻译自Intel网站,部分选自Intel编译器文档以及中科院计算所的一些资料

 

       首先要向大家道歉,由于疏忽,才发现intel的这个教程可能只是针对5.0版本的编译器,现在已经是7.1,所以文中的例子可能在现在的编译器上会有不同的表现,我会把每一个例子测试一下,并结合从其它渠道找到的关于intel编译器的文档来给大家介绍向量化编译技术.

 

1.         如何编写向量化程序

向量化代码是一个不断尝试的过程,每一个循环在被向量化前都可能需要调整很多次,依据下面几条原则去做能更好帮你完成工作.

 

a)         先尝试编译一次,会有一些循环是可以直接被向量化的.

一些现有的代码可能已经符合了编译器的要求,不需要做任何修改就可以直接被向量化,不管怎么样,先试一下.

 

b)        找到你的代码中的那些最影响程序性能的循环

使用代码分析工具来寻找你的代码中那些经常被调用的循环,这些循环最值得被向量化,即使是一个很小的循环,如果被频繁调用的话,对性能的影响是很可观的,所以能够向量化这个循环将给你的代码带来很大的性能的提高,Intel VTune Performance Analyzer 可以帮你找到这些性能上的瓶颈,你可以从Intel的网站上下载并免费试用 http://www.intel.com/software/products/vtune. 关于VTune的具体使用方法我会在别的时间给大家介绍,现在我就把它能做什么简单说一下

 

1.       附加在一个可执行文件上,在这程序运行的期间搜集处理器数据.

2.       跟踪你的代码,并把关于你的代码的性能的数据记录下来,比如函数A运行了多少时钟周期,使用了多少条指令…等,这样你就很容易找到那些最影响性能的循环.

3.       把运行的数据生成图形报表.

4.       对统计结果提出建议,知道你对代码的优化.

 

c)       使用#pragma ivdep

这个上次说明过了.

 

d)       重新编写这个循环

有时候一个循环在结构上注定无法向量化,这时只能另起炉灶了...

 

 

2.       循环中的数据依赖

为了从分利用Intel编译器,你需要了解数据依赖产生的原因以及如何处理这些情况

 

a)           这里因为Intel网站的例子可能有问题,应该是编译器版本问题,所以我换了个例子以说明问题,当然这样的例子在实际应用中没有什么意义,这里只是为了说明问题

 

下面这段程序是无法被向量化的.

 

float data[100];

int i = 0;

for (i = 0; i < 100-1; ++i)

{

  s1:  data[i] = data[i-1]*0.25 + data[i]*0.5+data[i+1]*0.25;

}

在这里在S1语句中的data[i]对data[i-1]产生数据依赖,data[i]被data[i-1]在上一个循环迭代中所修改,不明白?,这么看:

data[i-1] 的下标比 data[i]小1,操作中data[i-1]总是会覆盖data[i],这就说明了上一次说的向量化不是并行化,因为在向量化中是要考虑这样的相互影响,所以不能说是完全的并行化,虽然数据是被SIMD方式并行操作的.偶是这么理解的,或许有不正确的地方,请大家及时指正.再看下面的说明可能会更清晰一些.     

上面的例子中 当i=1时:            i=2时

read data[0]                    read data[1]

read data[1]                    read data[2]

read data[2]                    read data[3]

write data[1]                   write data[2]

当使用标量循环时不会有什么问题,data[1]数据依次被改写,但是在SIMD并行操作中问题就出现了i=2时 read data[1]时,数据就可能已经被i=1的write data[i]修改,这就改变了这个循环的本意.这是绝对不可以.

 

b)           上面是数据依赖的实际例子,下面我们从理论上解释一下数据依赖的原因.

数据依赖产生的条件就是在操作中发现可能对内存中发生的覆盖的存取,如果代码中有2个引用,那么.

1.       2个引用可能是别名,而他们指向了同一块内存或是两块相互覆盖的内存

2.       如果是数组,那就很据他们的下标来判断是否覆盖同一块内存.

对于数组,编译器的数据依赖分析器将使用一系列逐渐强化的测试来获取循环在时间和空间上的开销.首先编译器会对数组的每个维进行一些简单的测试,直到在任何一个维上都没有发现数据依赖的问题.在测试前,使用多维数组时可能发生的在它们定义边界内的数据交叉可以被转换为一个线性化的形式,其中的一些测试会使用快速最大公约数测试, 测试会使用达到数组边界的数据已确保不会有数据覆盖的问题.

如果上面的测试失败,编译器就会使用Fourier-Motzkin消去法来解决所有维中的数据依赖问题.

这里我发现Intel网站的教程中并没有提到这一过程,可能这就是在高版本编译器中更容易解决数据依赖问题而不需要人为去修改代码的原因,实际上我说的那个有问题的例子就是直接可以进行向量化编译而不需要修改.

 

下面看几个循环的例子.

1.         循环结构

可以使用for/while/until来构成循环,但是循环只能有一个入口和一个出口.

 

While( i< 100)

{

       a[i] = b[i] * c[i];

       if (a[i] < 0.0)

{

  a[i] = 0.0;

}

++i;

}

这个可以被向量化

While( i< 100)

{

       a[i] = b[i] * c[i];

       if (a[i] < 0.0)

{

  a[i] = 0.0;

       break;    

}

++i;

}

这样不行,不能有多个出口

 

2.       循环退出条件

循环退出条件决定了,循环执行的迭代次数,比如一个固定的次数.总之这必须是一个可以确定循环次数的表达式.

a)       常量,如100

b)       一个不被改变的变量,如 i=100

c)       一个计算循环次数的线性函数 如 i=100-1

 

下面是几个示例

 

                           

 

 

 

 

 

int k = 100;int i = 0;

while(i< k - 1)  

{

  a[i] = b[i] * c[i];

  if (a[i] < 0.0)

  {

    a[i] = 0.0;

   

  }

  ++i;

}

条件确定

 

int k = 100;int i = 0;

while(i< k – i) 

{

  a[i] = b[i] * c[i];

  if (a[i] < 0.0)

  {

    a[i] = 0.0;

   

  }

  ++i;

}

条件不确定,循环次数依赖i

 

for (i = m;i < n;++i)

{

  a[i] = i + 1;

}

条件确定,循环次数为 n-m

 

 

【优化程序性能】编译器的优化和限制

写程序最主要的目标是使他在所有的可能的情况下dou
  • u011708432
  • u011708432
  • 2014年05月02日 23:00
  • 832

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

今天和C++同行谈谈如何提高自己的身价。编程语言只是工具,要把工具用到最合适的地方,扬其长且避其短,打造出有价值的软件产品,那么使用这工具的人自然身价就高了。 C++语言的优势 C++语言...
  • i7thTool
  • i7thTool
  • 2017年02月10日 13:03
  • 4113

【golang】Go 性能优化技巧

一. array与slice 对于一些初学者,自知道 Go 里面的 array 以 pass-by-value 方式传递后,就莫名地引起 “恐慌”。外加诸多文章未作说明,就建议用 slice 代替 ...
  • zhonglinzhang
  • zhonglinzhang
  • 2017年05月03日 09:56
  • 575

intel编译器icc以及数学库MKL的下载与安装

icc是一款非常不错的编译器,intel有非商业版,可以免费下载,虽不提供技术支持,但对于大多数普通用户来讲,已经够用了.下面我就 ifort,icc编译器的下载安装及配置过程介绍如下,另外还介绍了相...
  • huangfei711
  • huangfei711
  • 2015年07月07日 10:14
  • 4560

优化CNNs--量化方法进展介绍

介绍了最新的几种通过量化方法来优化卷积神经网络的网络结构
  • dnvtmf
  • dnvtmf
  • 2017年07月09日 18:31
  • 750

使用Intel编译器SSA

1) 内存相关(初始化、NULL指针引用、内存分配和释放、内存重复释放(double free),内存泄漏、非法内存访问、缓冲区溢出等) 1. 读取没有初始化的变量,Uninitialized ...
  • x356982611
  • x356982611
  • 2015年01月05日 09:07
  • 1261

【量化投资】基金择时策略浅析(4) ——参数优化和模型稳定性

在股票市场的建模过程中,样本数据相对于要识别的模式来说一般都比较稀缺,因此模型不宜太复杂,而且模型的稳定性比参数最优化更重要。在本文中我们会讨论常见择时方法的参数优化和模型稳定性等问题。...
  • JDJRdata
  • JDJRdata
  • 2017年08月04日 09:51
  • 314

优化Angular应用的性能

MVVM框架的性能,其实就取决于几个因素: 监控的个数数据变更检测与绑定的方式索引的性能数据的大小数据的结构 我们要优化Angular项目的性能,也需要从这几个方面入手。 1. 减少...
  • happyduoduo1
  • happyduoduo1
  • 2016年07月05日 14:38
  • 3479

扫盲操作系统虚拟机[6]:如何优化运行速度?

预测未来最好的方法就是去创造未来 ——林肯 (美国前总统) 扫盲操作系统虚拟机[6]:如何优化运行速度?   前几天聊到了对付流氓软件的几个招数,其中...
  • DYC410181341
  • DYC410181341
  • 2014年10月06日 00:12
  • 2820

降低Cache失效率--编译器优化

//学点儿东西,晚些记得贴上来。。。
  • c__ilikeyouma
  • c__ilikeyouma
  • 2014年01月04日 01:14
  • 1956
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用Intel 向量化编译器优化性能(2)
举报原因:
原因补充:

(最多只允许输入30个字)