rni*_*ckb 5 c++ x86 gcc icc auto-vectorization
如果我接受这个代码
#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]);
}
}
Run Code Online (Sandbox Code Playgroud)
并使用 进行编译g++ -S -c -O3 -fopenmp-simd -march=cascadelake,然后我在循环中得到这样的指令(编译器-资源管理器)
...
vsqrtsd %xmm0, %xmm0, %xmm0
...
Run Code Online (Sandbox Code Playgroud)
XMM 是 128 位寄存器,但 Cascadelake 支持 avx-512。有没有办法让 gcc 使用 256 (YMM) 或 512 位 (ZMM) 寄存器?
相比之下,ICC 默认使用 256 个寄存器进行 Cascadelake:使用icc -c -S -O3 -march=cascadelake -qopenmp-simdProduces 进行编译 ( compiler-explorer )
...
vsqrtpd 32(%rdi,%r9,8), %ymm1 #7.12
...
Run Code Online (Sandbox Code Playgroud)
-qopt-zmm-usage=high并且您可以添加使用 512 位寄存器的选项(编译器-资源管理器)
...
vrsqrt14pd %zmm4, %zmm1 #7.12
...
Run Code Online (Sandbox Code Playgroud)
XMM 是 128 位寄存器
更糟糕的是,它vsqrtsd甚至不是向量运算,如sd末尾所示(标量,双精度)。XMM 寄存器也可用于标量浮点运算,但只有寄存器的低 64 或 32 位包含有用数据,其余部分被清零。
缺少的选项是-fno-math-errno(此标志也由 暗示-ffast-math,它具有附加效果)和(可选)-mprefer-vector-width=512。
-fno-math-errno关闭errno数学运算的设置,特别是对于平方根,这意味着负输入会导致 NaN而不设置errno为EDOM。ICC默认情况下显然并不关心这一点。
-mprefer-vector-width=512使自动向量化在有意义时更喜欢 512 位操作。默认情况下,256 位操作是首选,至少对于当前的其他处理器cascadelake而言是skylake-avx512这样,但对于所有未来的处理器来说,它可能不会保持这种状态。