File di intestazione per x86 SIMD intrinseca

Quali file di intestazione forniscono gli elementi intrinseci per le diverse estensioni del set di istruzioni SIMX x86 (MMX, SSE, AVX, …)? Sembra imansible trovare una tale lista online. Correggimi se sbaglio.

 MMX  SSE  SSE2  SSE3  SSSE3  SSE4.1  SSE4.2  SSE4A  AES  AVX  AVX512 

Se usi solo

 #include  

includerà tutte le intestazioni SSE / AVX che sono abilitate in base agli switch del compilatore come -march=corei7 o just -march=native . Inoltre alcune istruzioni specifiche per x86 come bswap o ror diventano disponibili come intrinseche.

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

  • Per Microsoft C ++ (targeting x86, x86-64 o ARM) e Intel C / C ++ Compiler per Windows utilizzare intrin.h
  • Per gcc / clang / icc targeting x86 / x86-64 usa x86intrin.h
  • Per ARM di gcc / clang / armcc con NEON usare arm_neon.h
  • Per ARM gcc / clang / armcc con WMMX usa mmintrin.h
  • Per gcc / clang / xlcc il targeting per PowerPC con VMX (noto anche come Altivec) e / o VSX usa altivec.h
  • Per gcc / clang, il targeting per PowerPC con SPE utilizza spe.h

Puoi gestire tutti questi casi con direttive di pre-elaborazione condizionale:

 #if defined(_MSC_VER) /* Microsoft C/C++-compatible compiler */ #include  #elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) /* GCC-compatible compiler, targeting x86/x86-64 */ #include  #elif defined(__GNUC__) && defined(__ARM_NEON__) /* GCC-compatible compiler, targeting ARM with NEON */ #include  #elif defined(__GNUC__) && defined(__IWMMXT__) /* GCC-compatible compiler, targeting ARM with WMMX */ #include  #elif (defined(__GNUC__) || defined(__xlC__)) && (defined(__VEC__) || defined(__ALTIVEC__)) /* XLC or GCC-compatible compiler, targeting PowerPC with VMX/VSX */ #include  #elif defined(__GNUC__) && defined(__SPE__) /* GCC-compatible compiler, targeting PowerPC with SPE */ #include  #endif 

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, è ansible includere immintrin.h per ottenere tutte le estensioni Intel o x86intrin.h se si desidera tutto, inclusi _bit_scan_forward e _rdtsc , così come tutti gli elementi intrinseci vettoriali includono quelli solo AMD. Se sei contrario a includere più che hai effettivamente bisogno allora puoi scegliere l’inclusione giusta guardando il tavolo.

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

Alcuni compilatori genereranno ancora messaggi di errore se si utilizzano intrinsecamente insiemi di istruzioni non abilitati (ad es. _mm_fmadd_ps senza abilitare fma, anche se si include immintrin.h e abilitato AVX2).

Come molte delle risposte e dei commenti hanno dichiarato, è l’ intestazione completa per x86 [-64] SIMD intrinseca. Fornisce inoltre istruzioni di supporto intrinseche per altre estensioni ISA. gcc , clang e icc sono tutti accordati su questo. Avevo bisogno di fare un po ‘di ricerca sulle versioni che supportano l’intestazione, e ho pensato che sarebbe stato utile elencare alcuni risultati …

  • gcc : il supporto per x86intrin.h appare per la prima volta in gcc-4.5.0 . La serie di rilascio gcc-4 non viene più mantenuta, mentre gcc-6.x è la serie di rilascio stabile corrente . gcc-5 anche introdotto l’estensione __has_include presente in tutte le versioni di clang-3.x . gcc-7 è in pre-release (test di regressione, ecc.) e seguendo lo schema di versioning corrente, sarà rilasciato come gcc-7.1.0 .

  • clang : x86intrin.h sembra essere stato supportato per tutte le versioni di clang-3.x . L’ultima versione stabile è clang (LLVM) 3.9.1 . Il ramo di sviluppo è clang (LLVM) 5.0.0 . Non è chiaro cosa sia successo alla serie 4.x

  • Apple clang : fastidiosamente, il versioning di Apple non corrisponde a quello dei progetti LLVM . Detto questo, la versione corrente: clang-800.0.42.1 , è basata su LLVM 3.9.0 . La prima versione basata su LLVM 3.0 sembra essere Apple clang 2.1 in Xcode 4.1 . LLVM 3.1 appare per la prima volta con Apple clang 3.1 (una coincidenza numerica) in Xcode 4.3.3 .

    Apple definisce anche __apple_build_version__ eg, 8000042 . Questo sembra lo schema di versioning più stabile e strettamente in ascesa disponibile. Se non si desidera supportare i compilatori legacy, rendere uno di questi valori un requisito minimo.

Nessuna versione recente di clang , incluse le versioni Apple, non dovrebbe pertanto presentare problemi con x86intrin.h . Ovviamente, insieme a gcc-5 , puoi sempre usare quanto segue:

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

Un trucco su cui non puoi fare affidamento è usare le versioni __GNUC__ in clang . Il versioning è, per ragioni storiche, bloccato a 4.2.1 . Una versione che precede l’intestazione x86intrin.h . È occasionalmente utile per, per esempio, semplici estensioni GNU C che sono rimaste compatibili all’indietro.

  • icc : per quanto posso dire, l’intestazione x86intrin.h è supportata almeno da Intel C ++ 16.0. Il test della versione può essere eseguito con: #if (__INTEL_COMPILER >= 1600) . Questa versione (e probabilmente anche versioni precedenti) fornisce anche il supporto per l’estensione __has_include .

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