etiquetas - Archivos de encabezado para x86 SIMD intrinsics
que es h2 en html (5)
¿Qué archivos de cabecera proporcionan las características intrínsecas de las diferentes extensiones de conjunto de instrucciones x86 SIMD (MMX, SSE, AVX, ...)? Parece imposible encontrar una lista en línea. Corrígeme si estoy equivocado.
Como muchas de las respuestas y comentarios han indicado, <x86intrin.h>
es el encabezado completo para x86 [-64] intrínsecos SIMD. También proporciona instrucciones de soporte intrínsecas para otras extensiones de ISA. gcc
, clang
e icc
han decidido por esto. Necesitaba investigar en las versiones que admiten el encabezado, y pensé que sería útil enumerar algunos hallazgos ...
gcc : la compatibilidad con
x86intrin.h
aparece por primera vez engcc-4.5.0
. La serie de lanzamiento degcc-4
ya no se mantiene, mientras quegcc-6.x
es la serie de lanzamiento estable actual .gcc-5
también introdujo la extensión__has_include
presente en todasclang-3.x
versiones declang-3.x
.gcc-7
está en prelanzamiento (pruebas de regresión, etc.) y siguiendo el esquema de control de versiones actual, se lanzará comogcc-7.1.0
.clang : Parece que
x86intrin.h
fue compatible con todasclang-3.x
versiones declang-3.x
. La última versión estable esclang (LLVM) 3.9.1
. La rama de desarrollo esclang (LLVM) 5.0.0
. No está claro qué pasó con la serie4.x
Choque de Apple : molestamente, el control de versiones de Apple no se corresponde con el de los proyectos de
LLVM
. Dicho esto, la versión actual:clang-800.0.42.1
, se basa enLLVM 3.9.0
. La primera versión basada enLLVM 3.0
parece serApple clang 2.1
enXcode 4.1
.LLVM 3.1
aparece por primera vez conApple clang 3.1
(una coincidencia numérica) enXcode 4.3.3
.
Apple también define__apple_build_version__
por ejemplo,8000042
. Esto parece ser el esquema de control de versiones más estable y estrictamente ascendente disponible. Si no desea admitir compiladores heredados, haga que uno de estos valores sea un requisito mínimo.
Cualquier versión reciente de clang
, incluidas las versiones de Apple, no debería tener problemas con x86intrin.h
. Por supuesto, junto con gcc-5
, siempre puedes usar lo siguiente:
#if defined (__has_include) && (__has_include(<x86intrin.h>))
#include <x86intrin.h>
#else
#error "upgrade your compiler. it''s free..."
#endif
Un truco en el que no puedes confiar es usar las versiones de __GNUC__
en clang
. El control de versiones está, por razones históricas, estancado en 4.2.1
. Una versión que precede al encabezado x86intrin.h
En ocasiones es útil para, por ejemplo, extensiones simples de GNU C que han permanecido compatibles con versiones anteriores.
icc : por lo que puedo decir, el encabezado
x86intrin.h
es compatible, al menos, con Intel C ++ 16.0. La prueba de versión se puede realizar con:#if (__INTEL_COMPILER >= 1600)
. Esta versión (y posiblemente versiones anteriores) también brinda soporte para la extensión__has_include
.MSVC : parece que
MSVC++ 12.0 (Visual Studio 2013)
es la primera versión que proporciona el encabezadointrin.h
, nox86intrin.h
... esto sugiere:#if (_MSC_VER >= 1800)
como prueba de versión. Por supuesto, si intenta escribir código que sea portátil en todos estos compiladores diferentes, el nombre de encabezado en esta plataforma será el menor de sus problemas.
De esta 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 |
+----------------+------------------------------------------------------------------------------------------+
Entonces, en general, puede incluir immintrin.h
para obtener todas las extensiones de Intel, o x86intrin.h
si desea que todo, incluidos _bit_scan_forward
y _rdtsc
, así como todos los vectores intrínsecos, incluyan solo los de AMD. Si está en contra de incluir más de lo que realmente necesita, puede elegir incluir el derecho mirando la tabla.
x86intrin.h
es la forma recomendada de obtener intrínsecos para AMD XOP (solo Bulldozer, ni siquiera futuras CPU AMD) , en lugar de tener su propio encabezado.
Algunos compiladores seguirán generando mensajes de error si utiliza intrínsecos para los conjuntos de instrucciones que no ha activado (por ejemplo, _mm_fmadd_ps
sin habilitar fma, incluso si incluye immintrin.h
y habilita AVX2).
El nombre del encabezado depende de su compilador y arquitectura de destino.
- Para Microsoft C ++ (dirigida a x86, x86-64 o ARM) y el compilador Intel C / C ++ para Windows, use
intrin.h
- Para la orientación gcc / clang / icc x86 / x86-64 use
x86intrin.h
- Para gcc / clang / brazocc, el ARM con NEON usa
arm_neon.h
- Para gcc / clang / armcc target ARM con WMMX use
mmintrin.h
- Para gcc / clang / xlcc que apunta a PowerPC con VMX (también conocido como Altivec) y / o VSX use
altivec.h
- Para la segmentación gcc / clang PowerPC con SPE use
spe.h
Puede manejar todos estos casos con directivas de preprocesamiento condicional:
#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
Si usa solo
#include <x86intrin.h>
incluirá todos los encabezados SSE / AVX que están habilitados de acuerdo con los modificadores del compilador como -march=corei7
o simplemente -march=native
. Además, algunas instrucciones específicas de x86 como bswap
o ror
están disponibles como intrínsecas.
<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