包括正确的内在标头

Cya*_*yan 2 c gcc header intel intrinsics

我一直在阅读有关哪个头文件更适合访问英特尔内在函数的意见:x86intrin.himmintrin.h

两者似乎都达到了相同的结果,但我确信在代码可移植性方面一定存在一些细微的差异。也许其中一个比另一个更常见或更完整?

我找不到对其中任何一个的解释。如果有人知道为什么有两个文件,以及它们有什么区别,这将是一个受欢迎的答案。

说到可移植性,对于较旧的编译器(例如gcc< v4.4.0),事情当然会变得更加复杂,而且两者都不可用。必须考虑包含另一个内在标头(可能emmintrin.h用于 SSE 支持)。

Pet*_*des 5

(在此处发布答案是因为x86 SIMD 内在函数的头文件具有过时的答案,建议包含单独的头文件)。


immintrin.h可跨所有编译器移植,并包含所有英特尔SIMD 内在函数,以及一些可与它_pdep_u32一起使用-mbmi2-march=包含它的标量扩展。(对于 AMD SSE4a 和 XOP(仅限 Bulldozer 系列,为 Zen 放弃),您还需要包含不同的标头。)

我能想到的<emmintrin.h>专门包含的唯一原因是,如果您正在使用 MSVC 并且希望为您不想依赖的 ISA 扩展保留未定义的内部函数。

GCC 的模型要求您先启用扩展,然后才能使用它们的内在函数,这意味着编译器会为您执行此检查,因此#include <immintrin.h>如果您尝试使用_mm_shuffle_epi8pshufb-mssse3.

不要使用早于 gcc4.4 的编译器。 它们已经过时,通常会生成较慢的代码,特别是对于在决定调整设置时还不存在的现代 CPU。


gcc/clangx86intrin.h与 MSVCintrin.h仅在您需要一些额外的非 SIMD 内在函数(例如 MSVC 等_BitScanReverse()并不总是可以跨编译器移植)时才有用。像整数旋转/位扫描内在函数这样的东西是基线(与 BMI1 lzcnt/tzcnt或 BMI2不同rorx),但很难或不可能以编译器识别并将循环转回单个指令的方式用 C 语言表达。

Intel 在其内在函数指南中将其中一些记录为可在 immintrin.h 中使用,但 gcc/clang 和 MSVC 实际上分别在其x86intrin.hintrin.h标头中提供了它们。

请参阅如何从 C++ 获取 x86_64 中的 CPU 周期计数?有关使用#ifdef _MSC_VER选择正确标头来定义uint64_t __rdtsc(void)和的示例__rdtscp()