您如何向量化循环?

问题描述

我无法对循环进行矢量化处理。我正在寻找重写下面的代码,使其向量化。我已经运行了完整的Banerjee测试,发现所有依赖项都已损坏,但我不知道从哪里去。 编译器是gcc。体系结构是x86,数组是整数数组。

for (int i = 0; i < 100; i++) { 
     x[20 + i] = y[i] * z[i];
     p[i] = x[21 + i] + q[i];
}

解决方法

两个一般提示:

  • 使用restrict关键字将数组作为参数传递给函数,以通知编译器它们不能互相别名(这将阻止任何向量化)。

  • 尽管循环第二行对x的读取并不取决于第一行的写入,但是编译器可能不够聪明,无法检测到这一点。通过交换这两行或在写入之前将读取移到其自己的循环中来帮助解决问题。

以下版本已由gcc 10.2使用-O3 -march-skylaketry on Godbolt)成功矢量化,使用ymm寄存器每次迭代处理8个int。由于迭代次数恒定且不会太大,因此它也可以完全展开循环。

void foo(
            int *restrict x,const int *restrict y,const int *restrict z,int *restrict p,const int *restrict q
        ) {
    for (int i = 0; i < 100; i++) { 
        p[i] = x[21 + i] + q[i];
        x[20 + i] = y[i] * z[i];
    }
}