如何克服"载体依赖的存在"在icc

时间:2013-07-26 05:12:43

标签: c vectorization simd icc

我想在C中对以下循环进行矢量化:

for(k = 0; k < SysData->numOfClaGen; k++)
            A[k] = B[k] * cos(x1[2 * k] - x1[ind0 + k]);

其中,变量之间没有别名,ind0是常量。其他指针(AB)都没有指向ind0,因此ind0在整个循环中保持不变。

当我用icc编译代码时,它说由于可能的向量依赖性,这个循环不能被矢量化。以下是信息:

loop was not vectorized: existence of vector dependence.

我缩小了问题,发现用一个常数替换ind0可以解决这个问题。所以,我认为icc认为A可能指向ind0,因此ind0可能会发生变化。

我想知道如何帮助编译器知道向量化这样的循环是安全的。

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

在for循环前添加#pragma ivdep,它指示编译器忽略假定的向量依赖性。

#pragma ivdep
for(k = 0; k < SysData->numOfClaGen; k++)
            A[k] = B[k] * cos(x1[2 * k] - x1[ind0 + k]);

有关ivdep的更多信息,请参阅icc doc

答案 1 :(得分:1)

对指针使用restrict修饰符断言编译器没有别名。此关键字是在C99中引入的。 C ++不支持它,但许多C ++编译器支持__restrict作为等效的专有扩展。使用英特尔编译器,必须通过添加命令行标志restrict(Linux)或-restrict(Windows)来启用/Qrestrict。在以下版本的代码中,使用英特尔编译器版本13.1.3.198时,循环将根据需要进行矢量化:

#include <math.h>

struct bar {
    int numOfClaGen;
};

void foo (double * restrict A, 
          const double * restrict B,
          const double * restrict x1,
          const struct bar * restrict SysData,
          const int ind0)
{
    int k;
    for (k = 0; k < SysData->numOfClaGen; k++) {
        A[k] = B[k] * cos(x1[2 * k] - x1[ind0 + k]);
    }
}

按如下方式调用编译器(在64位Windows系统上)

icl /c /Ox /QxHost /Qrestrict /Qvec-report2 vectorize.c

编译报告

vectorize.c(14): (col. 5) remark: LOOP WAS VECTORIZED.

答案 2 :(得分:0)

icc在一年前被更改为将-ansi-alias设置为linux和Mac的默认设置。对于Windows,此默认值无法计入,因为它与Microsoft使用冲突。此选项等同于gcc -fstrict-aliasing,这是自gcc 3.0以来的默认选项。我认为设置此选项要比为这样一个有限的问题设置ivdep restrict或simd要好得多。 虽然没有详细记录,但icc将__restrict视为与gcc相同,并且不需要使用restrict或C99选项来接受它。原则上,它应该只对被修改的对象起作用(上例中的A [])。 奇怪的是,__ restrict对MSVC ++的含义略有不同。它允许非向量优化,否则可能会被可能的依赖性阻止,但不能启用向量化(但它可能适用于当前情况)。