5

如果我拿这个代码

#include <cmath>

void compute_sqrt(const double* x, double* y, int n) {
  int i;
#pragma omp simd linear(i)
  for (i=0; i<n; ++i) {
    y[i] = std::sqrt(x[i]);
  }
}

并编译g++ -S -c -O3 -fopenmp-simd -march=cascadelake,然后我在循环中得到这样的指令(编译器-资源管理器

...
  vsqrtsd %xmm0, %xmm0, %xmm0
...

XMM 是 128 位寄存器,但 cascadelake 支持 avx-512。有没有办法让 gcc 使用 256 (YMM) 或 512 位 (ZMM) 寄存器?

相比之下,ICC 默认为 cascadelake 使用 256 个寄存器:Compiling with products icc -c -S -O3 -march=cascadelake -qopenmp-simd( compiler-explorer )

...
  vsqrtpd 32(%rdi,%r9,8), %ymm1 #7.12
...

并且您可以添加-qopt-zmm-usage=high使用 512 位寄存器的选项(compiler-explorer

...
  vrsqrt14pd %zmm4, %zmm1 #7.12
...
4

2 回答 2

5

XMM 是 128 位寄存器

更糟糕的是,vsqrtsd它甚至不是矢量运算,如sd末尾所示(标量,双精度)。XMM 寄存器也被像这样的标量浮点运算使用,但只有寄存器的低 64 位或 32 位包含有用数据,其余的被清零。

缺少的选项是-fno-math-errno(此标志也由 隐含-ffast-math,具有附加效果)和(可选)-mprefer-vector-width=512

-fno-math-errno关闭errno数学运算的设置,特别是平方根,这意味着负输入会导致 NaN而不设置errnoEDOM. 默认情况下,ICC 显然不关心这一点。

-mprefer-vector-width=512使自动向量化在有意义时更喜欢 512 位操作。默认情况下,首选 256 位操作,至少对于cascadelakeskylake-avx512其他当前处理器而言,它可能不会在所有未来的处理器中保持这种状态。

于 2020-08-23T00:26:59.380 回答
1

如果添加-ffast-math标志,gcc 将使用 YMM 寄存器,例如:

vsqrtpd (%rdi,%rax), %ymm0
vmovupd %ymm0, (%rcx,%rax)

演示

于 2020-08-23T00:20:24.560 回答