【问题标题】:Including the correct intrinsic header包括正确的内在标头
【发布时间】:2019-09-26 16:21:09
【问题描述】:

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

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

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

谈到可移植性,对于较旧的编译器(如gcc 另一个 内在标头(可能是 emmintrin.h 以获得 SSE 支持)。

【问题讨论】:

  • 我只包含了我正在使用的内在函数的特定部分。英特尔的参考指南在注释中包含(哈哈!)它们。

标签: c gcc header intel intrinsics


【解决方案1】:

(在此处发布答案是因为 Header files for x86 SIMD intrinsics 的答案已过时,建议包含个别头文件)。


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

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

GCC 的模型要求您在使用内部函数之前启用扩展,这意味着编译器会为您执行此检查,因此您可以只使用 #include <immintrin.h> 但如果您尝试使用 _mm_shuffle_epi8 (@987654329) 仍然会出错@) 没有-mssse3

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


gcc/clang 的 x86intrin.h 与 MSVC intrin.h 仅在您需要一些额外的非 SIMD 内在函数(如 MSVC 的 _BitScanReverse())时才有用,这些内在函数并不总是可跨编译器移植。诸如整数旋转/位扫描内在函数之类的基线(与 BMI1 lzcnt/tzcnt 或 BMI2 rorx 不同)但很难或不可能用 C 语言以编译器可以识别并将循环转换回单条指令。

英特尔在 immintrin.h 中的 their intrinsics guide 中记录了其中一些可用,但 gcc/clang 和 MSVC 实际上分别在其 x86intrin.hintrin.h 标头中包含它们。

请参阅Get CPU cycle count?,了解使用#ifdef _MSC_VER 选择正确的标题 来定义uint64_t __rdtsc(void)__rdtscp() 的示例。

【讨论】:

  • 感谢@Peter,这是非常棒的东西,准确而完整。
猜你喜欢
  • 2021-07-29
  • 1970-01-01
  • 2013-01-23
  • 1970-01-01
  • 2019-06-27
  • 1970-01-01
  • 1970-01-01
  • 2022-01-27
  • 2016-03-09
相关资源
最近更新 更多