Я пытаюсь создать минимальный репродуктор для этот отчет о проблеме. Кажется, есть некоторые проблемы с AVX-512, который поставляется на последних машинах Apple с процессорами Skylake.
В соответствии с Примечания к выпуску GCC6 AVX-512 должен быть в наличии. Согласно Intel Intrinsics Guide vmovdqu64
доступно с AVX-512VL
а также AVX-512F
:
$ cat test.cxx
#include <cstdint>
#include <immintrin.h>
int main(int argc, char* argv[])
{
uint64_t x[8];
__m512i y = _mm512_loadu_epi64(x);
return 0;
}
А потом:
$ /opt/local/bin/g++-mp-6 -mavx512f -Wa,-q test.cxx -o test.exe
test.cxx: In function 'int main(int, char**)':
test.cxx:6:37: error: '_mm512_loadu_epi64' was not declared in this scope
__m512i y = _mm512_loadu_epi64(x);
^
$ /opt/local/bin/g++-mp-6 -mavx -mavx2 -mavx512f -Wa,-q test.cxx -o test.exe
test.cxx: In function 'int main(int, char**)':
test.cxx:6:37: error: '_mm512_loadu_epi64' was not declared in this scope
__m512i y = _mm512_loadu_epi64(x);
^
$ /opt/local/bin/g++-mp-6 -msse4.1 -msse4.2 -mavx -mavx2 -mavx512f -Wa,-q test.cxx -o test.exe
test.cxx: In function 'int main(int, char**)':
test.cxx:6:37: error: '_mm512_loadu_epi64' was not declared in this scope
__m512i y = _mm512_loadu_epi64(x);
^
Я пошел варианты обратно -msse2
безуспешно. Кажется, я что-то упустил.
Что требуется для включения AVX-512 для современного GCC?
Согласно /opt/local/bin/g++-mp-6 -v
это пути поиска заголовка:
#include "..." search starts here:
#include <...> search starts here:
/opt/local/include/gcc6/c++/
/opt/local/include/gcc6/c++//x86_64-apple-darwin13
/opt/local/include/gcc6/c++//backward
/opt/local/lib/gcc6/gcc/x86_64-apple-darwin13/6.5.0/include
/opt/local/include
/opt/local/lib/gcc6/gcc/x86_64-apple-darwin13/6.5.0/include-fixed
/usr/include
/System/Library/Frameworks
/Library/Frameworks
А потом:
$ grep -R '_mm512_' /opt/local/lib/gcc6/ | grep avx512f | head -n 8
/opt/local/lib/gcc6//gcc/x86_64-apple-darwin13/6.5.0/include/avx512fintrin.h:_mm512_set_epi64 (long long __A, long long __B, long long __C,
/opt/local/lib/gcc6//gcc/x86_64-apple-darwin13/6.5.0/include/avx512fintrin.h:_mm512_set_epi32 (int __A, int __B, int __C, int __D,
/opt/local/lib/gcc6//gcc/x86_64-apple-darwin13/6.5.0/include/avx512fintrin.h:_mm512_set_pd (double __A, double __B, double __C, double __D,
/opt/local/lib/gcc6//gcc/x86_64-apple-darwin13/6.5.0/include/avx512fintrin.h:_mm512_set_ps (float __A, float __B, float __C, float __D,
/opt/local/lib/gcc6//gcc/x86_64-apple-darwin13/6.5.0/include/avx512fintrin.h:#define _mm512_setr_epi64(e0,e1,e2,e3,e4,e5,e6,e7) \
/opt/local/lib/gcc6//gcc/x86_64-apple-darwin13/6.5.0/include/avx512fintrin.h: _mm512_set_epi64(e7,e6,e5,e4,e3,e2,e1,e0)
/opt/local/lib/gcc6//gcc/x86_64-apple-darwin13/6.5.0/include/avx512fintrin.h:#define _mm512_setr_epi32(e0,e1,e2,e3,e4,e5,e6,e7, \
/opt/local/lib/gcc6//gcc/x86_64-apple-darwin13/6.5.0/include/avx512fintrin.h: _mm512_set_epi32(e15,e14,e13,e12,e11,e10,e9,e8,e7,e6,e5,e4,e3,e2,e1,e0)
...
Без маскировки нет никаких оснований для того, чтобы этот внутренний признак существовал или когда-либо использовал его вместо эквивалентного _mm512_loadu_si512
. Это просто сбивает с толку, и может заставить читателей думать, что это vmovq
растягивающая на ноль нагрузка одного epi64
,
Искатель встроенных функций Intel указывает, что он существует, но даже текущий ствол GCC (на Godbolt) не определяет его.
Почти все инструкции AVX512 поддерживают маскирование слиянием и нулевое маскирование. Инструкции, которые раньше были чисто побитовыми / целочисленными, без значимых границ элементов, теперь представлены в 32- и 64-битных вариантах элементов, например vpxord
а также vpxorq
, Или же vmovdqa32
а также vmovdqa64
. Но использование любой версии без маскировки по-прежнему является обычной загрузкой / хранением / регистром-копией вектора, и не имеет смысла указывать для них что-либо о размере элемента в исходном коде C ++ с внутренними компонентами, а только общую ширину вектора.
Смотрите также В чем разница между _mm512_load_epi32 и _mm512_load_si512?
Опции SSE * и AVX1 / 2 не имеют отношения к тому, определяют ли заголовки GCC эту встроенную функцию в терминах встроенных функций gcc или нет; -mavx512f
уже подразумевает все расширения Intel SSE / AVX до AVX512.
Он присутствует в стволе Clang (но не 7.0, поэтому он был добавлен совсем недавно).
_mm512_loadu_si512
— поддерживается везде, используйте это_mm512_loadu_epi64
— лязг ствола, не GCC._mm512_load_si512
— поддерживается везде, используйте это_mm512_load_epi64
— также поддерживается везде, на удивление._mm512_maskz_loadu_epi64
— поддерживается везде, используйте это для нулевых масок_mm512_mask_loadu_epi64
— поддерживается везде, используйте это для загрузки маски слияния.Этот код компилируется в gcc еще в 4.9.0, а mainline (Linux) — в 3.9, оба с -march=avx512f
, Или если они поддерживают это, -march=skylake-avx512
или же -march=knl
, Я не тестировал с Apple Clang.
#include <immintrin.h>
__m512i loadu_si512(void *x) { return _mm512_loadu_si512(x); }
__m512i load_epi64(void *x) { return _mm512_load_epi64(x); }
//__m512i loadu_epi64(void *x) { return _mm512_loadu_epi64(x); }
__m512i loadu_maskz(void *x) { return _mm512_maskz_loadu_epi64(0xf0, x); }
__m512i loadu_mask(void *x) { return _mm512_mask_loadu_epi64(_mm512_setzero_si512(), 0xf0, x); }
Ссылка Годболт; Вы можете раскомментировать _mm512_loadu_epi64
и переверните компилятор, чтобы соединить ствол, чтобы увидеть, как он там работает.
Других решений пока нет …