提问人:fredoverflow 提问时间:6/27/2012 最后编辑:plasmacelfredoverflow 更新时间:9/14/2020 访问量:96091
x86 SIMD 内部函数的头文件
Header files for x86 SIMD intrinsics
答:
这些天来,您通常应该只包括 .它包括一切。<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>
评论
#include <x86intrin.h>
<immintrin.h>
或更完整的 .这个答案基本上已经过时了,除非你有意避免包含较新版本的 SSE 的内部函数,因为当你在编译 SSE2 时使用 SSE4.1 指令时,你的编译器不会抱怨。(gcc/clang 确实抱怨,所以你应该只为他们使用 immintrin.h。关于其他人的 IDK。<zmmintrin.h>
<x86intrin.h>
在 GCC/clang 上,如果您仅使用
#include <x86intrin.h>
它将包括所有 SSE/AVX 标头,这些标头是根据编译器开关启用的,例如 或 只是 。此外,一些特定于 x86 的指令(如或)作为内部函数提供。-march=haswell
-march=native
bswap
ror
此标头的 MSVC 等效项<intrin.h>
如果您只想要便携式 SIMD,请使用 #include < immintrin.h>
MSVC、ICC 和 gcc/clang(以及我认为像 Sun 这样的其他编译器)都支持英特尔唯一的内部函数查找器/搜索工具记录的 SIMD 内部函数的标头:https://software.intel.com/sites/landingpage/IntrinsicsGuide/
评论
<x86intrin.h>
<intrin.h>
#include < immintrin.h>
。将其用于 SIMD 内部函数。您只需要更大的(并且编译速度稍慢),或者如果您需要整数旋转/位扫描内部函数之类的东西(尽管英特尔在其内部函数指南中记录了其中一些可用)。x86intrin.h
intrin.h
immintrin.h
x86intrin.h
intrin.h
immintrin.h
标头名称取决于编译器和目标体系结构。
- 适用于 Microsoft C++(面向 x86、x86-64 或 ARM)和适用于 Windows 的英特尔 C/C++ 编译器
intrin.h
- 对于以 x86/x86-64 为目标的 gcc/clang/icc 使用
x86intrin.h
- 对于使用 NEON 的 ARM 目标 gcc/clang/armcc
arm_neon.h
- 对于使用 WMMX 的针对 ARM 的 gcc/clang/armcc
mmintrin.h
- 对于以 VMX(又名 Altivec)和/或 VSX 为目标的 PowerPC 的 gcc/clang/xlcc
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
评论
从本页
+----------------+------------------------------------------------------------------------------------------+
| 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.h
x86intrin.h
_bit_scan_forward
_rdtsc
x86intrin.h
是获取 AMD XOP(仅限推土机,甚至不是未来的 AMD CPU)的内部函数的推荐方法,而不是拥有自己的标头。
如果您将内部函数用于尚未启用的指令集(例如 而不启用 FMA,即使包含并启用 AVX2)。_mm_fmadd_ps
immintrin.h
评论
smmintrin
(SSE4.1)是Penryn(45nm Core2),而不是Nehalem(“i7”)。我们可以停止使用“i7”作为架构名称吗?现在英特尔一直将其用于 SnB 系列,这毫无意义。
immintrin.h
似乎不包括 GCC 9.1.0 上的内部函数(不要与 !)内部函数。所以它似乎仍然有目的。_popcnt32
_popcnt64
popcntintrin.h
x86intrin.h
20200914:最新的最佳实践:<immintrin.h>
(MSVC 也支持))
我将把其余的答案留给历史目的;它可能对较旧的编译器/平台组合有用......
正如许多答案和评论所指出的,是 x86[-64] SIMD 内部函数的综合标题。它还为其他 ISA 扩展提供了内部函数支持指令。,,并且都解决了这个问题。我需要对支持标题的版本进行一些挖掘,并认为列出一些发现可能会有所帮助......<x86intrin.h>
gcc
clang
icc
gcc:对 first 的支持出现在 中。发布系列不再维护,而当前稳定版本系列则不再维护。 还引入了所有版本中存在的扩展。 处于预发布阶段(回归测试等),并遵循当前的版本控制方案,将作为 发布。
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 还定义了例如 .这似乎是最稳定、最严格的升序版本控制方案。如果不想支持旧版编译器,请将其中一个值作为最低要求。LLVM
clang-800.0.42.1
LLVM 3.9.0
LLVM 3.0
Apple clang 2.1
Xcode 4.1
LLVM 3.1
Apple clang 3.1
Xcode 4.3.3
__apple_build_version__
8000042
因此,任何最新版本的 ,包括 Apple 版本,都应该没有问题。当然,除了 ,您始终可以使用以下内容:clang
x86intrin.h
gcc-5
#if defined (__has_include) && (__has_include(<x86intrin.h>))
#include <x86intrin.h>
#else
#error "upgrade your compiler. it's free..."
#endif
你不能真正依赖的一个技巧是使用 .由于历史原因,版本控制停留在 .标头前面的版本。它偶尔对保持向后兼容的简单 GNU C 扩展很有用。__GNUC__
clang
4.2.1
x86intrin.h
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)
评论
__has_builtin
上一个:我应该返回集合还是流?
下一个:插入地图的首选/惯用方式是什么?
评论