【发布时间】:2020-12-11 23:34:29
【问题描述】:
如果我接受此代码
#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 编译,然后我在循环中得到这样的指令 (compiler-explorer)
...
vsqrtsd %xmm0, %xmm0, %xmm0
...
XMM 是 128 位寄存器,但 cascadelake 支持 avx-512。有没有办法让 gcc 使用 256 (YMM) 或 512 位 (ZMM) 寄存器?
相比之下,ICC 默认为 cascadelake 使用 256 个寄存器:使用 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
...
【问题讨论】:
-
请注意,
vrsqrt14pd是一个快速近似倒数,是 sqrt 近似的一部分,如果这就是你在循环中所做的所有事情(就像你的代码),它会更快。在现实生活中,将 sqrt 作为其他计算的一部分,这样它就可以与其他处于活动状态的 ALU 重叠。
标签: c++ gcc x86 icc auto-vectorization