Câu trả lời:
Những ngày này bạn thường chỉ nên bao gồm <immintrin.h>
. Nó bao gồm tất cả mọi thứ.
GCC và clang sẽ ngăn bạn sử dụng nội tại cho các hướng dẫn bạn chưa bật trong thời gian biên dịch (ví dụ: với -march=native
hoặc-mavx2 -mbmi2 -mpopcnt -mfma -mcx16 -mtune=znver1
hoặc bất cứ điều gì.)
MSVC và ICC sẽ cho phép bạn sử dụng nội tại mà không cần bật bất cứ thứ gì vào thời gian biên dịch, nhưng bạn vẫn nên bật AVX trước khi sử dụng nội tại AVX.
Trong lịch sử (trước khi immintrin.h
kéo mọi thứ), bạn phải bao gồm một tiêu đề theo cách thủ công cho mức độ nội tại cao nhất bạn muốn.
Điều này có thể vẫn hữu ích với MSVC và ICC để ngăn bạn sử dụng các bộ hướng dẫn mà bạn không muốn yêu cầu.
<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
Bao gồm một trong những lần kéo này trong tất cả các lần kéo trước (trừ SSE4A chỉ có AMD: immintrin.h
không kéo theo)
Một số trình biên dịch cũng có <zmmintrin.h>
cho AVX512.
<zmmintrin.h>
trực tiếp; gcc thậm chí không cung cấp nó. Chỉ cần sử dụng<immintrin.h>
hoặc thậm chí nhiều hơn nữa <x86intrin.h>
. Câu trả lời này về cơ bản đã lỗi thời, trừ khi bạn cố tình tránh bao gồm nội tại cho các phiên bản SSE mới hơn vì trình biên dịch của bạn không phàn nàn khi bạn sử dụng lệnh SSE4.1 trong khi biên dịch cho SSE2. (gcc / clang làm phàn nàn, vì vậy bạn chỉ nên sử dụng imintrin.h cho họ. IDK về người khác.)
Trên GCC / clang, nếu bạn chỉ sử dụng
#include <x86intrin.h>
nó sẽ bao gồm tất cả các tiêu đề SSE / AVX được kích hoạt theo các chuyển đổi trình biên dịch như -march=haswell
hoặc chỉ -march=native
. Ngoài ra, một số hướng dẫn cụ thể x86 như bswap
hoặc ror
trở nên khả dụng dưới dạng nội tại.
MSVC tương đương với tiêu đề này <intrin.h>
Nếu bạn chỉ muốn SIMD di động, hãy sử dụng #include <immintrin.h>
Tất cả MSVC, ICC và gcc / clang (và các trình biên dịch khác như Sun tôi nghĩ) đều hỗ trợ tiêu đề này cho nội dung SIMD được ghi lại bởi công cụ tìm kiếm / tìm kiếm nội tại của Intel: https://software.intel.com/sites/landingpage/IntrinsicsGuide /
<x86intrin.h>
, nhưng <intrin.h>
đạt được hiệu quả tương tự. Bạn vẫn cần biên soạn có điều kiện, tất nhiên. :-(
#include <immintrin.h>
. Sử dụng điều đó cho nội tại SIMD. Bạn chỉ cần trình biên dịch lớn hơn (và chậm hơn một chút) x86intrin.h
hoặc intrin.h
nếu bạn cần những thứ như nội tại xoay số nguyên / quét bit (mặc dù Intel ghi lại một số trong những immintrin.h
hướng dẫn có sẵn trong hướng dẫn nội tại của chúng ).
x86intrin.h
/ intrin.h
nhưng không có trong immintrin.h
.
Tên tiêu đề phụ thuộc vào trình biên dịch và kiến trúc đích của bạn.
intrin.h
x86intrin.h
arm_neon.h
mmintrin.h
altivec.h
spe.h
Bạn có thể xử lý tất cả các trường hợp này bằng các chỉ thị tiền xử lý có điều kiện:
#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
Từ trang này
+----------------+------------------------------------------------------------------------------------------+
| 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 |
+----------------+------------------------------------------------------------------------------------------+
Vì vậy, nói chung, bạn chỉ có thể bao gồm immintrin.h
để có được tất cả các tiện ích mở rộng của Intel hoặc x86intrin.h
nếu bạn muốn mọi thứ, bao gồm _bit_scan_forward
và_rdtsc
, cũng như tất cả các nội tại vectơ bao gồm chỉ có AMD. Nếu bạn chống lại bao gồm nhiều hơn những gì bạn thực sự cần thì bạn có thể chọn đúng bao gồm bằng cách nhìn vào bảng.
x86intrin.h
là cách được đề xuất để có được nội tại cho AMD XOP (chỉ dành cho Bulldozer, thậm chí không phải CPU AMD trong tương lai) , thay vì có tiêu đề riêng.
Một số trình biên dịch vẫn sẽ tạo thông báo lỗi nếu bạn sử dụng nội tại cho các tập lệnh mà bạn chưa kích hoạt (ví dụ: _mm_fmadd_ps
không bật fma, ngay cả khi bạn bao gồm immintrin.h
và bật AVX2).
smmintrin
(SSE4.1) là Penryn (45nm Core2), không phải Nehalem ("i7"). Chúng ta có thể ngừng sử dụng "i7" làm tên kiến trúc không? Bây giờ thật vô nghĩa khi Intel tiếp tục sử dụng nó cho gia đình SnB .
immintrin.h
không xuất hiện để bao gồm _popcnt32
và _popcnt64
(không bị nhầm lẫn với popcntintrin.h
nội tại!) trên GCC 9.1.0. Vì vậy, nó xuất hiện x86intrin.h
vẫn phục vụ một mục đích.
Như nhiều câu trả lời và ý kiến đã nêu, <x86intrin.h>
là những tiêu đề toàn diện cho x86 [-64] intrinsics SIMD. Nó cũng cung cấp các hướng dẫn hỗ trợ nội tại cho các phần mở rộng khác của ISA. gcc
, clang
và icc
đã giải quyết tất cả về điều này. Tôi cần thực hiện một số hoạt động đào trên các phiên bản hỗ trợ tiêu đề và nghĩ rằng có thể hữu ích khi liệt kê một số phát hiện ...
gcc : hỗ trợ cho x86intrin.h
lần đầu tiên xuất hiện trong gcc-4.5.0
. Các gcc-4
loạt phát hành không còn được duy trì, trong khi gcc-6.x
là hiện tại loạt phát hành ổn định . gcc-5
cũng giới thiệu __has_include
phần mở rộng có mặt trong tất cả các clang-3.x
bản phát hành. gcc-7
là trong bản phát hành trước (kiểm tra hồi quy, v.v.) và theo sơ đồ phiên bản hiện tại, sẽ được phát hành dưới dạng gcc-7.1.0
.
kêu vang :x86intrin.h
dường như đã được hỗ trợ cho tất cả các clang-3.x
bản phát hành. Bản phát hành ổn định mới nhất là clang (LLVM) 3.9.1
. Các ngành phát triển là clang (LLVM) 5.0.0
. Không rõ chuyện gì đã xảy ra với bộ 4.x
truyện.
Apple clang : thật khó chịu, phiên bản của Apple không tương ứng với các LLVM
dự án. Điều đó nói rằng, bản phát hành hiện tại : clang-800.0.42.1
, được dựa trên LLVM 3.9.0
. LLVM 3.0
Phiên bản dựa trên đầu tiên dường như Apple clang 2.1
trở lại Xcode 4.1
. LLVM 3.1
lần đầu tiên xuất hiện vớiApple clang 3.1
(một sự trùng hợp số) trong Xcode 4.3.3
.
Apple cũng định nghĩa __apple_build_version__
ví dụ 8000042
. Điều này có vẻ như về sơ đồ tăng dần ổn định, nghiêm ngặt nhất có sẵn. Nếu bạn không muốn hỗ trợ trình biên dịch cũ, hãy đặt một trong những giá trị này thành một yêu cầu tối thiểu.
Do đó, mọi phiên bản gần đây clang
, bao gồm cả các phiên bản của Apple, không có vấn đề gì x86intrin.h
. Tất nhiên, cùng với gcc-5
, bạn luôn có thể sử dụng như sau:
#if defined (__has_include) && (__has_include(<x86intrin.h>))
#include <x86intrin.h>
#else
#error "upgrade your compiler. it's free..."
#endif
Một mẹo bạn không thể thực sự dựa vào là sử dụng __GNUC__
phiên bản clang
. Phiên bản là, vì lý do lịch sử, bị mắc kẹt tại 4.2.1
. Một phiên bản đi trước x86intrin.h
tiêu đề. Đôi khi, nó hữu ích cho các phần mở rộng GNU C đơn giản vẫn tương thích ngược.
icc : theo như tôi có thể nói,x86intrin.h
tiêu đề được hỗ trợ vì ít nhất là Intel C ++ 16.0. Kiểm tra phiên bản có thể bằng cách thực hiện với : #if (__INTEL_COMPILER >= 1600)
. Phiên bản này (và có thể là các phiên bản trước đó) cũng cung cấp hỗ trợ cho __has_include
tiện ích mở rộng.
MSVC : Có vẻ như đây MSVC++ 12.0 (Visual Studio 2013)
là phiên bản đầu tiên cung cấp intrin.h
tiêu đề - không phải x86intrin.h
... điều này cho thấy: #if (_MSC_VER >= 1800)
dưới dạng thử nghiệm phiên bản. Tất nhiên, nếu bạn đang cố gắng viết mã di động trên tất cả các trình biên dịch khác nhau này, tên tiêu đề trên nền tảng này sẽ là vấn đề ít nhất của bạn.
#include <x86intrin.h>
kéo mọi thứ bạn cần.