C++ pragmas simd和ivdep向量之间的差异是否始终存在?

C++ pragmas simd和ivdep向量之间的差异是否始终存在?,c++,vectorization,pragma,icc,C++,Vectorization,Pragma,Icc,我目前正在尝试矢量化一个程序,我观察到一个奇怪的行为 使用时,for循环似乎是矢量化的 #布拉格语 (262):(第3列)备注:SIMD循环已矢量化 但当我使用 #pragma向量始终 #布拉格马伊夫代普 (262):(第3列)备注:循环未矢量化:存在矢量依赖性 我一直认为这两个句子做相同的向量化pragma simd强制循环的向量化,不管成本或安全性如何 pragma向量总是告诉编译器在决定是否进行向量化时忽略效率启发式。仅在添加此杂注时进行矢量化的代码可能会较慢 pragma ivdep告诉

我目前正在尝试矢量化一个程序,我观察到一个奇怪的行为

使用时,for循环似乎是矢量化的

#布拉格语

(262):(第3列)备注:SIMD循环已矢量化

但当我使用

#pragma向量始终

#布拉格马伊夫代普

(262):(第3列)备注:循环未矢量化:存在矢量依赖性


我一直认为这两个句子做相同的向量化

pragma simd强制循环的向量化,不管成本或安全性如何

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

pragma ivdep告诉编译器忽略阻止矢量化的假定数据依赖(例如循环携带的依赖),但不忽略已验证的依赖。例如,它可能会假设指向指针的内存和向量不相同。然而,它不会忽略一个经过验证的循环携带依赖(a[i]=a[i-1]*c),但pragma simd可能会忽略

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

来源:英特尔专用pragmas documentation()

#pragma simd
是提供给开发人员的一种显式矢量化工具,用于执行中提到的矢量化,而
#pragma vector
是一种用于指示编译器应根据其参数对循环进行矢量化的工具。这里的参数是
始终
,这意味着“忽略编译器的成本/效率启发,继续矢量化”。有关
#pragma vector
的更多信息,请访问。这并不意味着
#pragma simd
会产生错误的结果。它成功地将
#pragma vector始终
无法矢量化的循环矢量化。当
#pragma simd
与正确的子句集一起使用时,它可以矢量化,并且仍然生成正确的结果

下面是一个小代码段,它演示了:

void foo(浮点*a、浮点*b、浮点*c、整数N){ #pragma向量始终 #布拉格马伊夫代普 //#pragma simd矢量长度(2) for(int i=2;i 使用ICC编译此代码将生成以下矢量化报告:

$ icc -c -vec-report2 test11.cc
test11.cc(5): (col. 1) remark: loop was not vectorized: existence of vector dependence
默认情况下,ICC以使用128位XMM寄存器的SSE2为目标。一个XMM寄存器中可以容纳4个浮点,但当您尝试容纳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
void foo(浮点*a、浮点*b、浮点*c、整数N){
//#pragma向量始终
//#布拉格马伊夫代普
#pragma simd矢量长度(2)
for(int i=2;i
<>但<代码>α-语用向量没有一个子句可以明确地指定向量长度,同时对循环进行矢量化。这就是
#pragma simd
真正派上用场的地方

当与以向量方式最好地解释计算的正确子句一起使用时,编译器将生成不会生成错误结果的请求向量。在上发布的英特尔(R)Cilk(TM)Plus白皮书中有一节介绍了“使用$pragma simd vectorlength子句”和“使用$pragma simd reduction和private子句”,其中解释了如何使用正确的子句来使用pragma simd子句。这些子句帮助开发人员向编译器表达他想要实现的内容,编译器相应地生成向量代码。强烈建议在需要时使用带有相关子句的#pragma simd,以最好地向编译器表达循环逻辑

传统上,内循环也是矢量化的目标,但pragma simd也可用于外循环的矢量化。有关这方面的更多信息,请访问