x86 SIMD内部函数的头文件
哪些头文件为不同的x86 SIMD指令集扩展(MMX,SSE,AVX,…)提供了内在的function? 在网上find这样的清单似乎是不可能的。 如我错了请纠正我。
<mmintrin.h> MMX <xmmintrin.h> SSE <emmintrin.h> SSE2 <pmmintrin.h> SSE3 <tmmintrin.h> SSSE3 <smmintrin.h> SSE4.1 <nmmintrin.h> SSE4.2 <ammintrin.h> SSE4A <wmmintrin.h> AES <immintrin.h> AVX <zmmintrin.h> AVX512
如果你只是使用
#include <x86intrin.h>
它将包含所有根据编译器开关启用的SSE / AVX头文件,如-march=corei7
或者-march=native
。 此外,一些特定于x86的指令(如bswap
或ror
可用作内在函数。
标题名称取决于您的编译器和目标体系结构。
- 对于Microsoft C ++(针对x86,x86-64或ARM)和Windows的Intel C / C ++编译器,请使用
intrin.h
- 对于x86 / x86-64的gcc / clang / icc,使用
x86intrin.h
- 对于使用ARM的gcc / clang / armcc,使用
arm_neon.h
- 对于使用WMMX的gcc / clang / armcc定位ARM,请使用
mmintrin.h
- 对于使用VMX(又名Altivec)和/或VSX的PowerPC的gcc / clang / xlcc,使用
altivec.h
- 对于使用SPE使用SPE的gcc / clang来说,使用
spe.h
您可以使用条件预处理指令处理所有这些情况:
#if defined(_MSC_VER) /* Microsoft C/C++-compatible compiler */ #include <intrin.h> #elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) /* GCC-compatible compiler, targeting x86/x86-64 */ #include <x86intrin.h> #elif defined(__GNUC__) && defined(__ARM_NEON__) /* GCC-compatible compiler, targeting ARM with NEON */ #include <arm_neon.h> #elif defined(__GNUC__) && defined(__IWMMXT__) /* GCC-compatible compiler, targeting ARM with WMMX */ #include <mmintrin.h> #elif (defined(__GNUC__) || defined(__xlC__)) && (defined(__VEC__) || defined(__ALTIVEC__)) /* XLC or GCC-compatible compiler, targeting PowerPC with VMX/VSX */ #include <altivec.h> #elif defined(__GNUC__) && defined(__SPE__) /* GCC-compatible compiler, targeting PowerPC with SPE */ #include <spe.h> #endif
从这个页面
+----------------+------------------------------------------------------------------------------------------+ | Header | Purpose | +----------------+------------------------------------------------------------------------------------------+ | x86intrin.h | Everything, including non-vector x86 instructions like _rdtsc(). | | mmintrin.h | MMX (Pentium MMX!) | | mm3dnow.h | 3dnow! (K6-2) (deprecated) | | xmmintrin.h | SSE + MMX (Pentium 3, Athlon XP) | | emmintrin.h | SSE2 + SSE + MMX (Pentium 4, Athlon 64) | | pmmintrin.h | SSE3 + SSE2 + SSE + MMX (Pentium 4 Prescott, Athlon 64 San Diego) | | tmmintrin.h | SSSE3 + SSE3 + SSE2 + SSE + MMX (Core 2, Bulldozer) | | popcntintrin.h | POPCNT (Nehalem (Core i7), Phenom) | | ammintrin.h | SSE4A + SSE3 + SSE2 + SSE + MMX (AMD-only, starting with Phenom) | | smmintrin.h | SSE4_1 + SSSE3 + SSE3 + SSE2 + SSE + MMX (Penryn, Bulldozer) | | nmmintrin.h | SSE4_2 + SSE4_1 + SSSE3 + SSE3 + SSE2 + SSE + MMX (Nehalem (aka Core i7), Bulldozer) | | wmmintrin.h | AES (Core i7 Westmere, Bulldozer) | | immintrin.h | AVX, AVX2, AVX512, all SSE+MMX (except SSE4A and XOP), popcnt, BMI/BMI2, FMA | +----------------+------------------------------------------------------------------------------------------+
所以一般来说,如果你想要所有的东西,包括_bit_scan_forward
和_rdtsc
,以及所有的vector内在函数,都只包含AMD,那么你可以包含immintrin.h
来得到所有的Intel扩展,或者x86intrin.h
。 如果你反对包括更多你真正需要的,那么你可以select正确的包括通过看表。
x86intrin.h
是推荐用于AMD XOP(仅推土机,甚至不是未来的AMD CPU)的内部函数,而不是拥有自己的头文件。
有些编译器仍然会产生错误信息,如果你使用内部函数来指令你没有启用(例如_mm_fmadd_ps
没有启用fma,即使你包含immintrin.h
并启用AVX2)。
正如许多答案和评论所述, <x86intrin.h>
是x86 [-64] SIMD内在函数的综合头文件。 它还提供了其他ISA扩展的内部支持指令。 gcc
, clang
和icc
都已经解决了这个问题。 我需要对支持标题的版本进行一些挖掘,并认为列出一些发现可能是有用的。
-
gcc :对
x86intrin.h
支持首先出现在gcc-4.5.0
。gcc-4
发行版系列不再维护,而gcc-6.x
是目前的稳定版系列。gcc-5
还引入了所有clang-3.x
版本中的__has_include
扩展。gcc-7
在预发行版(回归testing等)中,并遵循当前的版本scheme,将作为gcc-7.1.0
发布。 -
铛 :
x86intrin.h
似乎已经支持所有的clang-3.x
版本。 最新的稳定版本是clang (LLVM) 3.9.1
。 开发分支是clang (LLVM) 5.0.0
。 目前还不清楚4.x
系列发生了什么。 -
苹果叮当 :恼人的是,苹果的版本与
LLVM
项目的版本并不一致。 也就是说,目前的版本是:clang-800.0.42.1
,基于LLVM 3.9.0
。 第一个基于LLVM 3.0
的版本在Xcode 4.1
似乎是Apple clang 2.1
。 在Xcode 4.3.3
LLVM 3.1
首先出现在Apple clang 3.1
(数字巧合)中。Apple还定义了
__apple_build_version__
例如8000042
。 这似乎是最稳定的,严格按照升序版本的scheme。 如果您不想支持遗留编译器,请将其中一个值作为最低要求。
因此,任何最近版本的clang
,包括Apple版本,都应该对x86intrin.h
没有任何问题。 当然,随着gcc-5
,你可以随时使用以下内容:
#if defined (__has_include) && (__has_include(<x86intrin.h>)) #include <x86intrin.h> #else #error "upgrade your compiler. it's free..." #endif
你不能真正依赖的一个技巧是在clang
使用__GNUC__
版本。 由于历史原因,版本控制在4.2.1
。 x86intrin.h
头文件之前的版本。 对于那些保持向后兼容的简单的GNU C扩展偶尔是有用的。
-
icc :就我所知,
x86intrin.h
头文件至less支持Intel C ++ 16.0。 版本testing可以通过执行:#if (__INTEL_COMPILER >= 1600)
。 该版本(以及可能更早的版本)也提供对__has_include
扩展的支持。 -
MSVC :看起来,
MSVC++ 12.0 (Visual Studio 2013)
是第一个提供intrin.h
头文件的版本 – 不是x86intrin.h
…这表明:#if (_MSC_VER >= 1800)
作为版本testing。 当然,如果你试图编写在所有这些不同编译器中可移植的代码,那么这个平台上的标题名称将是你的问题中最less的。