如何使用GCC自动矢量化跨步写入?

T. *_*ner 6 c performance gcc c99 vectorization

当使用-std=c99,-O3和编译GCC 5.2时,-mavx2以下代码示例自动向量化(此处为程序集):

#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];
  }
}
Run Code Online (Sandbox Code Playgroud)

但是以下代码示例不会自动向量化(此处为程序集):

#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];
  }
}
Run Code Online (Sandbox Code Playgroud)

样本之间的唯一区别是缩放因子a_aligned[i+1].

GCC 4.8,4.9和5.1也是如此.添加volatile到a_aligned声明会完全禁止自动矢量化.对于我们来说,第一个样本的运行速度始终高于第二个样本,对于较小的类型(例如uint8_t代替uint32_t),速度更快.

有没有办法让第二个代码示例使用GCC自动向量化?

Gil*_*les 1

下面的版本是矢量化的,但如果你问我的话,那就很丑了......

#include <stdint.h>

void test(uint32_t *a, uint32_t *aa,
          uint32_t *restrict b) {
  #pragma omp simd aligned(a,aa,b:32)
  for (int i = 0; i < (1L << 10); i += 2) {
    a[i] = 2 * b[i];
    a[i+1] = aa[i+1];
  }
}
Run Code Online (Sandbox Code Playgroud)

使用 进行编译-fopenmp和调用test(a, a, b)。