x86 SIMD内在函数的头文件

时间:2012-06-27 14:44:54

标签: x86 header-files sse simd intrinsics

哪些头文件为不同的x86 SIMD指令集扩展(MMX,SSE,AVX,...)提供内在函数?似乎不可能在网上找到这样的清单。如果我错了,请纠正我。

5 个答案:

答案 0 :(得分:152)

<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

答案 1 :(得分:69)

如果你只使用

#include <x86intrin.h>

它将包括根据-march=corei7-march=native之类的编译器开关启用的所有SSE / AVX标头。此外,某些x86特定说明(如bswapror)可用作内在函数。

答案 2 :(得分:51)

标题名称取决于您的编译器和目标体系结构。

  • 对于Microsoft C ++(针对x86,x86-64或ARM)和适用于Windows的英特尔C / C ++编译器,请使用intrin.h
  • 对于gcc / clang / icc定位x86 / x86-64,请使用x86intrin.h
  • 对于使用NEON定位ARM的gcc / clang / armcc,请使用arm_neon.h
  • 对于使用WMMX定位ARM的gcc / clang / armcc,请使用mmintrin.h
  • 对于gcc / clang / xlcc定位PowerPC与VMX(又名Altivec)和/或VSX使用altivec.h
  • 对于使用SPE定位PowerPC的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

答案 3 :(得分:37)

从此page

+----------------+------------------------------------------------------------------------------------------+
|     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             |
+----------------+------------------------------------------------------------------------------------------+

因此,一般情况下,您可以包含immintrin.h以获取所有英特尔扩展程序,或x86intrin.h如果您想要所有内容,包括_bit_scan_forward_rdtsc,以及所有向量内在因素包括仅限AMD的内在因素。如果您反对包含您实际需要的更多内容,那么您可以通过查看表格来选择正确的包含。

x86intrin.h是获取AMD XOP (Bulldozer-only, not even future AMD CPUs)内在函数的推荐方法,而不是拥有自己的标题。

如果您对尚未启用的指令集使用内在函数(例如_mm_fmadd_ps而未启用fma,即使您包含immintrin.h并启用AVX2),某些编译器仍会生成错误消息。

答案 4 :(得分:11)

正如许多答案和评论所述,<x86intrin.h>是x86 [-64] SIMD内在函数的 综合标题。它还为其他ISA扩展提供内在支持指令。 gccclangicc已全部解决此问题。我需要对支持标题的版本进行一些挖掘,并认为列出一些结果可能有用...

  • gcc :首先在x86intrin.h中显示对gcc-4.5.0的支持。不再维护gcc-4版本系列,而gcc-6.x当前稳定版本系列。 gcc-5还引入了所有__has_include版本中的clang-3.x扩展名。 gcc-7处于预发布状态(回归测试等),并且遵循当前版本控制方案,将以gcc-7.1.0发布。

  • clang :所有x86intrin.h版本似乎都支持clang-3.x。最新的稳定版本为clang (LLVM) 3.9.1。开发分支是clang (LLVM) 5.0.0。目前尚不清楚4.x系列发生了什么。

  • Apple clang :令人讨厌的是,Apple的版本控制与LLVM项目的版本控制不一致。也就是说,当前版本clang-800.0.42.1基于LLVM 3.9.0。基于LLVM 3.0的第一个版本似乎是Apple clang 2.1Xcode 4.1LLVM 3.1 Apple clang 3.1首次显示Xcode 4.3.3(数字巧合)。{
    Apple还定义__apple_build_version__,例如8000042。这似乎是最稳定,严格提升的版本控制方案。如果您不想支持旧版编译器,请将其中一个值作为最低要求。

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

您无法真正依赖的一个技巧是使用__GNUC__中的clang版本。由于历史原因,版本控制停留在4.2.1。在x86intrin.h标头之前的版本。例如,对于保持向后兼容的简单GNU C扩展,它偶尔会有用。

  • icc :据我所知,至少从英特尔C ++ 16.0开始支持x86intrin.h标头。版本测试可以通过以下方式执行:#if (__INTEL_COMPILER >= 1600)。此版本(可能还有早期版本)还支持__has_include扩展名。

  • MSVC MSVC++ 12.0 (Visual Studio 2013)是第一个提供intrin.h标题的版本 - 不是 x86intrin.h ...这表明:#if (_MSC_VER >= 1800)作为版本测试。当然,如果您正在尝试编写可在所有这些不同编译器中移植的代码,则此平台上的标题名称将是您遇到的最少问题。