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

原创 2003年05月17日 16:51:00

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

 

本文节选翻译自Intel编译器文档

 

1.       向量化循环中的数据类型

在整形的循环中,MMXSSE技术都为多数使用8/16/32bits长度数据的算法和逻辑操作提供了相应的SIMD指令,如果一个使用整数的算法把结果保存在一个有足够精度的变量中,那么这个算法就可能被向量化,举例说,一个运算的结果是32位整数,但却被保存在一个16位的整数中,那么这么操作就不能被向量化,不是所有整形操作都能够被向量化的.

32位或64位浮点数的循环中,SSE指令集不光为加减乘除等运算提供了相应的SIMD指令,而且也提供了诸如MAX/MIN/SORT这样的操作的SIMD指令,其它的一些数学运算,比如三角函数SIN/COS/TANSIMD版本也已经在和编译器一起提供的向量数学库中得到了支持.

 

2.       展开循环

         编译器会自动对循环进行分析,并生成展开后的代码,这就是说你不需要自己去展开循环重新编写循环操作,在很多情况下,这能够使你获得更多的向量化操作.

看下面的循环

int i = 0;

     while(i < k)

     {

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

         ++i;

}

              向量化后就生成这样2个循环操作

                                   while(i < (k - k % 4))

  {

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

    a[i + 1] = b[i + 1] + c[i + 1];

    a[i + 2] = b[i + 2] + c[i + 2];

    a[i + 3] = b[i + 3] + c[i + 3];

    i+=4; 

  }

 

  while(i < k)

  {

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

++i;  <-此处文档上遗漏,很显然缺少这行程序很可能会陷入死循环

  }

 

 

 

3.       循环中的语句

整数和浮点数间的向量化操作是不同的.

 

a)          浮点数组操作

支持的算法包括加/////平方根/求最大值/求最小值,P4处理器还可以使用双精度的运算,前提是编译时使用-QxW-QaxW打开对P4的优化.

 

b)         整数数组操作

在包含8/16/32位整形数据的循环中,计算平方根(sqrt)和浮点数绝对值(fabs)这样的运算也是可以支持的,像加//(16)/(16)/and/or/xor/max/min这些运算在一定条件下也是支持的,你可以在运算中使用多种数据类型只要结果不丢失数据,就是说结果不能超过32bits发生溢出.

 

c)          其它操作

任何超出整数和浮点数精度范围的语句都是不能向量化的,那些特殊的如__m64__m128这样类型的数据也不能被向量化,循环中不能有任何函数调用(:void fun(void)这样的是可以的J),也不能够使用SSE SDKIntrinsics(这里意思不确定,原文是Use of  the Streaming SIMD Extensions Intrinsics(_mm_add_ps) are not allowed ).

 

4.       语言支持和控制指令

一些控制指令可以更好的帮助你向量化你的代码.

__declspec(align(n))

使你的编译器把变量的地址对齐n字节,就是说变量的地址 mod n =0

__declspec(align(n,off))

使你的编译器把变量的地址对齐n字节+offset,就是说变量的地址 mod n = off

restrict

使编译器认为没有指针别名,可以更容易向量化你的代码

__assume_aligned(a,n)

如果编译器没能字节对齐的信息,用这个让编译器假设数组a使按n对齐的

#pragma ivdep

让编译器假设你的代码没有数据依赖

#pragma vector

{aligned | unaligned | always}

指定如何向量化这个循环并忽略效率推测

#pragma novector

不要向量化这个循环

 

 

5.       一些向量化循环的例子

a)          有别名问题的循环

下面的例子是个向量复制的操作

void vec_copy (int* p1,int* p2)

{

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

  {

    p1[i] = p2[i];

  }

}

这里因为编译器能清楚的分别两个指针,所以可以被向量化.

 

又有个例子

void vec_copy (int* restrict p1,int* restrict p2)

{

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

  {

    p1[i] = p2[i];

  }

}

和上一个例子同样可以被向量化,但是用了restrict,所以编译器不用产生多个版本的代码,注意,restrict编译时要加/Qrestrict参数

 

6.       数据对齐

一个16字节或更大的数据结构或数组应该是对齐的,所以这些结构和数据的基地址应该是16的倍数,下图说明了一个DCU(data cache unit)是如何分割一个没有对齐16字节的数据.

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

 

在访问这个数据的时候需要多花费6-12时钟周期,如果你能把数据对齐就可以避免这些额外的性能开销

举例说明

float *a,*b;

for (i = 0; i < 10; ++i)

              {

                   a[i] = b[i];

     }

如果a[0]/b[0]都是16字节对齐的,那么这个循环就可以使用#pragma vector aligned这个指令,在向量化后就是这样执行的.

     2次向量化迭代             2次循环

ß------------------------à ß------->

     i=0-3,i=4-7                i=8-9

2次向量化迭代可以用块复制的方式来操作.

 

注意,如果向量化使用不正确的对齐指令,编译器会产生不可预见的行为,比如在未对齐的的数据上使用#pragma vector aligned将会导致一个异常.

 

这是几个关于数据对齐的例子

void f(int lb)

{

     float z2[N],a2[N],y2[N],x2;

     for (i = lb; i < N; ++i)

          {

              a2[i] = a2[i] * x2 + y2[i];

          }

}

因为无法在编译时去确定lb,所以我们只能认为这里没有做到对齐,如果你确定lb时4的倍数,那么你就可以使用#pragma vector aligned.

void f(int lb)

{

     float z2[N],a2[N],y2[N],x2;

     assert(lb % 4 = 0);

     #pragma vector aligned

for (i = lb; i < N; ++i)

          {

              a2[i] = a2[i] * x2 + y2[i];

          }

}

 

 

全文完,谢谢大家的支持.

使用#pragma simd进行自动向量化

#pragma simd 该编译指示(SIMD)是12.0编译器最新提供的功能。他可以强制性的让编译器做自动并行化。对于其他编译指示比如#pragma ivdep来说,如果编译器编译时发现用户提...
  • honey_yyang
  • honey_yyang
  • 2012年08月09日 17:59
  • 2801

OpenCL优化方法-消除访问内存数组引起的循环依赖关系

消除访问内存数组引起的循环依赖关系 在单个工作项内核中包含ivdep pragma,可以声明对内存数组的访问不会导致循环依赖。在编译期间,OpenCL离线编译器的英特尔FPGA SDK创建了可确保加...
  • zhenxindengdai1208
  • zhenxindengdai1208
  • 2017年08月01日 20:03
  • 148

SSE指令优化一例

前两天为了加速一段求梯度的代码,用了SSE指令,在实验室PMH大侠的指导下,最终实现了3倍速度提升(极限是4倍,因为4个浮点数一起计算)。在这里写一下心得,欢迎拍砖。 SSE加速的几个关键是 ...
  • mydear_11000
  • mydear_11000
  • 2016年03月11日 15:46
  • 1168

基于intel编译器的优化

首先介绍下编译器所提供的编译优化功能,这些都比较简单: 普通优化 Linux 功能 -O0 禁止优化 -g 生成标...
  • honey_yyang
  • honey_yyang
  • 2012年08月09日 20:17
  • 4334

sse优化一例

sse优化一例
  • jacke121
  • jacke121
  • 2017年01月24日 10:29
  • 229

VS2010下FPU和SSE优化测试结果

#include #include #include #include using namespace std; #define asm __asm #define ARRAY_S...
  • swimmingfish2004
  • swimmingfish2004
  • 2011年05月16日 15:52
  • 2093

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

使用Intel 向量化编译器优化性能(1) 本文节选翻译自Intel网站 使用Intel c++编译器的时候,怎么也找不到相关的资料可以参考,在Intel的网站找到了一些教程,我C++的水平很一般,对...
  • xzygod
  • xzygod
  • 2003年05月13日 11:02
  • 2208

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

使用Intel 向量化编译器优化性能(2) 本文部分翻译自Intel网站,部分选自Intel编译器文档以及中科院计算所的一些资料        首先要向大家道歉,由于疏忽,才发现intel的这个教程可...
  • xzygod
  • xzygod
  • 2003年05月14日 14:21
  • 1649

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

使用Intel 向量化编译器优化性能(3) 本文节选翻译自Intel编译器文档 1.       向量化循环中的数据类型在整形的循环中,MMX和SSE技术都为多数使用8/16/32bits长度数据的算...
  • xzygod
  • xzygod
  • 2003年05月17日 16:51
  • 2082

图象:sine(正弦)、cosine(余弦)与Tangent(正切)

http://www.97ae.com/aebiaodashi/geometry/trig_graphs.html 目录 矢量加法 距离与长度 三角函数 图象:正弦、...
  • linuxheik
  • linuxheik
  • 2013年09月06日 10:54
  • 2753
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用Intel 向量化编译器优化性能(3)
举报原因:
原因补充:

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