错误:未在此范围内声明“ _mm512_loadu_epi64”

时间:2018-12-04 02:47:02

标签: c++ gcc x86 intrinsics avx512

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

根据GCC6 release notes,AVX-512齿轮应可用。根据{{​​3}},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。我似乎丢失了一些东西。

将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)
...

2 个答案:

答案 0 :(得分:2)

没有任何屏蔽,没有任何理由要使用此内在函数或使用它代替等效的_mm512_loadu_si512 。这只是令人困惑,并且可能使人类读者误以为这是单个vmovq的{​​{1}}零扩展负载。

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

几乎所有的AVX512指令都支持合并屏蔽和零屏蔽。过去纯粹是按位/完整寄存器的指令,现在没有有意义的元素边界,现在有32位和64位元素风格,例如epi64vpxord。或vmovdqa32 and vmovdqa64。但是使用没有屏蔽的任何版本仍然只是正常的向量加载/存储/寄存器复制,并且在带有内在函数的C ++源代码中为它们指定元素大小的任何内容(仅包含向量的总宽度)是没有意义的。

另请参阅What is the difference between _mm512_load_epi32 and _mm512_load_si512?


SSE *和AVX1 / 2选项与GCC标头是否根据gcc内置定义此内在函数无关。 vpxorq已经暗示了AVX512之前的所有Intel SSE / AVX扩展。


它存在于Clang干线中(但不存在7.0,因此它是最近才添加的。)

  • 未对齐的-mavx512f-各地都受支持,请使用此
  • 未对齐的_mm512_loadu_si512-lang声,而不是gcc。
  • 对齐的_mm512_loadu_epi64-各地都受支持,请使用此
  • 对齐的_mm512_load_si512-令人惊讶的是,它也得到了各地的支持。
  • 未对齐的_mm512_load_epi64-各处均受支持,可将其用于零屏蔽载荷
  • 未对齐的_mm512_maskz_loadu_epi64-各处均受支持,可将其用于合并掩码加载。

此代码最早在gcc上编译为4.9.0,而主线(Linux)早期为3.9,都使用_mm512_mask_loadu_epi64进行编译。或者,如果他们支持-march=avx512f-march=skylake-avx512。我尚未使用Apple Clang进行测试。

-march=knl

Godbolt link;您可以取消对#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); } 的注释,然后将编译器翻转到Clang干线,以查看它在那儿工作。

答案 1 :(得分:0)

_mm512_loadu_epi64在32位模式下不可用。您需要针对64位模式进行编译。通常,AVX512在64位模式下效果最佳。