错误:内联调用 always_inline 失败

Posted

技术标签:

【中文标题】错误:内联调用 always_inline 失败【英文标题】:error: inlining failed to call always_inline 【发布时间】:2019-02-12 16:11:41 【问题描述】:

我正在尝试在一些文件上实现和编码,其中一些包含 SIMD 调用。我已经在服务器上编译了这段代码,运行与我的机器基本相同的操作系统,但我无法编译它。

这是错误:

make
g++ main.cpp -march=native -o main -fopenmp
In file included from /usr/lib/gcc/x86_64-linux-gnu/7/include/immintrin.h:53:0,
                 from tensor.hpp:9,
                 from main.cpp:4:
/usr/lib/gcc/x86_64-linux-gnu/7/include/avx512vlintrin.h: In function ‘_ZN6TensorIdE8add_avx2ERKS0_._omp_fn.5’:
/usr/lib/gcc/x86_64-linux-gnu/7/include/avx512vlintrin.h:447:1: error: inlining failed in call to always_inline ‘__m256d _mm256_mask_add_pd(__m256d, __mmask8, __m256d, __m256d)’: target specific option mismatch
 _mm256_mask_add_pd (__m256d __W, __mmask8 __U, __m256d __A,
 ^~~~~~~~~~~~~~~~~~
In file included from main.cpp:4:0:
tensor.hpp:228:33: note: called from here
         res = _mm256_mask_add_pd(tmp, 0xFF, _mm256_mask_loadu_pd(tmp, 0xFF, &elements[i]), _mm256_mask_loadu_pd(tmp, 0xFF, &a.elements[i]));
               ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/lib/gcc/x86_64-linux-gnu/7/include/immintrin.h:53:0,
                 from tensor.hpp:9,
                 from main.cpp:4:
/usr/lib/gcc/x86_64-linux-gnu/7/include/avx512vlintrin.h:610:1: error: inlining failed in call to always_inline ‘__m256d _mm256_mask_loadu_pd(__m256d, __mmask8, const void*)’: target specific option mismatch
 _mm256_mask_loadu_pd (__m256d __W, __mmask8 __U, void const *__P)
 ^~~~~~~~~~~~~~~~~~~~
In file included from main.cpp:4:0:
tensor.hpp:228:33: note: called from here
         res = _mm256_mask_add_pd(tmp, 0xFF, _mm256_mask_loadu_pd(tmp, 0xFF, &elements[i]), _mm256_mask_loadu_pd(tmp, 0xFF, &a.elements[i]));
               ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/lib/gcc/x86_64-linux-gnu/7/include/immintrin.h:53:0,
                 from tensor.hpp:9,
                 from main.cpp:4:
/usr/lib/gcc/x86_64-linux-gnu/7/include/avx512vlintrin.h:610:1: error: inlining failed in call to always_inline ‘__m256d _mm256_mask_loadu_pd(__m256d, __mmask8, const void*)’: target specific option mismatch
 _mm256_mask_loadu_pd (__m256d __W, __mmask8 __U, void const *__P)
 ^~~~~~~~~~~~~~~~~~~~
In file included from main.cpp:4:0:
tensor.hpp:228:33: note: called from here
         res = _mm256_mask_add_pd(tmp, 0xFF, _mm256_mask_loadu_pd(tmp, 0xFF, &elements[i]), _mm256_mask_loadu_pd(tmp, 0xFF, &a.elements[i]));
               ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Makefile:7: recipe for target 'main' failed
make: *** [main] Error 1

谷歌搜索问题并没有真正帮助,因为所有答案都指出了事情,我已经这样做/尝试过。

有人可以提供一些背景说明为什么它不起作用。

编辑:

int main()
#ifdef __AVX512F___
    auto tt = createTensor();
    auto tt2 = createTensor();
    auto res = tt.addAVX512(tt2);
#endif


//This is in tensor.hpp
#ifdef __AVX512F__
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

这是发生的事情的要点......我已将所有 SIMDcall 包含在 #ifdefs 等中。

【问题讨论】:

@bruno 这个问题是关于cmake的。 这也是关于 C,而不是 C++。 @Barmar:这是关于在使用 SSE4.1 内部函数编译代码时省略 -msse4.1。或者在这种情况下,在编译 AVX 内部函数时忽略 -mavx-march=haswell @bruno 不,我已经找到了,但它没有帮助 @bruno:如果 OP 没有使用 -march=native,inlining failed in call to always_inline '__m256d _mm256_broadcast_sd(const double*)' 将完全重复:-mavx 是这些内在函数的相关选项。但是对于这种情况,它只会让 OP 制作一个他们无法运行的二进制文件。要么他们的服务器太旧了,要么它使用了无法为客人启用 AVX 的糟糕虚拟化,或者它运行在 Pentium / Celeron CPU 上(甚至 Skylake Pentium 也禁用了 AVX,大概是为了他们可以销售具有高 128 位缺陷的芯片FMA u 【参考方案1】:

GCC 只允许您将内在函数用于编译器启用的指令集。例如关于 AVX1 内在函数的相关问题:inlining failed in call to always_inline '__m256d _mm256_broadcast_sd(const double*)'


这些是 256 位内部函数的 _mask_ 版本,它们需要 AVX512VL。

(关于-mavx的问题我的cmets是错误的,我没有注意到名称或参数中的_mask,只是_mm256。)

您可能正在服务器上的 KNL(Knight's Landing / Xeon Phi)上编译,该服务器具有 AVX512F 但没有 AVX512VL。所以-march=native 将设置-mavx512f。 (与具有 AVX512VL 的 Skylake-AVX512 不同,它允许使用很酷的新 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

这毫无意义,如果您要使用常量全为掩码,则不需要使用这些内在函数的掩码版本。像普通人一样使用_mm256_add_pd,只检查__AVX__。或者使用_mm512_add_pd

起初我以为这是来自 TensorFlow,但是(来自您的 cmets)这没有意义。而且不能写得那么差。 使用全真掩码将同一tmp 合并为 3 个副本是没有意义的;如果编译器无法将 mask=all-ones 优化为未屏蔽的负载,那么引入虚假依赖项似乎是一种愚蠢的方式。

还有糟糕的 C++ 风格:你有一个名为 __m256d tmp 的变量作为全局或类成员?它甚至不是本地虚拟变量,它可能存在于编译器无法完全优化掉的地方。

【讨论】:

谢谢,看来我在 AVX2 块中使用了 AVX512-Instructions,我对此进行了研究……但这解决了它(将它们注释掉,因为我现在的主要关注点在其他地方)跨度> @CleboSevic:查看我的更新:您引用的来自 tensor.hpp 的块无缘无故地使用了掩码的内在函数。 实际上我的代码 sn-p 有点错误。函数调用不在 AVX512-Block 中,而是在 AVX2-Block 中,这从来没有真正引起过麻烦,因为之前的服务器是 skylake CPU ......无论如何,必须寻找相当于添加的 AVX2,到让它再次运行,但无论如何谢谢 :thumbs_up: @CleboSevic:我已经在回答中建议您使用 AVX1 _mm256_add_pd / _mm256_loadu_pd,只需删除 _mask 部分。掩蔽是 AVX512 的一项新功能。但总的来说,请参阅 Intel 的内在函数查找器:software.intel.com/sites/landingpage/IntrinsicsGuide

以上是关于错误:内联调用 always_inline 失败的主要内容,如果未能解决你的问题,请参考以下文章

调用 always_inline '_mm256_add_epi32' 时内联失败:目标特定选项不匹配 [重复]

调用 always_inline '__m128i _mm_cvtepu8_epi32(__m128i)' 时内联失败:目标特定选项不匹配 _mm_cvtepu8_epi32 (__m128i __X

g ++ inlined在调用always_inline“int _rdrand16_step()”时失败

强制函数在Clang / LLVM中内联

内联汇编,错误

Angular 11字体内联失败