2012-06-27 6 views
98

¿Qué archivos de encabezado 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.Archivos de encabezado para x36 SIMD intrinsics

Respuesta

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

Creo que 'ammintrin.h' también tiene las instrucciones de XOP. – Mysticial

+47

O puede simplemente '#include ' que atrae todo lo que necesita. –

+2

zmmintrin.h tiene los intrínsecos AVX-512. – onitake

64

Si utiliza simplemente

#include <x86intrin.h> 

que incluirá todas las cabeceras SSE/AVX que se habilitan de acuerdo con 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.

+13

+1, también notaré que Visual C++ no tiene ese encabezado. – Mysticial

+0

No estaba seguro, si las versiones más nuevas podrían ... De todos modos mientras gcc, icc y clang lo tengan, está bien usarlo creo :-) – hirschhornsalz

+4

MSVC no tiene '', pero '' logra un efecto similar. Aún necesitas compilación condicional, por supuesto. :-( –

43

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

  • Para Microsoft C++ (focalización x86, x86-64 o ARM) e Intel C/C++ Compiler para Windows utilizar intrin.h
  • para GCC/ruido metálico/ICC x86 focalización/x86-64 utilizar x86intrin.h
  • Para gcc/sonido metálico/armcc brazo de direccionamiento con NEON utilizar arm_neon.h
  • Para gcc/sonido metálico/armcc orientación ARM con WMMX utilizar mmintrin.h
  • Para gcc/sonido metálico/xlcc orientación PowerPC con VMX (aka Altivec) y/o VSX utilizar altivec.h
  • para GCC/ruido metálico de orientación PowerPC con el uso de SPE spe.h

Puede manejar todos estos casos con las directivas de preprocesamiento condicionales:

#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

Aquí hay algo 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. La documentación se puede encontrar aquí: [GCC VIS construcciones internas] (https://gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc/SPARC-VIS-Built-in-Functions.html#SPARC-VIS-Built-in-Functions), [usuario de Sun VIS guía] (http://web.archive.org/web/20040221220512/http://www.sun.com/processors/vis/download/vsdk/visuserg.pdf). – onitake

28

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

Así que, en general, solo puede incluir immintrin.h para obtener todas las extensiones de Intel, o x86intrin.h si desea hing, que incluye _bit_scan_forward y _rdtsc, y todos los vectores intrínsecos incluyen solo 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 (Bulldozer-only, not even future AMD CPUs), en lugar de tener su propio encabezado.

Algunos compiladores seguirán generando mensajes de error si utiliza intrínsecos para conjuntos de instrucciones que no ha activado (por ejemplo, _mm_fmadd_ps sin habilitar fma, incluso si incluye immintrin.h y habilita AVX2).

+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] (http://stackoverflow.com/ preguntas/37361145/deoptimizing-a-program-for-the-pipeline-in-intel-sandybridge-family-cpus/37362225 # 37362225). –

5

Como muchas de las respuestas y comentarios han declarado, <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, y icc se han decidido por esto. Necesitaba investigar en las versiones que admiten el encabezado, y pensé que sería útil enumerar algunos hallazgos ...

  • gcc: soporte para x86intrin.h aparece por primera vez en gcc-4.5.0. La serie de versiones gcc-4 ya no se mantiene, mientras que gcc-6.x es la serie de versiones estables actual. gcc-5 también introdujo la extensión __has_include presente en todas las versiones clang-3.x. gcc-7 está en prelanzamiento (pruebas de regresión, etc.) y siguiendo el esquema de control de versiones actual, se lanzará como gcc-7.1.0.

  • sonido metálico: x86intrin.h parece haber contado con el apoyo de todos los comunicados de clang-3.x. 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 serie 4.x.

  • de Apple sonido metálico: molesto, control de versiones de Apple no se corresponde con la de los LLVM proyectos. Dicho esto, la versión actual: clang-800.0.42.1, se basa en LLVM 3.9.0. La primera versión basada en LLVM 3.0 parece ser Apple clang 2.1 en Xcode 4.1. LLVM 3.1 aparece por primera vez con Apple clang 3.1 (una coincidencia numérica) en Xcode 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, por lo tanto, debería tener ningún problema con x86intrin.h. Por supuesto, junto con gcc-5, siempre se puede utilizar el siguiente:

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

Un truco realmente no se puede confiar en la está usando las versiones __GNUC__ en clang. El control de versiones está, por razones históricas, atascado 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 yo puedo decir, la cabecera x86intrin.h es apoyado desde por lo menos 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 de proporcionar la cabecera intrin.h-nox86intrin.h ... esto sugiere: #if (_MSC_VER >= 1800) como una prueba de la 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.

Cuestiones relacionadas