Cle*_*vic 5 c++ gcc makefile simd avx
我正在尝试在一些文件上实现和编码,其中一些包含 SIMD 调用。我已经在服务器上编译了这段代码,运行与我的机器基本相同的操作系统,但我无法编译它。
\n\n这是错误:
\n\nmake\ng++ main.cpp -march=native -o main -fopenmp\nIn file included from /usr/lib/gcc/x86_64-linux-gnu/7/include/immintrin.h:53:0,\n from tensor.hpp:9,\n from main.cpp:4:\n/usr/lib/gcc/x86_64-linux-gnu/7/include/avx512vlintrin.h: In function \xe2\x80\x98_ZN6TensorIdE8add_avx2ERKS0_._omp_fn.5\xe2\x80\x99:\n/usr/lib/gcc/x86_64-linux-gnu/7/include/avx512vlintrin.h:447:1: error: inlining failed in call to always_inline \xe2\x80\x98__m256d _mm256_mask_add_pd(__m256d, __mmask8, __m256d, __m256d)\xe2\x80\x99: target specific option mismatch\n _mm256_mask_add_pd (__m256d __W, __mmask8 __U, __m256d __A,\n ^~~~~~~~~~~~~~~~~~\nIn file included from main.cpp:4:0:\ntensor.hpp:228:33: note: called from here\n res = _mm256_mask_add_pd(tmp, 0xFF, _mm256_mask_loadu_pd(tmp, 0xFF, &elements[i]), _mm256_mask_loadu_pd(tmp, 0xFF, &a.elements[i]));\n ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nIn file included from /usr/lib/gcc/x86_64-linux-gnu/7/include/immintrin.h:53:0,\n from tensor.hpp:9,\n from main.cpp:4:\n/usr/lib/gcc/x86_64-linux-gnu/7/include/avx512vlintrin.h:610:1: error: inlining failed in call to always_inline \xe2\x80\x98__m256d _mm256_mask_loadu_pd(__m256d, __mmask8, const void*)\xe2\x80\x99: target specific option mismatch\n _mm256_mask_loadu_pd (__m256d __W, __mmask8 __U, void const *__P)\n ^~~~~~~~~~~~~~~~~~~~\nIn file included from main.cpp:4:0:\ntensor.hpp:228:33: note: called from here\n res = _mm256_mask_add_pd(tmp, 0xFF, _mm256_mask_loadu_pd(tmp, 0xFF, &elements[i]), _mm256_mask_loadu_pd(tmp, 0xFF, &a.elements[i]));\n ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nIn file included from /usr/lib/gcc/x86_64-linux-gnu/7/include/immintrin.h:53:0,\n from tensor.hpp:9,\n from main.cpp:4:\n/usr/lib/gcc/x86_64-linux-gnu/7/include/avx512vlintrin.h:610:1: error: inlining failed in call to always_inline \xe2\x80\x98__m256d _mm256_mask_loadu_pd(__m256d, __mmask8, const void*)\xe2\x80\x99: target specific option mismatch\n _mm256_mask_loadu_pd (__m256d __W, __mmask8 __U, void const *__P)\n ^~~~~~~~~~~~~~~~~~~~\nIn file included from main.cpp:4:0:\ntensor.hpp:228:33: note: called from here\n res = _mm256_mask_add_pd(tmp, 0xFF, _mm256_mask_loadu_pd(tmp, 0xFF, &elements[i]), _mm256_mask_loadu_pd(tmp, 0xFF, &a.elements[i]));\n ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nMakefile:7: recipe for target 'main' failed\nmake: *** [main] Error 1\n\nRun Code Online (Sandbox Code Playgroud)\n\n谷歌搜索这个问题并没有真正帮助,因为所有答案都指出了这一点,我已经准备好了/尝试过。
\n\n有人可以提供一些背景来解释为什么它不起作用。
\n\n编辑:
\n\nint main(){\n#ifdef __AVX512F___\n auto tt = createTensor();\n auto tt2 = createTensor();\n auto res = tt.addAVX512(tt2);\n#endif\n}\n\n//This is in tensor.hpp\n#ifdef __AVX512F__\nTensor<T> Tensor::addAVX512(_param_){\n res = _mm256_mask_add_pd(tmp, 0xFF, _mm256_mask_loadu_pd(tmp, 0xFF, &elements[i]), _mm256_mask_loadu_pd(tmp, 0xFF, &a.elements[i]));\n}\n#endif\nRun Code Online (Sandbox Code Playgroud)\n\n这就是发生的事情的要点...我已将所有 SIMDcalls 封装在 #ifdefs 等中。
\nGCC 只允许您使用可供编译器使用的指令集的内在函数。例如,有关 AVX1 内在函数的相关问题:内联在调用always_inline '__m256d _mm256_broadcast_sd(const double*)' 时失败
这些是_mask_256 位内在函数的版本,它们需要 AVX512VL。
(我在这个问题下的评论-mavx是错误的,我没有注意到_mask名称或参数中的 ,只是注意到_mm256。)
您可能在服务器上的 KNL(Knight's Landing / Xeon Phi)上进行编译,该服务器具有 AVX512F 但没有 AVX512VL。如此便-march=native定-mavx512f。(与 Skylake-AVX512 不同,Skylake-AVX512 确实具有 AVX512VL,允许使用很酷的新 AVX512 内容,例如具有更窄向量的屏蔽指令。)
并且您在 中发现了一个错误tensor.hpp,您在仅检查__AVX512F__而不是 后使用 AVX512VL 内在函数__AVX512VL__。 AVX512-anything 意味着 512F,因此不需要同时检查两者。
#ifdef __AVX512F__ // should be __AVX512VL__
Tensor<T> Tensor::addAVX512(_param_){
res = _mm256_mask_add_pd(tmp, 0xFF, _mm256_mask_loadu_pd(tmp, 0xFF, &elements[i]), _mm256_mask_loadu_pd(tmp, 0xFF, &a.elements[i]));
}
#endif
Run Code Online (Sandbox Code Playgroud)
这是毫无意义的,如果您要使用常量全一掩码,则不需要使用这些内在函数的掩码版本。_mm256_add_pd像正常人一样使用,只检查__AVX__. 或者使用_mm512_add_pd.
我一开始以为这是来自 TensorFlow,但是(从你的评论来看)这是没有意义的。而且不可能写得那么糟糕。 使用全真掩码将掩码合并为 3 个相同的副本tmp是没有意义的;如果编译器无法将 mask=all-ones 优化为未屏蔽的加载,那么引入错误依赖项看起来是一种愚蠢的方法。
还有可怕的 C++ 风格:你有一个称为__m256d tmp全局或类成员的变量?它甚至不是本地虚拟变量,它可能存在于编译器无法完全优化它的地方。