Quels fichiers d'en-tête fournissent les éléments intrinsèques des différentes extensions du jeu d'instructions SIMD x86 (MMX, SSE, AVX, ...)? Il semble impossible de trouver une telle liste en ligne. Corrige moi si je me trompe.
<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
Si vous utilisez juste
#include <x86intrin.h>
il inclura tous les en-têtes SSE/AVX activés en fonction des commutateurs de compilation tels que -march=corei7
ou juste -march=native
. De plus, certaines instructions spécifiques à x86 telles que bswap
ou ror
deviennent disponibles en tant qu'intrinsèques.
Le nom de l'en-tête dépend de votre compilateur et de votre architecture cible.
intrin.h
x86intrin.h
arm_neon.h
mmintrin.h
altivec.h
spe.h
Vous pouvez gérer tous ces cas avec des directives de pré-traitement conditionnel:
#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
De ceci 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 |
+----------------+------------------------------------------------------------------------------------------+
Donc, en général, vous pouvez simplement inclure immintrin.h
pour obtenir toutes les extensions Intel, ou x86intrin.h
si vous voulez tout, y compris _bit_scan_forward
et _rdtsc
, ainsi que tous les éléments intrinsèques aux vecteurs, incluent ceux d’AMD uniquement. Si vous êtes contre d’inclure plus que ce dont vous avez réellement besoin, vous pouvez choisir le bon inclure en consultant le tableau.
x86intrin.h
est le moyen recommandé d’obtenir des éléments intrinsèques pour AMD XOP (processeurs AMD uniquement, pas même les futurs processeurs AMD) , plutôt que d’avoir son propre en-tête.
Certains compilateurs continueront de générer des messages d’erreur si vous utilisez des éléments intrinsèques pour des jeux d’instructions que vous n’avez pas activés (par exemple, _mm_fmadd_ps
sans activer FMA, même si vous incluez immintrin.h
et activez AVX2).
Comme beaucoup de réponses et de commentaires l'ont indiqué, <x86intrin.h>
Est le en-tête complet pour x86 [-64] intrinsics SIMD. Il fournit également des instructions intrinsèques pour le support d’autres ISA extensions. gcc
, clang
et icc
ont toutes réglé ce problème. Je devais faire des recherches sur les versions qui supportent l’en-tête, et a pensé qu’il pourrait être utile d’énumérer quelques découvertes ...
gcc: le support pour x86intrin.h
apparaît pour la première fois dans gcc-4.5.0
. La série de versions gcc-4
N'est plus maintenue, alors que gcc-6.x
Est la série de versions actuelle stable. gcc-5
A également introduit l'extension __has_include
Présente dans toutes les versions clang-3.x
. gcc-7
Est en pré-version (test de régression, etc.) et suit le schéma de version actuel, sera publié en tant que gcc-7.1.0
.
clang: x86intrin.h
semble avoir été pris en charge pour toutes les versions clang-3.x
. La dernière version stable est clang (LLVM) 3.9.1
. La branche de développement est clang (LLVM) 5.0.0
. Ce qui est arrivé à la série 4.x
N'est pas clair.
Apple clang: ennuyeusement, le versioning d’Apple ne correspond pas à celui des projets LLVM
. Cela dit, la version actuelle: clang-800.0.42.1
, Est basée sur LLVM 3.9.0
. La première version basée sur LLVM 3.0
Semble être Apple clang 2.1
Dans Xcode 4.1
. LLVM 3.1
Apparaît d'abord avec Apple clang 3.1
(Une coïncidence numérique) dans Xcode 4.3.3
.
Apple définit également __Apple_build_version__
, Par exemple 8000042
. Cela semble être le schéma de versions le plus stable et le plus strictement ascendant disponible. Si vous ne souhaitez pas prendre en charge les compilateurs hérités, définissez l'une de ces valeurs comme une exigence minimale.
Toute version récente de clang
, y compris les versions Apple, ne devrait donc pas avoir de problème avec x86intrin.h
. Bien sûr, avec gcc-5
, Vous peut toujours utiliser les éléments suivants:
#if defined (__has_include) && (__has_include(<x86intrin.h>))
#include <x86intrin.h>
#else
#error "upgrade your compiler. it's free..."
#endif
Une astuce sur laquelle vous ne pouvez pas vraiment compter consiste à utiliser les versions __GNUC__
Dans clang
. Le contrôle de version est, pour des raisons historiques, bloqué à 4.2.1
. Une version qui précède l'en-tête x86intrin.h
. C'est parfois utile pour, par exemple, les simples GNU extensions C qui sont restées compatibles avec les versions antérieures.
icc: autant que je sache, l'en-tête x86intrin.h
est supporté depuis au moins Intel C++ 16.0. Le test de version peut être effectué avec: #if (__INTEL_COMPILER >= 1600)
. Cette version (et éventuellement les versions antérieures) prend également en charge l'extension __has_include
.
MSVC : Il semble que MSVC++ 12.0 (Visual Studio 2013)
soit la première version à fournir l'en-tête intrin.h
- not x86intrin.h
... ceci suggère: #if (_MSC_VER >= 1800)
comme test de version. Bien sûr, si vous essayez d'écrire du code portable sur tous ces différents compilateurs, le nom de l'en-tête sur cette plate-forme sera le moindre de vos problèmes.