File header mana yang menyediakan intrinsik untuk ekstensi set instruksi x86 SIMD yang berbeda (MMX, SSE, AVX, ...)? Tampaknya tidak mungkin menemukan daftar online seperti itu. Koreksi saya jika saya salah.
File header mana yang menyediakan intrinsik untuk ekstensi set instruksi x86 SIMD yang berbeda (MMX, SSE, AVX, ...)? Tampaknya tidak mungkin menemukan daftar online seperti itu. Koreksi saya jika saya salah.
Jawaban:
Hari-hari ini Anda biasanya hanya perlu memasukkan <immintrin.h>
. Itu termasuk semuanya.
GCC dan dentang akan menghentikan Anda dari menggunakan intrinsik untuk instruksi yang belum Anda aktifkan pada waktu kompilasi (misalnya dengan -march=native
atau -mavx2 -mbmi2 -mpopcnt -mfma -mcx16 -mtune=znver1
atau apa pun.)
MSVC dan ICC akan memungkinkan Anda menggunakan intrinsik tanpa mengaktifkan apa pun pada waktu kompilasi, tetapi Anda tetap harus mengaktifkan AVX sebelum menggunakan AVX intrinsics.
Secara historis (sebelum immintrin.h
menarik semuanya) Anda harus memasukkan header secara manual untuk level intrinsik tertinggi yang Anda inginkan.
Ini mungkin masih berguna dengan MSVC dan ICC untuk menghentikan diri Anda dari menggunakan set instruksi yang tidak Anda inginkan.
<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
Termasuk salah satu dari tarikan ini di semua yang sebelumnya (kecuali SSE4A khusus AMD: immintrin.h
tidak menarik itu)
Beberapa kompiler juga ada <zmmintrin.h>
untuk AVX512.
<zmmintrin.h>
secara langsung; gcc bahkan tidak menyediakannya. Cukup gunakan<immintrin.h>
atau bahkan lebih lengkap <x86intrin.h>
. Jawaban ini pada dasarnya sudah usang, kecuali jika Anda secara sengaja menghindari memasukkan intrinsik untuk versi SSE yang lebih baru karena kompiler Anda tidak mengeluh ketika Anda menggunakan instruksi SSE4.1 saat menyusun untuk SSE2. (Gcc / dentang memang mengeluh, jadi Anda harus menggunakan immintrin.h untuk mereka. IDK tentang orang lain.)
Pada GCC / dentang, jika Anda gunakan saja
#include <x86intrin.h>
itu akan mencakup semua header SSE / AVX yang diaktifkan sesuai dengan sakelar kompiler suka -march=haswell
atau adil -march=native
. Selain itu beberapa instruksi spesifik x86 suka bswap
atau ror
tersedia sebagai intrinsik.
Setara MSVC dari header ini <intrin.h>
Jika Anda hanya ingin SIMD portabel, gunakan #include <immintrin.h>
MSVC, ICC, dan gcc / dentang (dan kompiler lain seperti Sun, saya pikir) semuanya mendukung tajuk ini untuk intrinsik SIMD yang didokumentasikan oleh satu-satunya alat pencari / penelusuran intrinsik Intel: https://software.intel.com/sites/landingpage/IntrinsicsGuide /
<x86intrin.h>
, tetapi <intrin.h>
mencapai efek yang serupa. Anda masih membutuhkan kompilasi bersyarat, tentu saja. :-(
#include <immintrin.h>
. Gunakan itu untuk SIMD intrinsik. Anda hanya memerlukan kompiler yang bahkan lebih besar (dan sedikit lebih lambat) x86intrin.h
atau intrin.h
jika Anda memerlukan hal-hal seperti integer rotate / bit-scan intrinsik (walaupun Intel mendokumentasikan beberapa dari mereka yang tersedia di immintrin.h
dalam panduan intrinsik mereka ).
x86intrin.h
/ intrin.h
tetapi tidak di immintrin.h
.
Nama header tergantung pada kompiler dan arsitektur target Anda.
intrin.h
x86intrin.h
arm_neon.h
mmintrin.h
altivec.h
spe.h
Anda dapat menangani semua kasus ini dengan arahan preprocessing bersyarat:
#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
Dari halaman ini
+----------------+------------------------------------------------------------------------------------------+
| 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 |
+----------------+------------------------------------------------------------------------------------------+
Jadi secara umum Anda bisa memasukkan immintrin.h
untuk mendapatkan semua ekstensi Intel, atau x86intrin.h
jika Anda menginginkan semuanya, termasuk _bit_scan_forward
dan _rdtsc
, serta semua vektor intrinsik termasuk yang hanya AMD. Jika Anda menentang memasukkan lebih banyak yang sebenarnya Anda butuhkan, maka Anda dapat memilih yang benar termasuk dengan melihat tabel.
x86intrin.h
adalah cara yang disarankan untuk mendapatkan intrinsik untuk AMD XOP (hanya Bulldozer, bahkan untuk CPU AMD yang akan datang) , daripada memiliki header sendiri.
Beberapa kompiler masih akan menghasilkan pesan kesalahan jika Anda menggunakan intrinsik untuk set instruksi yang belum Anda aktifkan (mis. _mm_fmadd_ps
Tanpa mengaktifkan fma, bahkan jika Anda memasukkan immintrin.h
dan mengaktifkan AVX2).
smmintrin
(SSE4.1) adalah Penryn (45nm Core2), bukan Nehalem ("i7"). Bisakah kita berhenti menggunakan "i7" sebagai nama arsitektur? Tidak ada artinya sekarang karena Intel terus menggunakannya untuk keluarga SnB .
immintrin.h
tampaknya tidak termasuk _popcnt32
dan _popcnt64
(jangan disamakan dengan yang ada di popcntintrin.h
dalamnya!) intrinsik pada GCC 9.1.0. Jadi tampaknya x86intrin.h
masih memiliki tujuan.
Seperti banyak dari jawaban dan komentar telah menyatakan, <x86intrin.h>
adalah yang sundulan komprehensif untuk x86 [-64] SIMD intrinsik. Ini juga menyediakan instruksi pendukung intrinsik untuk ekstensi ISA lainnya. gcc
,, clang
dan icc
semuanya sudah sepakat. Saya perlu melakukan penggalian pada versi yang mendukung tajuk, dan saya pikir mungkin berguna untuk membuat daftar beberapa temuan ...
gcc : dukungan untuk x86intrin.h
pertama kali muncul di gcc-4.5.0
. The gcc-4
seri rilis tidak lagi dipertahankan, sedangkan gcc-6.x
adalah saat rilis stabil seri. gcc-5
juga memperkenalkan __has_include
hadiah ekstensi di semua clang-3.x
rilis. gcc-7
dalam pra-rilis (pengujian regresi, dll.) dan mengikuti skema versi saat ini, akan dirilis sebagai gcc-7.1.0
.
dentang : x86intrin.h
tampaknya telah didukung untuk semua clang-3.x
rilis. Rilis stabil terbaru adalah clang (LLVM) 3.9.1
. Cabang pengembangan adalah clang (LLVM) 5.0.0
. Tidak jelas apa yang terjadi pada 4.x
seri ini.
Dentang Apple : mengganggu, versi Apple tidak sesuai dengan LLVM
proyek. Yang mengatakan, rilis saat ini:, clang-800.0.42.1
didasarkan pada LLVM 3.9.0
. Versi LLVM 3.0
berbasis pertama tampaknya Apple clang 2.1
kembali Xcode 4.1
. LLVM 3.1
pertama kali muncul dengan Apple clang 3.1
(kebetulan numerik) di Xcode 4.3.3
.
Apple juga mendefinisikan __apple_build_version__
misalnya 8000042
,. Tampaknya ini tentang skema versi yang paling stabil dan ketat yang tersedia. Jika Anda tidak ingin mendukung kompiler lawas, jadikan salah satu dari nilai ini persyaratan minimum.
clang
Oleh karena itu, setiap versi terbaru , termasuk versi Apple, tidak akan memiliki masalah dengan x86intrin.h
. Tentu saja, bersama dengan gcc-5
, Anda selalu dapat menggunakan yang berikut:
#if defined (__has_include) && (__has_include(<x86intrin.h>))
#include <x86intrin.h>
#else
#error "upgrade your compiler. it's free..."
#endif
Satu trik yang tidak bisa Anda andalkan adalah menggunakan __GNUC__
versi di clang
. Versi ini, karena alasan historis, terjebak di 4.2.1
. Versi yang mendahului x86intrin.h
header. Ini kadang-kadang berguna untuk, katakanlah, ekstensi GNU C sederhana yang tetap kompatibel ke belakang.
icc : sejauh yang saya tahu, x86intrin.h
header didukung sejak setidaknya Intel C ++ 16.0. Tes Versi oleh dapat dilakukan dengan: #if (__INTEL_COMPILER >= 1600)
. Versi ini (dan mungkin versi sebelumnya) juga memberikan dukungan untuk __has_include
ekstensi.
MSVC : Tampaknya MSVC++ 12.0 (Visual Studio 2013)
ini adalah versi pertama yang menyediakan intrin.h
header - bukan x86intrin.h
... ini menyarankan: #if (_MSC_VER >= 1800)
sebagai tes versi. Tentu saja, jika Anda mencoba untuk menulis kode yang portabel di semua kompiler berbeda ini, nama header pada platform ini akan menjadi yang paling sedikit masalah Anda.
#include <x86intrin.h>
yang menarik semua yang Anda butuhkan.