如果我使用这段代码
#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位寄存器,但Cascade Lake支持AVX-512。有没有办法让GCC使用256位(YMM)或512位(ZMM)寄存器?
与之相比,ICC默认使用256个寄存器用于Cascade Lake:使用icc -c -S -O3 -march=cascadelake -qopenmp-simd
编译会产生(Compiler Explorer)。
...
vsqrtpd 32(%rdi,%r9,8), %ymm1 #7.12
...
你可以添加选项-qopt-zmm-usage=high
以使用512位寄存器(编译器浏览器)
...
vrsqrt14pd %zmm4, %zmm1 #7.12
...
vrsqrt14pd
是一种快速的近似倒数,是sqrt的近似值的一部分,如果您在循环中只执行这个操作(就像您的代码一样),那么它会更快。在实际应用中,请将sqrt作为其他计算的一部分来执行,以便它可以与其他活动的ALU重叠。 - Peter Cordes