Các tệp tiêu đề cho nội tại x86 SIMD


131

Những tệp tiêu đề nào cung cấp nội tại cho các phần mở rộng tập lệnh SIMD x86 khác nhau (MMX, SSE, AVX, ...)? Dường như không thể tìm thấy một danh sách như vậy trực tuyến. Sửa tôi nếu tôi sai.

Câu trả lời:


174

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=nativehoặ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.hké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.hkhông kéo theo)

Một số trình biên dịch cũng có <zmmintrin.h>cho AVX512.


62
Hoặc bạn có thể chỉ cần #include <x86intrin.h>kéo mọi thứ bạn cần.
Paul R

2
zmmintrin.h có nội tại AVX-512.
bắt đầu

3
Tại sao p, t, s và n cho SSE3 / SSSE3 / SSE4.1 và 4.2? Những nhân vật đó đại diện cho cái gì?
phuclv

5
@ LưuViênPhúc SSE3 = Chọn trước hướng dẫn mới, SSSE3 = Tejas hướng dẫn mới. Tôi nghĩ SSE4.2 và AES đề cập đến họ bộ xử lý mà họ đã được giới thiệu trên (Nehalem và West 4.0.3)
Drew McGowen

14
Đừng bao gồm <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.)
Peter Cordes

76

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=haswellhoặc chỉ -march=native. Ngoài ra, một số hướng dẫn cụ thể x86 như bswaphoặc rortrở 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 /


Tôi không chắc chắn, nếu các phiên bản mới hơn có thể ... Dù sao, miễn là gcc, icc và clang có nó, tôi nghĩ sẽ ổn thôi :-)
Gunther Piez

5
MSVC không có <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. :-(
Cody Grey

Tất cả các trình biên dịch x86 chính có #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.hhoặc intrin.hnế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 ).
Peter Cordes

IIRC, có một số nội tại không phải SIMD mà Intel ghi nhận là trong imintrin.h, nhưng gcc, clang và / hoặc MSVC chỉ có trong x86intrin.h/ intrin.hnhưng không có trong immintrin.h.
Peter Cordes

56

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.

  • Đối với Microsoft C ++ (nhắm mục tiêu x86, x86-64 hoặc ARM) và Trình biên dịch Intel C / C ++ cho Windows sử dụng intrin.h
  • Để nhắm mục tiêu gcc / clang / icc x86 / x86-64 x86intrin.h
  • Đối với gcc / clang / armcc nhắm mục tiêu ARM với NEON sử dụng arm_neon.h
  • Đối với gcc / clang / armcc nhắm mục tiêu ARM với WMMX, hãy sử dụng mmintrin.h
  • Để gcc / clang / xlcc nhắm mục tiêu PowerPC với VMX (còn gọi là Altivec) và / hoặc VSX sử dụng altivec.h
  • Đối với PowerPC nhắm mục tiêu gcc / clang với sử dụng SPE 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

Dưới đây là một số chi tiết khác để thêm vào danh sách của bạn: Trên UltraSPARC + VIS với gcc, hãy sử dụng visintrin.h; nếu bạn có VSDK của Sun, vis.h cung cấp một bộ nội tại khác. Tài liệu có thể được tìm thấy ở đây: Nội dung GCC VIS , hướng dẫn sử dụng Sun VIS .
trực

44

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.hnếu bạn muốn mọi thứ, bao gồm _bit_scan_forward_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.hlà 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.hvà bật AVX2).


1
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 .
Peter Cordes

immintrin.hkhông xuất hiện để bao gồm _popcnt32_popcnt64(không bị nhầm lẫn với popcntintrin.hnội tại!) trên GCC 9.1.0. Vì vậy, nó xuất hiện x86intrin.hvẫn phục vụ một mục đích.
Thom Wiggers

12

Như nhiều câu trả lời và ý kiến đã nêu, <x86intrin.h>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, clangiccđã 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.hlần đầu tiên xuất hiện trong gcc-4.5.0. Các gcc-4loạt phát hành không còn được duy trì, trong khi gcc-6.xhiện tại loạt phát hành ổn định . gcc-5cũng giới thiệu __has_includephần mở rộng có mặt trong tất cả các clang-3.xbản phát hành. gcc-7là 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.xbả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.xtruyện.

  • Apple clang : thật khó chịu, phiên bản của Apple không tương ứng với các LLVMdự á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.0Phiên bản dựa trên đầu tiên dường như Apple clang 2.1trở lại Xcode 4.1. LLVM 3.1lầ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.htiê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_includetiệ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.htiê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.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.