2014-02-10 18 views
3

我目前正在向量化的程序,并且我观察到的奇数行为编译指示simd和ivdep矢量之间的差异总是如此吗?

好像使用

的#pragma SIMD

(262)时for循环被矢量:(COL。 3)备注:SIMD LOOP WAS向量化。

但它并不当我使用

的#pragma矢量总是

的#pragma ivdep

(262):(COL 3)备注:循环未向量化:存在矢量依赖。

我一直认为两个句子做同样的量化

回答

4

编译SIMD强制循环的向量化,不计成本或安全的。

编译器向导总是告诉编译器在决定是否向量化时忽略效率启发式。仅在添加该附注时才进行矢量化的代码可能会较慢。

编译ivdep告诉编译器忽略抑制矢量(例如循环承载依赖性)假定数据相关,但没有证明的。例如,它可能假设指针不指向相同的内存并向量化。然而,它不会忽视一个经过验证的循环携带依赖(a [i] = a [i - 1] * c),但编译指示可能会。

您的代码可能只有使用编译指示simd进行矢量化的原因是被忽略的证明依赖。您可能想验证您的程序输出是否正确。

来源:Intel特定编译指示文档(http://software.intel.com/en-us/node/462880

2

附注SIMD是如在https://software.intel.com/en-us/node/514582提到赋予显影剂以执行向量化一个明确的矢量化工具而编译指示矢量是用于指示编译器的工具环应根据其论据进行矢量化。这里的观点总是意味着“它应该忽略编译器的成本/效率启发式,并继续进行矢量化”。有关Pragma矢量的更多信息,请访问https://software.intel.com/en-us/node/514586。这并不意味着编译指示向量总是无法进行向量化时,编译指示会产生错误的结果。当#pragma simd与正确的子句集合一起使用时,它可以进行矢量化并仍然产生正确的结果。以下是演示了一个小的代码片段:

void foo(float *a, float *b, float *c, int N){ 
    #pragma vector always 
    #pragma ivdep 
    //#pragma simd vectorlength(2) 
    for(int i = 2; i < N; i++) 
     a[i] = a[i-2] + b[i] + c[i]; 
    return; 
    } 

使用ICC会产生以下矢量报道编译此代码:

$ icc -c -vec-report2 test11.cc 
test11.cc(5): (col. 1) remark: loop was not vectorized: existence of vector dependence 

通过它使用128位XMM寄存器的默认ICC目标SSE2。 4个浮点数可以容纳在一个XMM寄存器中,但是当你试图容纳4个浮点数的矢量时,会有一个矢量依赖性。那么#pragma向量总是发出什么是正确的。但不是4,如果我们只考虑2个浮点数,我们可以矢量化这个循环而不会破坏结果。对于相同的量化报告如下:

void foo(float *a, float *b, float *c, int N){ 
//#pragma vector always 
//#pragma ivdep 
#pragma simd vectorlength(2) 
for(int i = 2; i < N; i++) 
     a[i] = a[i-2] + b[i] + c[i]; 
return; 
} 
$ icc -c -vec-report2 test11.cc 
test11.cc(5): (col. 1) remark: SIMD LOOP WAS VECTORIZED 

不过的#pragma向量不能够明确指定矢量长度时要考虑引导循环条款。这是编译simd可以真正派上用场。当与最佳解释矢量方式计算的右边子句一起使用时,编译器将生成所请求的矢量,这将不会产生错误的结果。发布在https://software.intel.com/sites/default/files/article/402486/intel-cilk-plus-white-paper.pdf处的英特尔(R)Cilk(TM)Plus白皮书有一章“使用$ pragma simd向量长度子句”和“使用$ pragma simd reduction和private clause”,它解释了如何在右子句中编译simd子句。这些条款帮助开发人员向编译器表达他想实现的目标,并且编译器相应地生成向量代码。强烈建议在需要的地方使用#pragma simd和相关的子句以最好地向编译器表达循环逻辑。

传统上,内部循环也是矢量化的目标,但编译指示simd也可用于矢量化外部循环。有关这方面的更多信息,请登录https://software.intel.com/en-us/articles/outer-loop-vectorization

+0

我相信'for'循环的起始索引应该是'i = 2' ... –