0

我想在 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可能会改变。

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

在此先感谢您的帮助。

4

3 回答 3

2

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

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

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

于 2013-07-27T09:54:16.393 回答
1

使用restrict指针修饰符向编译器断言没有别名。这个关键字是在 C99 中引入的。C++ 不支持它,但许多 C++ 编译器支持__restrict作为等效的专有扩展。restrict使用英特尔编译器,必须通过添加命令行标志-restrict(Linux) 或/Qrestrict(Windows)来启用使用。在您的代码的以下版本中,当使用英特尔编译器版本 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.
于 2013-07-28T03:13:30.433 回答
0

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

于 2015-05-25T13:52:31.413 回答