我试图对我的对齐函数的内部循环进行矢量化,但遇到了一个我不明白的问题。当比较输入数组中连续的两个元素时,循环不会向量化,但当被比较的元素偏移 2 时,它会成功向量化。一个最小的例子:
int *vec_test(int *input) {
int i, n1, n2;
int *out = (int *) malloc(100 * sizeof(int));
// This loop fails to vectorize
for(i=1;i<100;i++) {
n1 = input[i-1];
n2 = input[i];
out[i] = n1 > n2 ? n1 : n2;
}
// This loop successfully vectorizes
for(i=1;i<100;i++) {
n1 = input[i-1];
n2 = input[i+1];
out[i] = n1 > n2 ? n1 : n2;
}
return(out);
}
当我使用 clang 编译此代码 (clang++ -O2 -Rpass=loop-vectorize -Rpass-analysis=loop-vectorize -c minimal.cpp) 时,第二个循环矢量化,但第一个循环不矢量化。
minimal.cpp:17:17: remark: loop not vectorized: value that could not be identified as reduction is used outside the loop
minimal.cpp:23:3: remark: vectorized loop (vectorization factor: 4, unrolling interleave factor: 1) [-Rpass=loop-vectorize]
唯一的区别是被比较的元素在第一个循环中是连续的,而在第二个循环中偏移 2。为什么第一个循环无法矢量化?
编辑:用不同的宽度类型(int64_t、int32_t 或 int16_t)替换 int 在所有情况下都会产生相同的结果:底部循环向量化,顶部循环无法这样做。
最佳答案
这个失败看起来像是 clang ~3.8 中的一个错误,已被 3.9.0 解决。
$ clang++ -O2 -Rpass=loop-vectorize -Rpass-analysis=loop-vectorize -c minimal.cpp
minimal.cpp:8:3: remark: the cost-model indicates that interleaving is not beneficial [-Rpass-analysis=loop-vectorize]
for(i=1;i<100;i++) {
^
minimal.cpp:8:3: remark: vectorized loop (vectorization width: 4, interleaved count: 1) [-Rpass=loop-vectorize]
minimal.cpp:15:3: remark: the cost-model indicates that interleaving is not beneficial [-Rpass-analysis=loop-vectorize]
for(i=1;i<100;i++) {
^
minimal.cpp:15:3: remark: vectorized loop (vectorization width: 4, interleaved count: 1) [-Rpass=loop-vectorize]
$ clang++ --version
clang version 3.9.0 (tags/RELEASE_390/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /opt/clang-latest/bin
关于比较顺序数组元素时,Clang 无法矢量化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33489964/