实用注解simd和ivdep vector总是有区别吗?

Ign*_*lla 4 c++ pragma vectorization icc

我目前正在尝试对程序进行矢量化处理,并且观察到了奇怪的行为

似乎在使用时对for循环进行了矢量化

#pragma simd

(262):(第3列)备注:SIMD LOOP已被存储。

但是当我使用时没有

#pragma vector Always

#pragma ivdep

(262):(第3列)注释:循环未向量化:存在向量依赖性。

我一直以为两个句子都做相同的向量化

小智 7

pragma simd 强制循环矢量化,无论成本或安全性如何。

pragma向量总是告诉编译器在决定是否向量化时忽略效率启发法。仅当添加此编译指示时才进行矢量化的代码可能会较慢。

pragma ivdep 告诉编译器忽略假设的抑制向量化的数据依赖性(例如循环携带的依赖性),但不是经过验证的数据依赖性。例如,它可能假设指针不指向相同的内存并进行向量化。但是,它不会忽略经过验证的循环携带的依赖性(a[i] = a[i - 1] * c),但 pragma simd 可能会忽略。

您的代码可能仅使用 pragma simd 进行矢量化的一个原因是已证明的依赖性被忽略了。您可能想验证您的程序输出是否正确。

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


Ano*_*tel 5

Pragma SIMD是提供给开发人员的显式矢量化工具,用于强制执行矢量化,如https://software.intel.com/zh-cn/node/514582所述,而pragma vector是一种工具,用于指示循环应执行的编译器根据其参数进行向量化。这里的论点始终是“这应该忽略编译器的成本/效率启发法,并继续进行矢量化”。有关Pragma向量的更多信息,请访问https://software.intel.com/zh-cn/node/514586。这并不意味着在杂散向量总是无法矢量化时,杂散simd会产生错误的结果。当#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;
   }
Run Code Online (Sandbox Code Playgroud)

使用ICC编译此代码将产生以下矢量化报告:

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

默认情况下,ICC以使用128位XMM寄存器的SSE2为目标。一个XMM寄存器中可以容纳4个浮点数,但是当您尝试容纳4个浮点数的向量时,则存在向量相关性。因此,#pragma向量始终发出的信号是正确的。但是,如果不考虑4个浮点数,则可以用4个浮点数代替矢量,而不破坏结果。相同的矢量化报告如下所示:

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
Run Code Online (Sandbox Code Playgroud)

但是#pragma vector没有子句,后者可以明确指定在对循环进行矢量处理时要考虑的矢量长度。这是pragma simd真的可以派上用场的地方。与正确的子句一起使用可以最好地解释矢量形式的计算时,编译器将生成请求的矢量,而不会产生错误的结果。英特尔(R)Cilk(TM)Plus白皮书发布于https://software.intel.com/sites/default/files/article/402486/intel-cilk-plus-white-paper.pdf在“ $ pragma simd vectorlength子句的用法”和“ $ pragma simd归约和私有子句的用法”一节中,介绍了如何使用正确的子句对pragma simd子句进行处理。这些子句帮助开发人员向编译器表达他想要实现的目标,并且编译器相应地生成矢量代码。强烈建议在需要向编译器最佳表达循环逻辑的地方使用#pragma simd及其相关子句。

传统上,内部循环也用于矢量化,但杂注simd也可以用于外部循环的矢量化。有关此方面的更多信息,请访问https://software.intel.com/zh-cn/articles/outer-loop-vectorization