x86 SIMD 内部函数的头文件

Header files for x86 SIMD intrinsics

提问人:fredoverflow 提问时间:6/27/2012 最后编辑:plasmacelfredoverflow 更新时间:9/14/2020 访问量:96091

问:

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

x86 头文件 SSE SIMD 内部函数

评论


答:

229赞 fredoverflow 6/27/2012 #1

这些天来,您通常应该只包括 .它包括一切。<immintrin.h>

GCC 和 clang 将阻止您对编译时未启用的指令(例如,with or 或其他指令)使用内部函数。-march=native-mavx2 -mbmi2 -mpopcnt -mfma -mcx16 -mtune=znver1

MSVC 和 ICC 将允许您在不在编译时启用任何内容的情况下使用内部函数,但在使用 AVX 内部函数之前,您仍启用 AVX。


从历史上看(在拉入所有内容之前),您必须手动包含您想要的最高级别内部函数的标头。immintrin.h

对于 MSVC 和 ICC,这可能仍然有用,可以阻止自己使用您不想使用的指令集。

<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, AVX2, FMA

在所有以前的拉动中包括其中一个拉动(仅限 AMD 的 SSE4A:不会拉入)immintrin.h

一些编译器也具有 AVX512。<zmmintrin.h>

评论

72赞 Paul R 6/27/2012
或者你可以拉动你需要的一切。#include <x86intrin.h>
2赞 onitake 10/30/2014
zmmintrin.h 具有 AVX-512 内部函数。
6赞 phuclv 1/17/2015
为什么 SSE3/SSSE3/SSE4.1 和 4.2 是 p、t、s 和 n?这些角色代表什么?
8赞 Drew McGowen 6/8/2015
@LưuVĩnhPhúc SSE3 = Prescott 新指令,SSSE3 = Tejas 新指令。我认为 SSE4.2 和 AES 指的是它们引入的处理器系列(Nehalem 和 Westmere)
18赞 Peter Cordes 6/29/2016
不要直接包含;GCC 甚至不提供它。只需使用 <immintrin.h> 或更完整的 .这个答案基本上已经过时了,除非你有意避免包含较新版本的 SSE 的内部函数,因为当你在编译 SSE2 时使用 SSE4.1 指令时,你的编译器不会抱怨。(gcc/clang 确实抱怨,所以你应该只为他们使用 immintrin.h。关于其他人的 IDK。<zmmintrin.h><x86intrin.h>
93赞 Gunther Piez 6/27/2012 #2

在 GCC/clang 上,如果您仅使用

#include <x86intrin.h>

它将包括所有 SSE/AVX 标头,这些标头是根据编译器开关启用的,例如 或 只是 。此外,一些特定于 x86 的指令(如或)作为内部函数提供。-march=haswell-march=nativebswapror


此标头的 MSVC 等效项<intrin.h>


如果您只想要便携式 SIMD,请使用 #include < immintrin.h>

MSVC、ICC 和 gcc/clang(以及我认为像 Sun 这样的其他编译器)都支持英特尔唯一的内部函数查找器/搜索工具记录的 SIMD 内部函数的标头:https://software.intel.com/sites/landingpage/IntrinsicsGuide/

评论

0赞 Gunther Piez 6/28/2012
我不确定,如果较新的版本可能......无论如何,只要 gcc、icc 和 clang 有它,我认为可以使用:-)
6赞 Cody Gray - on strike 6/1/2014
MSVC 没有 ,但可以达到类似的效果。当然,您仍然需要条件编译。:-(<x86intrin.h><intrin.h>
1赞 Peter Cordes 4/16/2018
所有主要的 x86 编译器都有 #include < immintrin.h>。将其用于 SIMD 内部函数。您只需要更大的(并且编译速度稍慢),或者如果您需要整数旋转/位扫描内部函数之类的东西(尽管英特尔在其内部函数指南中记录了其中一些可用)。x86intrin.hintrin.himmintrin.h
0赞 Peter Cordes 4/16/2018
IIRC,有一些非 SIMD 内部函数,英特尔将其记录为 immintrin.h 中,但 gcc、clang 和/或 MSVC 仅在 / 中具有,但在 .x86intrin.hintrin.himmintrin.h
65赞 Marat Dukhan 3/10/2014 #3

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

  • 适用于 Microsoft C++(面向 x86、x86-64 或 ARM)和适用于 Windows 的英特尔 C/C++ 编译器intrin.h
  • 对于以 x86/x86-64 为目标的 gcc/clang/icc 使用x86intrin.h
  • 对于使用 NEON 的 ARM 目标 gcc/clang/armccarm_neon.h
  • 对于使用 WMMX 的针对 ARM 的 gcc/clang/armccmmintrin.h
  • 对于以 VMX(又名 Altivec)和/或 VSX 为目标的 PowerPC 的 gcc/clang/xlccaltivec.h
  • 对于使用 SPE 的 PowerPC 目标 gcc/clangspe.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

评论

0赞 onitake 10/29/2014
这里还有一些要添加到您的列表中:在带有 gcc 的 UltraSPARC+VIS 上,使用 visintrin.h;如果您有 Sun 的 VSDK,vis.h 会提供一组不同的内部函数。文档可在此处找到:GCC VIS 内置、Sun VIS 用户指南
53赞 RubenLaguna 7/2/2015 #4

从本

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

因此,一般来说,您可以只包含以获取所有英特尔扩展,或者如果您想要所有内容,包括 和 ,以及所有矢量内部函数都包括仅限 AMD 的扩展。如果您反对包含更多您实际需要的内容,那么您可以通过查看表格来选择正确的包含。immintrin.hx86intrin.h_bit_scan_forward_rdtsc

x86intrin.h是获取 AMD XOP(仅限推土机,甚至不是未来的 AMD CPU)的内部函数的推荐方法,而不是拥有自己的标头。

如果您将内部函数用于尚未启用的指令集(例如 而不启用 FMA,即使包含并启用 AVX2)。_mm_fmadd_psimmintrin.h

评论

1赞 Peter Cordes 6/4/2016
smmintrin(SSE4.1)是Penryn(45nm Core2),而不是Nehalem(“i7”)。我们可以停止使用“i7”作为架构名称吗?现在英特尔一直将其用于 SnB 系列,这毫无意义
0赞 Thom Wiggers 8/27/2019
immintrin.h似乎不包括 GCC 9.1.0 上的内部函数(不要与 !)内部函数。所以它似乎仍然有目的。_popcnt32_popcnt64popcntintrin.hx86intrin.h
24赞 Brett Hale 2/28/2017 #5

20200914:最新的最佳实践:<immintrin.h>MSVC 也支持))

我将把其余的答案留给历史目的;它可能对较旧的编译器/平台组合有用......


正如许多答案和评论所指出的,是 x86[-64] SIMD 内部函数的综合标题。它还为其他 ISA 扩展提供了内部函数支持指令。,,并且都解决了这个问题。我需要对支持标题的版本进行一些挖掘,并认为列出一些发现可能会有所帮助......<x86intrin.h>gccclangicc

  • gcc:对 first 的支持出现在 中。发布系列不再维护,而当前稳定版本系列则不再维护。 还引入了所有版本中存在的扩展。 处于预发布阶段(回归测试等),并遵循当前的版本控制方案,将作为 发布。x86intrin.hgcc-4.5.0gcc-4gcc-6.xgcc-5__has_includeclang-3.xgcc-7gcc-7.1.0

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

  • 苹果叮叮当当:令人讨厌的是,苹果的版本控制与项目的版本控制不符。也就是说,当前版本:基于 。第一个基于的版本似乎又回到了 中。 首次出现在 中(数字巧合)。

    Apple 还定义了例如 .这似乎是最稳定、最严格的升序版本控制方案。如果不想支持旧版编译器,请将其中一个值作为最低要求。
    LLVMclang-800.0.42.1LLVM 3.9.0LLVM 3.0Apple clang 2.1Xcode 4.1LLVM 3.1Apple clang 3.1Xcode 4.3.3__apple_build_version__8000042

因此,任何最新版本的 ,包括 Apple 版本,都应该没有问题。当然,除了 ,您始终可以使用以下内容:clangx86intrin.hgcc-5

#if defined (__has_include) && (__has_include(<x86intrin.h>))
#include <x86intrin.h>
#else
#error "upgrade your compiler. it's free..."
#endif

你不能真正依赖的一个技巧是使用 .由于历史原因,版本控制停留在 .标头前面的版本。它偶尔对保持向后兼容的简单 GNU C 扩展很有用。__GNUC__clang4.2.1x86intrin.h

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

  • MSVC :这似乎是第一个提供标头的版本 - 不是......这表明:作为版本测试。当然,如果你试图编写跨所有这些不同编译器的可移植代码,那么这个平台上的标头名称将是你最不容易遇到的问题。MSVC++ 12.0 (Visual Studio 2013)intrin.hx86intrin.h#if (_MSC_VER >= 1800)

评论

1赞 FrankHB 12/21/2021
我宁愿而不是烦人的版本检查。另请注意,GCC 目前在特定 buitins 上仍然存在一些错误;在这种情况下,我会考虑特定于目标的,甚至是没有记录的__has_builtin