Hangi başlık dosyaları farklı x86 SIMD komut seti uzantıları (MMX, SSE, AVX, ...) için içsel bilgiler sağlar? İnternette böyle bir liste bulmak imkansız görünüyor. Yanlışsam düzelt.
Hangi başlık dosyaları farklı x86 SIMD komut seti uzantıları (MMX, SSE, AVX, ...) için içsel bilgiler sağlar? İnternette böyle bir liste bulmak imkansız görünüyor. Yanlışsam düzelt.
Yanıtlar:
Bu günlerde normalde sadece eklemelisiniz <immintrin.h>
. Her şeyi içerir.
GCC, clang talimatlar için derleme zamanında etkinleştirmediğinizden intrinsics kullanmayasın (örneğin ile -march=native
veya -mavx2 -mbmi2 -mpopcnt -mfma -mcx16 -mtune=znver1
ya da her neyse.)
MSVC ve ICC, derleme zamanında hiçbir şeyi etkinleştirmeden içsel bilgileri kullanmanıza izin verir, ancak yine de AVX intrinsiklerini kullanmadan önce AVX'i etkinleştirmelisiniz.
Tarihsel olarak ( immintrin.h
her şeyi içeri çekmeden önce ), istediğiniz en yüksek iç bilgiler için manuel olarak bir başlık eklemeniz gerekiyordu.
Bu, MSVC ve ICC'de, gerek duymak istemediğiniz komut setlerini kullanmaktan kendinizi alıkoymak için hala yararlı olabilir.
<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
Tüm öncekilere bu çekimlerden biri dahil (yalnızca AMD için SSE4A hariç: immintrin.h
bunu içeri çekmiyor)
Bazı derleyicilerin <zmmintrin.h>
AVX512 için de vardır .
<zmmintrin.h>
Doğrudan dahil etmeyin ; gcc bunu bile sağlamaz. Sadece<immintrin.h>
veya daha eksiksiz olanı kullanın<x86intrin.h>
. Bu yanıt, SSE'nin daha yeni sürümleri için iç bilgi eklemekten kasıtlı olarak kaçınmadığınız sürece, temelde geçersizdir, çünkü derleyiciniz SSE2 için derleme yaparken bir SSE4.1 talimatı kullandığınızda şikayet etmez. (gcc / çınlama yok . Sadece onlar için immintrin.h kullanmalıdır nedenle, şikayet başkaları hakkında IDK.)
GCC / clang'da, yalnızca
#include <x86intrin.h>
gibi -march=haswell
veya sadece derleyici anahtarlarına göre etkinleştirilen tüm SSE / AVX başlıklarını içerecektir -march=native
. Ek olarak, bazı x86'ya özgü talimatlar bswap
veya ror
içsel olarak kullanılabilir hale gelir.
Bu başlığın MSVC eşdeğeri <intrin.h>
Yalnızca taşınabilir SIMD istiyorsanız, #include <immintrin.h>
MSVC, ICC ve gcc / clang (ve sanırım Sun gibi diğer derleyiciler), Intel'in tek dahili bulucu / arama aracı tarafından belgelenen SIMD içsel bilgileri için bu başlığı destekler: https://software.intel.com/sites/landingpage/IntrinsicsGuide /
<x86intrin.h>
, ancak <intrin.h>
benzer bir etki yaratır. Elbette hala koşullu derlemeye ihtiyacınız var. :-(
#include <immintrin.h>
. SIMD içselleri için bunu kullanın. Yalnızca daha büyük olana (ve derleyiciye biraz daha yavaş) ihtiyacınız varsa x86intrin.h
veya intrin.h
tamsayı döndürme / bit tarama içselleri gibi şeylere ihtiyacınız varsa (Intel bunlardan bazılarını immintrin.h
içsel kılavuzunda mevcut olarak belgelese de ).
x86intrin.h
/ intrin.h
ama değil de immintrin.h
.
Başlık adı, derleyicinize ve hedef mimarinize bağlıdır.
intrin.h
x86intrin.h
arm_neon.h
mmintrin.h
altivec.h
spe.h
Tüm bu durumları koşullu ön işleme yönergeleriyle halledebilirsiniz:
#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
Bu sayfadan
+----------------+------------------------------------------------------------------------------------------+
| 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 |
+----------------+------------------------------------------------------------------------------------------+
Dolayısıyla, genel olarak, immintrin.h
tüm Intel uzantılarını almak için dahil edebilirsiniz veya ve x86intrin.h
dahil olmak üzere her şeyi istiyorsanız, tüm vektör içselleri yalnızca AMD olanları içerir. Gerçekte ihtiyacınız olandan daha fazlasını dahil etmeye karşıysanız, tabloya bakarak doğru dahil etmeyi seçebilirsiniz._bit_scan_forward
_rdtsc
x86intrin.h
kendi başlığına sahip olmak yerine AMD XOP için (yalnızca Buldozer, hatta gelecekteki AMD CPU'lar değil ) içsel bilgiler edinmenin önerilen yoludur .
Etkinleştirmediğiniz komut kümeleri için içsel kullanırsanız (örneğin _mm_fmadd_ps
, AVX2'yi dahil immintrin.h
etseniz ve etkinleştirseniz bile fma'yı etkinleştirmeden) bazı derleyiciler yine de hata mesajları üretecektir .
smmintrin
(SSE4.1) Penryn'dir (45nm Çekirdek2), Nehalem ("i7") değil. Mimari adı olarak "i7" yi kullanmayı bırakabilir miyiz? Intel'in SnB ailesi için kullanmaya devam etmesi artık anlamsız .
immintrin.h
GCC 9.1.0'da içsel bilgiler içermiyor _popcnt32
ve _popcnt64
(içindekilerle karıştırılmayacak popcntintrin.h
!) görünmüyor . Yani x86intrin.h
hala bir amaca hizmet ediyor gibi görünüyor .
Cevaplar ve yorumlar birçok belirttiğimiz gibi, <x86intrin.h>
olduğu x86 [-64] SIMD intrinsics için kapsamlı başlığı. Ayrıca, diğer ISA uzantıları için içsel destekleyici talimatlar sağlar. , ve hepsi bu konuda kararlaştırdı. Başlığı destekleyen sürümlerde biraz araştırma yapmam gerekiyordu ve bazı bulguları listelemenin faydalı olabileceğini düşündüm ...gcc
clang
icc
gcc : x86intrin.h
ilk için destek içinde görünür gcc-4.5.0
. gcc-4
Salma serisi artık ise, muhafaza ediliyor gcc-6.x
olup , mevcut kararlı açma dizisi. gcc-5
ayrıca __has_include
tüm clang-3.x
sürümlerde bulunan uzantıyı tanıttı . gcc-7
ön sürümde (regresyon testi, vb.) ve mevcut sürüm oluşturma şemasını takiben, olarak yayınlanacaktır gcc-7.1.0
.
clang : x86intrin.h
tüm clang-3.x
sürümler için desteklendiği görülüyor . En son kararlı sürüm clang (LLVM) 3.9.1
. Geliştirme dalı clang (LLVM) 5.0.0
. Diziye ne olduğu net değil 4.x
.
Apple clang : can sıkıcı bir şekilde, Apple'ın sürüm belirlemesi LLVM
projelerinkiyle uyuşmuyor . Bununla birlikte, mevcut sürüm: clang-800.0.42.1
dayanmaktadır LLVM 3.9.0
. İlk LLVM 3.0
tabanlı sürüm Apple clang 2.1
geri dönüyor gibi görünüyor Xcode 4.1
. LLVM 3.1
ilk olarak içinde Apple clang 3.1
(sayısal bir tesadüf) ile görünür Xcode 4.3.3
.
Apple ayrıca __apple_build_version__
örneğin, tanımlar 8000042
. Bu, mevcut en kararlı, kesinlikle artan sürüm oluşturma şeması gibi görünüyor. Eski derleyicileri desteklemek istemiyorsanız, bu değerlerden birini minimum gereksinim yapın.
Bu clang
nedenle, Apple sürümleri de dahil olmak üzere son sürümlerin herhangi bir sorunu olmamalıdır x86intrin.h
. Tabii ki, aşağıdakilerle birlikte gcc-5
her zaman kullanabilirsiniz:
#if defined (__has_include) && (__has_include(<x86intrin.h>))
#include <x86intrin.h>
#else
#error "upgrade your compiler. it's free..."
#endif
Gerçekten güvenemeyeceğiniz bir numara, içindeki __GNUC__
sürümleri kullanmaktır clang
. Versiyonlama, tarihsel nedenlerden dolayı, takılıp kalmıştır 4.2.1
. Başlıktan önce gelen bir sürüm x86intrin.h
. Zaman zaman, örneğin geriye doğru uyumlu kalan basit GNU C uzantıları için yararlıdır.
icc : Anladığım kadarıyla x86intrin.h
başlık en azından Intel C ++ 16.0'dan beri destekleniyor. Sürüm testinde tarafından gerçekleştirilen edebilirsiniz: #if (__INTEL_COMPILER >= 1600)
. Bu sürüm (ve muhtemelen daha önceki sürümler) ayrıca __has_include
uzantı için destek sağlar .
MSVC : Görünüşe göre MSVC++ 12.0 (Visual Studio 2013)
bu intrin.h
başlık sağlayan ilk sürüm - değil x86intrin.h
... bu şunu öneriyor: #if (_MSC_VER >= 1800)
bir sürüm testi olarak. Elbette, tüm bu farklı derleyiciler arasında taşınabilir bir kod yazmaya çalışıyorsanız, bu platformdaki başlık adı sorunlarınızın en küçüğü olacaktır.
#include <x86intrin.h>
ihtiyacınız olan her şeyi çekebilirsiniz .