我一直在阅读有关哪个头文件更适合访问英特尔内部函数的意见:x86intrin.h
或 immintrin.h
。
两者似乎都达到了相同的结果,但我确信在代码可移植性方面一定存在一些细微的差异。也许其中一个比另一个更常见或更完整?
我找不到其中任何一个的解释。如果有人知道为什么有 2 个文件,以及它们有什么区别,这将是一个受欢迎的答案。
说到可移植性,对于较旧的编译器(例如gcc
< v4.4.0),事情当然会变得更加复杂,而且两者都不可用。必须考虑包含另一个内部 header (可能是用于 SSE 支持的 emmintrin.h
)。
最佳答案
(在此处发布答案,因为 Header files for x86 SIMD intrinsics 已过时的答案建议包含单独的头文件)。
<强> immintrin.h
可跨所有编译器移植,并包含所有Intel SIMD 内在函数,以及一些标量扩展,例如 _pdep_u32
可用 -mbmi2
或-march=
其中包括它。 (对于 AMD SSE4a 和 XOP(仅限 Bulldozer 系列,为 Zen 放弃),您还需要包含不同的 header 。)
我能想到包括 <emmintrin.h>
的唯一原因具体来说,如果您使用 MSVC 并且希望为您不想依赖的 ISA 扩展保留未定义的内部函数。
GCC 的模型要求您先启用扩展,然后才能使用它们的内在函数,这意味着编译器会为您进行此检查,因此您只需 #include <immintrin.h>
但如果您尝试使用 _mm_shuffle_epi8
仍然会出现错误( pshufb
) 没有 -mssse3
.
不要使用早于 gcc4.4 的编译器。它们已经过时,通常会生成较慢的代码,特别是对于在决定调优设置时还不存在的现代 CPU。
gcc/clang 的 x86intrin.h
与 MSVC intrin.h
仅当您需要一些额外的非 SIMD 内在函数(例如 MSVC 的 _BitScanReverse()
)时才有用。并不总是可以跨编译器移植。像整数旋转/位扫描内在函数这样的东西是基线(不像 BMI1 lzcnt
/tzcnt
或 BMI2 rorx
),但很难或不可能以编译器能够识别并将循环转回循环的方式在 C 中表达单条指令。
英特尔在 their intrinsics guide 的 immintrin.h 中记录了其中一些可用的内容,但 gcc/clang 和 MSVC 实际上将它们放在 x86intrin.h
中或intrin.h
分别是标题。
参见How to get the CPU cycle count in x86_64 from C++?例如使用#ifdef _MSC_VER
选择正确的 header 来定义 uint64_t __rdtsc(void)
和__rdtscp()
.
关于c - 包括正确的内在 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56049110/