ошибка: «_mm512_loadu_epi64» не было объявлено в этой области

Я пытаюсь создать минимальный репродуктор для этот отчет о проблеме. Кажется, есть некоторые проблемы с 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)
...

0

Решение

Без маскировки нет никаких оснований для того, чтобы этот внутренний признак существовал или когда-либо использовал его вместо эквивалентного _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 и переверните компилятор, чтобы соединить ствол, чтобы увидеть, как он там работает.

2

Другие решения

Других решений пока нет …