#c #gcc #x86 #icc #auto-vectorization
#c #gcc #x86 #icc #автоматическая векторизация
Вопрос:
Если я возьму этот код
#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 по умолчанию использует 256 регистров для cascadelake: компиляция с 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
...
Комментарии:
1. Обратите внимание, что
vrsqrt14pd
это быстрое приблизительное обратное, часть приближения к sqrt, которое выполняется быстрее, если это все, что вы делаете в цикле (например, ваш код). В реальной жизни выполняйте sqrt как часть какого-либо другого вычисления, чтобы оно могло перекрываться с другими активными ALU.
Ответ №1:
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
and skylake-avx512
и других текущих процессоров, вероятно, так не останется для всех будущих процессоров.
Комментарии:
1. ICC по умолчанию имеет значение
-fp-model fast=1
, что-то вроде gcc / clang-ffast-math
, включая, я думаю, обработку FP math как ассоциативной. Так что да, ICC наплевать на настройкуerrno
по умолчанию! производительность icc main.cpp == g -ffast-math main.cpp . Вот почему OP видит это с помощьюvrsqrt14pd
, быстрой приблизительной обратной связи.
Ответ №2:
Если вы добавите -ffast-math
флаг, gcc будет использовать регистры YMM, например:
vsqrtpd (%rdi,%rax), %ymm0
vmovupd %ymm0, (%rcx,%rax)