Archivos de encabezado para intrínsecos SIMD x86

131

¿Qué archivos de encabezado proporcionan los elementos intrínsecos para las diferentes extensiones del conjunto de instrucciones SIMD x86 (MMX, SSE, AVX, ...)? Parece imposible encontrar esa lista en línea. Corrígeme si me equivoco.

flujo libre
fuente

Respuestas:

174

En estos días, normalmente debería incluir <immintrin.h>. Incluye todo

GCC y clang le impedirán usar intrínsecos para instrucciones que no ha habilitado en tiempo de compilación (por ejemplo, con -march=nativeo-mavx2 -mbmi2 -mpopcnt -mfma -mcx16 -mtune=znver1 o lo que sea).

MSVC e ICC le permitirán usar intrínsecos sin habilitar nada en el momento de la compilación, pero aún debe habilitar AVX antes de usar intrínsecos AVX.


Históricamente (antes de immintrin.hextraer todo) tenía que incluir manualmente un encabezado para el nivel más alto de intrínsecos que deseaba.

Esto aún puede ser útil con MSVC e ICC para evitar el uso de conjuntos de instrucciones que no desea requerir.

<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

Incluir uno de estos tirones en todos los anteriores (excepto SSE4A solo para AMD: immintrin.hno lo hace)

Algunos compiladores también tienen <zmmintrin.h>para AVX512.

flujo libre
fuente
62
O puede simplemente lo #include <x86intrin.h>que atrae todo lo que necesita.
Paul R
2
zmmintrin.h tiene los intrínsecos AVX-512.
onitake
3
¿Por qué p, t, syn para SSE3 / SSSE3 / SSE4.1 y 4.2? ¿Qué representan esos personajes?
phuclv
55
@ LưuVĩnhPhúc SSE3 = Prescott nuevas instrucciones, SSSE3 = Tejas nuevas instrucciones. Creo que SSE4.2 y AES se refieren a la familia de procesadores en los que se presentaron (Nehalem y Westmere)
Drew McGowen
14
No incluir <zmmintrin.h>directamente; gcc ni siquiera lo proporciona. Solo use<immintrin.h> o el aún más completo <x86intrin.h>. Esta respuesta es básicamente obsoleta, a menos que evite intencionalmente incluir intrínsecos para las versiones más nuevas de SSE porque su compilador no se queja cuando usa una instrucción SSE4.1 mientras compila para SSE2. (gcc / ruido metálico no se quejan, por lo que sólo debe utilizar immintrin.h para ellos IDK por los demás..)
Peter Cordes
76

En GCC / clang, si usa solo

#include <x86intrin.h>

incluirá todos los encabezados SSE / AVX que están habilitados de acuerdo con los conmutadores del compilador como -march=haswello simplemente -march=native. Además, algunas instrucciones específicas de x86 tienen gusto bswapo rorestán disponibles como intrínsecas.


El equivalente de MSVC de este encabezado <intrin.h>


Si solo desea SIMD portátil, use #include <immintrin.h>

MSVC, ICC y gcc / clang (y otros compiladores como Sun, creo) son compatibles con este encabezado para los intrínsecos SIMD documentados por el único buscador / herramienta de búsqueda de intrínsecos de Intel: https://software.intel.com/sites/landingpage/IntrinsicsGuide / /

Gunther Piez
fuente
No estaba seguro, si las versiones más nuevas podrían ... De todos modos, siempre que gcc, icc y clang lo tengan, está bien usarlo, creo :-)
Gunther Piez
55
MSVC no tiene <x86intrin.h>, pero <intrin.h>logra un efecto similar. Todavía necesita compilación condicional, por supuesto. :-(
Cody Gray
Todos los principales compiladores x86 tienen #include <immintrin.h>. Úselo para intrínsecos SIMD. Solo necesita el compilador aún más grande (y un poco más lento para el compilador) x86intrin.ho intrin.hsi necesita cosas como intrínsecos de rotación de enteros / escaneo de bits (aunque Intel documenta algunos de ellos como disponibles immintrin.h en su guía de intrínsecos ).
Peter Cordes
IIRC, hay algunos intrínsecos no SIMD que Intel documenta como inmintrin.h, pero que gcc, clang y / o MSVC solo tienen en x86intrin.h/ intrin.hpero no en immintrin.h.
Peter Cordes
56

El nombre del encabezado depende de su compilador y arquitectura de destino.

  • Para Microsoft C ++ (dirigido a x86, x86-64 o ARM) y el compilador Intel C / C ++ para uso de Windows intrin.h
  • Para gcc / clang / icc objetivo x86 / x86-64 uso x86intrin.h
  • Para gcc / clang / armcc apuntando a ARM con NEON use arm_neon.h
  • Para gcc / clang / armcc apuntando a ARM con WMMX use mmintrin.h
  • Para gcc / clang / xlcc dirigido a PowerPC con VMX (también conocido como Altivec) y / o VSX uso altivec.h
  • Para gcc / clang apuntando a PowerPC con uso SPE 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
Marat Dukhan
fuente
Aquí hay más para agregar a su lista: en UltraSPARC + VIS con gcc, use visintrin.h; Si tiene VSDK de Sun, vis.h ofrece un conjunto diferente de intrínsecos. Puede encontrar documentos aquí: GCC VIS incorporados , guía del usuario de Sun VIS .
onitake
44

De esta página

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

Por lo tanto, en general, puede incluir immintrin.hpara obtener todas las extensiones de Intel, o x86intrin.hsi lo desea todo, incluido _bit_scan_forwardy _rdtsc, así como todos los vectores intrínsecos incluyen solo AMD. Si está en contra de incluir más de lo que realmente necesita, puede elegir la inclusión correcta mirando la tabla.

x86intrin.hes la forma recomendada de obtener intrínsecos para AMD XOP (solo CPU Bulldozer, ni siquiera futuras CPU AMD) , en lugar de tener su propio encabezado.

Algunos compiladores seguirán generando mensajes de error si usa intrínsecos para conjuntos de instrucciones que no ha habilitado (por ejemplo, _mm_fmadd_pssin habilitar fma, incluso si incluye immintrin.hy habilita AVX2).

RubenLaguna
fuente
1
smmintrin(SSE4.1) es Penryn (45nm Core2), no Nehalem ("i7"). ¿Podemos dejar de usar "i7" como nombre de arquitectura? No tiene sentido ahora que Intel ha seguido usándolo para la familia SnB .
Peter Cordes
immintrin.hno parece incluir _popcnt32y _popcnt64(¡no debe confundirse con los de popcntintrin.h!) intrínsecos en GCC 9.1.0. Entonces parece que x86intrin.htodavía tiene un propósito.
Thom Wiggers
12

Como han indicado muchas de las respuestas y comentarios, <x86intrin.h>es el encabezado completo para intrínsecos SIMD x86 [-64]. También proporciona instrucciones de soporte intrínsecas para otras extensiones ISA. gcc, clangy icctodos se han decidido por esto. Necesitaba investigar un poco sobre las versiones que admiten el encabezado, y pensé que podría ser útil enumerar algunos hallazgos ...

  • gcc : el soporte para la x86intrin.hprimera aparece en gcc-4.5.0. La gcc-4serie de lanzamiento ya no se mantiene, mientras gcc-6.xque la serie de lanzamiento estable actual . gcc-5También introdujo la __has_includeextensión presente en todos los clang-3.xlanzamientos. gcc-7está en prelanzamiento (prueba de regresión, etc.) y siguiendo el esquema de versiones actual, se lanzará como gcc-7.1.0.

  • Clang : x86intrin.hparece haber sido compatible con todas las clang-3.xversiones. La última versión estable es clang (LLVM) 3.9.1. La rama de desarrollo es clang (LLVM) 5.0.0. No está claro qué pasó con la 4.xserie.

  • Clan de Apple : molestamente, el versionado de Apple no se corresponde con el de los LLVMproyectos. Dicho esto, el lanzamiento actual: clang-800.0.42.1se basa en LLVM 3.9.0. La primera LLVM 3.0versión basada parece estar de Apple clang 2.1vuelta Xcode 4.1. LLVM 3.1primero aparece con Apple clang 3.1(una coincidencia numérica) en Xcode 4.3.3.

    Apple también define __apple_build_version__por ejemplo, 8000042. Este parece ser el esquema 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.

Por lo tanto, cualquier versión reciente de clang, incluidas las versiones de Apple, no debería tener problemas 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 realmente no puede confiar es usar las __GNUC__versiones clang. La versión está, por razones históricas, estancada 4.2.1. Una versión que precede al x86intrin.hencabezado. De vez en cuando es útil para, por ejemplo, extensiones simples de GNU C que han seguido siendo compatibles con versiones anteriores.

  • icc : por lo que puedo decir, el x86intrin.hencabezado es compatible desde al menos Intel C ++ 16.0. La prueba de la versión de puede realizarse con: #if (__INTEL_COMPILER >= 1600). Esta versión (y posiblemente versiones anteriores) también proporciona soporte para la __has_includeextensión.

  • MSVC : Parece que MSVC++ 12.0 (Visual Studio 2013)es la primera versión que proporciona el intrin.hencabezado, no x86intrin.h ... esto sugiere: #if (_MSC_VER >= 1800)como una prueba de versión. Por supuesto, si está intentando escribir código que sea portátil en todos estos compiladores diferentes, el nombre del encabezado en esta plataforma será el menor de sus problemas.

Brett Hale
fuente