File di intestazione per intrinseci x86 SIMD


131

Quali file di intestazione forniscono le informazioni intrinseche per le diverse estensioni del set di istruzioni SIMD x86 (MMX, SSE, AVX, ...)? Sembra impossibile trovare un simile elenco online. Correggimi se sbaglio.

Risposte:


174

In questi giorni dovresti normalmente includere solo <immintrin.h>. Include tutto.

GCC e clang ti impediranno di usare intrinseci per istruzioni che non hai abilitato in fase di compilazione (ad es. Con -march=nativeo -mavx2 -mbmi2 -mpopcnt -mfma -mcx16 -mtune=znver1o altro).

MSVC e ICC consentono di utilizzare intrinseche senza attivare nulla in fase di compilazione, ma è comunque dovrebbe consentire AVX prima di utilizzare intrinseche AVX.


Storicamente (prima immintrin.hdi inserire tutto), è stato necessario includere manualmente un'intestazione per il livello più elevato di elementi intrinseci desiderati.

Questo può essere ancora utile con MSVC e ICC per impedirti di usare le istruzioni che non desideri richiedere.

<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

Incluso uno di questi pull in tutti i precedenti (tranne SSE4A solo AMD: immintrin.hnon lo inserisce )

Alcuni compilatori hanno anche <zmmintrin.h>per AVX512.


62
Oppure puoi solo quello #include <x86intrin.h>che ti attira in tutto ciò che ti serve.
Paul R,

2
zmmintrin.h ha gli intrinseci AVX-512.
onitake,

3
Perché p, t, s e n per SSE3 / SSSE3 / SSE4.1 e 4.2? Cosa rappresentano quei personaggi?
phuclv,

5
@ LưuVĩnhPhúc SSE3 = Prescott nuove istruzioni, SSSE3 = Tejas nuove istruzioni. Penso che SSE4.2 e AES si riferiscano alla famiglia di processori su cui sono stati introdotti (Nehalem e Westmere)
Drew McGowen,

14
Non includere <zmmintrin.h>direttamente; gcc non lo fornisce nemmeno. Basta usare<immintrin.h> o anche il più completo <x86intrin.h>. Questa risposta è sostanzialmente obsoleta, a meno che tu non stia evitando intenzionalmente di includere elementi intrinseci per le nuove versioni di SSE perché il compilatore non si lamenta quando usi un'istruzione SSE4.1 durante la compilazione per SSE2. (gcc / clang si lamentano, quindi dovresti semplicemente usare immintrin.h per loro. IDK sugli altri.)
Peter Cordes,

76

Su GCC / clang, se usi solo

#include <x86intrin.h>

includerà tutte le intestazioni SSE / AVX che sono abilitate in base agli switch del compilatore come -march=haswello solo -march=native. Inoltre, alcune istruzioni specifiche x86 gradiscono bswapo rordiventano disponibili come intrinseche.


L'equivalente MSVC di questa intestazione <intrin.h>


Se vuoi solo un SIMD portatile, usa #include <immintrin.h>

MSVC, ICC e gcc / clang (e altri compilatori come Sun penso) supportano tutti questa intestazione per i intrinseci SIMD documentati dall'unico strumento di ricerca / ricerca di intrinseci di Intel: https://software.intel.com/sites/landingpage/IntrinsicsGuide /


Non ero sicuro, se le versioni più recenti potessero ... Comunque, fintanto che gcc, icc e clang ce l'hanno, va bene usare penso :-)
Gunther Piez,

5
MSVC non ha <x86intrin.h>, ma <intrin.h>ottiene un effetto simile. Hai ancora bisogno di compilazione condizionale, ovviamente. :-(
Cody Grey

Tutti i principali compilatori x86 hanno #include <immintrin.h>. Usalo per intrinseci SIMD. Hai solo bisogno di un formato ancora più grande (e leggermente più lento per il compilatore) x86intrin.ho intrin.hse hai bisogno di cose come i valori intrinseci di rotazione / scansione a bit (anche se Intel documenta alcuni di quelli disponibili immintrin.h nella loro guida ai valori intrinseci ).
Peter Cordes,

IIRC, ci sono alcuni intrinseci non SIMD che Intel documenta come in immintrin.h, ma che gcc, clang e / o MSVC hanno solo in x86intrin.h/ intrin.hma non in immintrin.h.
Peter Cordes,

56

Il nome dell'intestazione dipende dal compilatore e dall'architettura di destinazione.

  • Per Microsoft C ++ (targeting per x86, x86-64 o ARM) e compilatore Intel C / C ++ per Windows intrin.h
  • Per gcc / clang / icc targeting x86 / x86-64 utilizzare x86intrin.h
  • Per il targeting gcc / clang / armcc ARM con NEON utilizzare arm_neon.h
  • Per il targeting gcc / clang / armcc ARM con WMMX utilizzare mmintrin.h
  • Per il targeting gcc / clang / xlcc PowerPC con VMX (aka Altivec) e / o VSX utilizzare altivec.h
  • Per gcc / clang con targeting PowerPC con utilizzo SPE spe.h

È possibile gestire tutti questi casi con direttive di preelaborazione condizionali:

#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

Ecco alcuni altri da aggiungere al tuo elenco: su UltraSPARC + VIS con gcc, usa visintrin.h; se si dispone del VSDK di Sun, vis.h offre una serie diversa di elementi intrinseci. La documentazione è disponibile qui: built-in GCC VIS , guida dell'utente di Sun VIS .
onitake,

44

Da questa pagina

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

Quindi, in generale, puoi semplicemente includere immintrin.hper ottenere tutte le estensioni Intel, o x86intrin.hse vuoi tutto, inclusi _bit_scan_forwarde _rdtsc, così come tutti gli intrinseci vettoriali includono solo AMD. Se sei contrario a includere più cose di cui hai effettivamente bisogno, puoi scegliere l'inclusione giusta guardando il tavolo.

x86intrin.hè il modo consigliato per ottenere elementi intrinseci per AMD XOP (solo Bulldozer, nemmeno future CPU AMD) , piuttosto che avere una propria intestazione.

Alcuni compilatori genereranno comunque messaggi di errore se si utilizzano intrinseci per i set di istruzioni non abilitati (ad esempio _mm_fmadd_pssenza abilitare fma, anche se si include immintrin.he si abilita AVX2).


1
smmintrin(SSE4.1) è Penryn (45nm Core2), non Nehalem ("i7"). Possiamo smettere di usare "i7" come nome di architettura? Non ha senso ora che Intel abbia continuato a usarlo per la famiglia SnB .
Peter Cordes,

immintrin.hnon sembra includere _popcnt32e _popcnt64(da non confondere con quelli in popcntintrin.h!) intrinseci su GCC 9.1.0. Quindi sembra x86intrin.hancora servire a uno scopo.
Thom Wiggers,

12

Come molte delle risposte e dei commenti hanno affermato, <x86intrin.h>è l' intestazione completa per intrinseci x86 [-64] SIMD. Fornisce inoltre istruzioni di supporto intrinseco per altre estensioni ISA. gcc, clange icctutti si sono stabiliti su questo. Avevo bisogno di scavare sulle versioni che supportano l'intestazione e ho pensato che potesse essere utile elencare alcuni risultati ...

  • gcc : il supporto per il x86intrin.hprimo appare in gcc-4.5.0. La gcc-4serie di versioni non viene più mantenuta, mentre gcc-6.xè l' attuale serie di versioni stabili. gcc-5ha inoltre introdotto l' __has_includeestensione presente in tutte le clang-3.xversioni. gcc-7è in pre-release (test di regressione, ecc.) e seguendo l'attuale schema di versione, verrà rilasciato come gcc-7.1.0.

  • clang : x86intrin.hsembra essere stato supportato per tutte le clang-3.xversioni. L'ultima versione stabile è clang (LLVM) 3.9.1. Il ramo di sviluppo è clang (LLVM) 5.0.0. Non è chiaro cosa sia successo alla 4.xserie.

  • Clang di Apple : fastidiosamente, il versioning di Apple non corrisponde a quello dei LLVMprogetti. Detto questo, l'attuale versione:, clang-800.0.42.1si basa su LLVM 3.9.0. La prima LLVM 3.0versione basata sembra essere Apple clang 2.1tornata Xcode 4.1. LLVM 3.1appare per la prima volta Apple clang 3.1(una coincidenza numerica) in Xcode 4.3.3.

    Apple definisce anche __apple_build_version__ad es 8000042. Questo sembra lo schema di versione più stabile e rigorosamente crescente disponibile. Se non si desidera supportare compilatori legacy, impostare uno di questi valori come requisito minimo.

Qualsiasi versione recente di clang, comprese le versioni di Apple, non dovrebbe quindi avere problemi x86intrin.h. Naturalmente, insieme a gcc-5, puoi sempre usare quanto segue:

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

Un trucco su cui non puoi davvero fare affidamento è usare le __GNUC__versioni in clang. Il versioning è, per ragioni storiche, bloccato 4.2.1. Una versione che precede l' x86intrin.hintestazione. Occasionalmente è utile, diciamo, per semplici estensioni GNU C che sono rimaste compatibili con le versioni precedenti.

  • icc : per quanto ne so, l' x86intrin.hintestazione è supportata almeno da Intel C ++ 16.0. Il test versione può da eseguita con: #if (__INTEL_COMPILER >= 1600). Questa versione (e possibilmente versioni precedenti) fornisce anche supporto per l' __has_includeestensione.

  • MSVC : Sembra che MSVC++ 12.0 (Visual Studio 2013)sia la prima versione a fornire l' intrin.hintestazione, non x86intrin.h ... questo suggerisce: #if (_MSC_VER >= 1800)come test di versione. Naturalmente, se stai cercando di scrivere un codice portatile su tutti questi diversi compilatori, il nome dell'intestazione su questa piattaforma sarà l'ultimo dei tuoi problemi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.