你如何矢量化一个循环?
How do you vectorise a loop?
我在矢量化循环时遇到问题。我希望重写下面的代码,使其矢量化。我有 运行 完成 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-skylake
(try on Godbolt) 成功矢量化,使用 ymm 寄存器每次迭代处理 8 int
s。它还完全展开循环,因为迭代计数是恒定的并且不会太大。
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];
}
}
我在矢量化循环时遇到问题。我希望重写下面的代码,使其矢量化。我有 运行 完成 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-skylake
(try on Godbolt) 成功矢量化,使用 ymm 寄存器每次迭代处理 8 int
s。它还完全展开循环,因为迭代计数是恒定的并且不会太大。
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];
}
}