error: inlining failed to call always_inline
error: inlining failed to call always_inline
我正在尝试在一些文件上实施和编码,其中一些文件包含 SIMD 调用。我在服务器上编译了这段代码,运行 与我的机器基本相同OS,但我无法编译它。
这是错误:
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
谷歌搜索问题并没有真正帮助,因为所有答案都指出了问题,我已经准备好 do/tried。
有人可以提供一些关于它为什么不起作用的背景信息吗?
编辑:
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
这就是发生的事情的要点......我已经将所有 SIMDcalls 封装在 #ifdefs 等中。
GCC 将只允许您将内部函数用于允许编译器使用的指令集。例如关于 AVX1 intrinsic 的相关问题:inlining failed in call to always_inline '__m256d _mm256_broadcast_sd(const double*)'
这些是 256 位内部函数的 _mask_
版本,它们需要 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
这毫无意义,如果您要使用常量全一掩码,则不需要使用这些内在函数的掩码版本。像正常人一样使用 _mm256_add_pd
,只检查 __AVX__
。或者使用 _mm512_add_pd
.
起初我以为这是来自 TensorFlow,但(根据您的评论)这没有意义。它不可能写得那么糟糕。 使用完全真实的掩码将相同的 tmp
合并到 3 个副本中是没有意义的;如果编译器无法将 mask=all-ones 优化为未屏蔽的负载,那么引入错误依赖的方式看起来很愚蠢。
还有糟糕的 C++ 风格:你有一个名为 __m256d tmp
的变量作为全局或 class 成员??它甚至不是局部虚拟变量,它可能存在于编译器无法完全优化的地方。
我正在尝试在一些文件上实施和编码,其中一些文件包含 SIMD 调用。我在服务器上编译了这段代码,运行 与我的机器基本相同OS,但我无法编译它。
这是错误:
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
谷歌搜索问题并没有真正帮助,因为所有答案都指出了问题,我已经准备好 do/tried。
有人可以提供一些关于它为什么不起作用的背景信息吗?
编辑:
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
这就是发生的事情的要点......我已经将所有 SIMDcalls 封装在 #ifdefs 等中。
GCC 将只允许您将内部函数用于允许编译器使用的指令集。例如关于 AVX1 intrinsic 的相关问题:inlining failed in call to always_inline '__m256d _mm256_broadcast_sd(const double*)'
这些是 256 位内部函数的 _mask_
版本,它们需要 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
这毫无意义,如果您要使用常量全一掩码,则不需要使用这些内在函数的掩码版本。像正常人一样使用 _mm256_add_pd
,只检查 __AVX__
。或者使用 _mm512_add_pd
.
起初我以为这是来自 TensorFlow,但(根据您的评论)这没有意义。它不可能写得那么糟糕。 使用完全真实的掩码将相同的 tmp
合并到 3 个副本中是没有意义的;如果编译器无法将 mask=all-ones 优化为未屏蔽的负载,那么引入错误依赖的方式看起来很愚蠢。
还有糟糕的 C++ 风格:你有一个名为 __m256d tmp
的变量作为全局或 class 成员??它甚至不是局部虚拟变量,它可能存在于编译器无法完全优化的地方。