【发布时间】:2016-01-16 12:29:37
【问题描述】:
当使用 GCC 5.2 使用 -std=c99、-O3 和 -mavx2 编译时,
以下代码示例自动矢量化 (assembly here):
#include <stdint.h>
void test(uint32_t *restrict a,
uint32_t *restrict b) {
uint32_t *a_aligned = __builtin_assume_aligned(a, 32);
uint32_t *b_aligned = __builtin_assume_aligned(b, 32);
for (int i = 0; i < (1L << 10); i += 2) {
a_aligned[i] = 42 * b_aligned[i];
a_aligned[i+1] = 3 * a_aligned[i+1];
}
}
但以下代码示例不会自动矢量化 (assembly here):
#include <stdint.h>
void test(uint32_t *restrict a,
uint32_t *restrict b) {
uint32_t *a_aligned = __builtin_assume_aligned(a, 32);
uint32_t *b_aligned = __builtin_assume_aligned(b, 32);
for (int i = 0; i < (1L << 10); i += 2) {
a_aligned[i] = 42 * b_aligned[i];
a_aligned[i+1] = a_aligned[i+1];
}
}
样本之间的唯一区别是a_aligned[i+1] 的比例因子。
GCC 4.8、4.9 和 5.1 也是如此。将volatile 添加到a_aligned 的声明会完全禁止自动矢量化。第一个样本对我们来说始终比第二个运行得快,对于较小的类型(例如 uint8_t 而不是 uint32_t)具有更明显的加速。
有没有办法让第二个代码示例使用 GCC 自动矢量化?
【问题讨论】:
-
所以唯一的区别是缩放因子(3 vs 没有)?尝试明确添加 1 作为比例因子。如果这样可以解决,那就是编译器错误。
-
或者尝试注释掉声明
a_aligned[i+1] = a_aligned[i+1],或者将其重写为a_aligned[i+1] *= 1。编译器可能不知道如何处理您的无操作自赋值,而不是完全按照您说的去做。 -
@Jeff 实际上,唯一的区别是缩放因子。添加显式 1 不会使第二个代码示例自动矢量化 (assembly here)。
-
@DavidHammen 将行注释掉 (assembly here) 并将其重写为复合赋值 (assembly here) 也不起作用。
-
你可以只删除第 2 行,因为它等同于身份。
标签: c performance gcc vectorization c99