error: '_mm512_loadu_epi64' was not declared in this scope

error: '_mm512_loadu_epi64' was not declared in this scope

我正在尝试为 this issue report 创建一个最小的复制器。 AVX-512 似乎有一些问题,它正在配备 Skylake 处理器的最新 Apple 机器上发货。

根据 GCC6 release notes the AVX-512 gear should be available. According to the Intel Intrinsics Guide vmovdqu64 可用于 AVX-512VLAVX-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 但没有成功。我好像漏掉了什么。

为现代 GCC 使用 AVX-512 需要什么?


根据 /opt/local/bin/g++-mp-6 -v,这些是 header 搜索路径:

#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。它只是令人困惑,并且可能会欺骗人类读者认为它是单个 epi64.

vmovq zero-extending 负载

Intel's intrinsics finder does specify that it exists,但即使是当前的主干 gcc(在 Godbolt 上)也没有定义它。

几乎所有的AVX512指令都支持merge-masking和zero-masking。过去纯按位/whole-register 没有有意义的元素边界的指令现在有 32 位和 64 位元素风格,如 vpxordvpxorq。或者 vmovdqa32 and vmovdqa64。但是使用任何一个没有屏蔽的版本仍然只是一个普通的向量加载/存储/register-copy,并且在带有内在函数的 C++ 源代码中为它们指定任何关于 element-size 的内容是没有意义的,只有总矢量宽度。

另见 What is the difference between _mm512_load_epi32 and _mm512_load_si512?


SSE* 和 AVX1/2 选项与 GCC headers 是否根据 gcc built-ins 定义此内在函数无关; -mavx512f 已经暗示了 AVX512 之前的所有英特尔 SSE/AVX 扩展。


它存在于 clang trunk 中(但不是 7.0,所以它是最近才添加的)。

  • 未对齐 _mm512_loadu_si512 - 到处都支持,使用这个
  • 未对齐 _mm512_loadu_epi64 - clang trunk,不是 gcc。
  • 对齐 _mm512_load_si512 - 到处都支持,使用这个
  • 对齐 _mm512_load_epi64 - 令人惊讶的是,到处都支持。
  • 未对齐 _mm512_maskz_loadu_epi64 - 到处都支持,将其用于 zero-masked 加载
  • 未对齐 _mm512_mask_loadu_epi64 - 到处都支持,将其用于 merge-mask 负载。

这段代码早在 4.9.0 就可以在 gcc 上编译,主线 (Linux) clang 早在 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); }

Godbolt link;您可以取消注释 _mm512_loadu_epi64 并将编译器翻转到 clang trunk 以查看它在那里工作。

_mm512_loadu_epi64 在 32 位模式下不可用。您需要针对 64 位模式进行编译。一般来说,AVX512 在 64 位模式下效果最好。