Ошибка: "_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)
...

1 ответ

Решение

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

_mm512_loadu_epi64 is not available in 32-bit mode. You need to compile for 64-bit mode. In general, AVX512 works best in 64-bit mode.

Другие вопросы по тегам