Файли заголовків для внутрішніх технологій x86 SIMD


131

Які файли заголовків містять суттєві характеристики для різних розширень набору інструкцій SIM86 x86 (MMX, SSE, AVX, ...)? Здається, неможливо знайти такий список в Інтернеті. Виправте мене, якщо я помиляюся.

Відповіді:


174

У ці дні вам слід просто включити <immintrin.h>. Він включає все.

GCC і брязкіт зупинить вас від використання вбудованих засобів для отримання інструкцій ви не включили під час компіляції (наприклад , з допомогою -march=nativeабо -mavx2 -mbmi2 -mpopcnt -mfma -mcx16 -mtune=znver1чи будь інший .)

MSVC та ICC дозволять використовувати внутрішні символи, не дозволяючи нічого компілювати під час компіляції, але ви все одно повинні активувати AVX перед тим, як використовувати AVX вбудовані.


Історично (перш ніж immintrin.hвитягнути все) вам довелося вручну включити заголовок для найвищого рівня потрібних вам елементів.

Це все ще може бути корисно для MSVC та ICC, щоб не допустити використання наборів інструкцій, які ви не хочете вимагати.

<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

Включаючи один з цих витягів у всіх попередніх (крім SSD4A лише для AMD: immintrin.hне втягує це в)

Деякі компілятори також мають <zmmintrin.h>AVX512.


62
Або ви можете просто #include <x86intrin.h>витягнути все, що вам потрібно.
Пол Р

2
zmmintrin.h має властивості AVX-512.
онітак

3
Чому p, t, s і n для SSE3 / SSSE3 / SSE4.1 і 4.2? Що представляють ці персонажі?
phuclv

5
@ LưuVĩnhPhúc SSE3 = Prescott нові інструкції, SSSE3 = Tejas нові інструкції. Я думаю, що SSE4.2 і AES відносяться до сімейства процесорів, на яких вони були представлені (Негалем і Вестмер)
Дрю МакГовен

14
Не включайте <zmmintrin.h>безпосередньо; gcc навіть не надає. Просто використовуйте<immintrin.h> або навіть ще більш повне <x86intrin.h>. Ця відповідь в основному застаріла, якщо ви навмисно не уникаєте включення внутрішніх текстів для новіших версій SSE, оскільки ваш компілятор не скаржиться під час використання інструкції SSE4.1 під час компіляції для SSE2. (gcc / clang не скаржаться, тому вам просто слід використовувати immintrin.h для них. IDK про інших.)
Peter Cordes

76

На GCC / clang, якщо ви використовуєте просто

#include <x86intrin.h>

він буде включати всі заголовки SSE / AVX, які увімкнено відповідно до комутаторів компілятора, таких як -march=haswellабо просто -march=native. Крім того, деякі специфічні для x86 інструкції на кшталт bswapабо rorстають доступними як внутрішні матеріали.


Еквівалент MSVC цього заголовка <intrin.h>


Якщо ви просто хочете переносити SIMD, використовуйте #include <immintrin.h>

MSVC, ICC та gcc / clang (та інші компілятори, як-от Sun, я думаю) підтримують цей заголовок для вбудованих SIMD-файлів, задокументованих єдиним інструментом пошуку / пошуку інструменту Intel: https://software.intel.com/sites/landingpage/IntrinsicsGuide /


Я не був впевнений, якщо новіші версії можуть бути ... Як би там не було, поки у них є gcc, icc та
clang,

5
MSVC не має <x86intrin.h>, але <intrin.h>досягає подібного ефекту. Вам, звичайно, потрібна умовна збірка. :-(
Коді Грей

Усі основні компілятори x86 мають #include <immintrin.h>. Використовуйте це для внутрішніх технологій SIMD. Вам потрібен лише ще більший (і трохи повільніший для компілятора) x86intrin.hабо intrin.hякщо вам потрібні такі речі, як цілі внутрішні обертання / біт-сканування (хоча Intel документує деякі з них, як це доступно immintrin.h в їх посібнику з внутрішньої роботи ).
Пітер Кордес

IIRC, є деякі не SIMD-елементи, які Intel документи містять у immintrin.h, але які gcc, clang та / або MSVC мають лише в x86intrin.h/, intrin.hале не в immintrin.h.
Пітер Кордес

56

Назва заголовка залежить від компілятора та цільової архітектури.

  • Для Microsoft C ++ (орієнтація на x86, x86-64 або ARM) та компілятор Intel C / C ++ для Windows intrin.h
  • Для націлювання gcc / clang / icc використовуйте x86 / x86-64 x86intrin.h
  • Для націлювання gcc / clang / armcc на ARM з використанням NEON arm_neon.h
  • Для націлювання gcc / clang / armcc на ARM із використанням WMMX mmintrin.h
  • Для націлювання gcc / clang / xlcc на PowerPC з VMX (він же Altivec) та / або VSX altivec.h
  • Для націлювання gcc / clang на PowerPC із використанням SPE spe.h

Ви можете обробляти всі ці випадки умовними директивами попередньої обробки:

#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

Ось ще кілька, які можна додати до вашого списку: На UltraSPARC + VIS з gcc використовуйте visintrin.h; якщо у вас є VSDK Sun, vis.h пропонує інший набір внутрішніх даних. Документацію можна знайти тут: вбудовані GCC VIS , посібник користувача Sun VIS .
onitake

44

З цієї сторінки

+----------------+------------------------------------------------------------------------------------------+
|     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             |
+----------------+------------------------------------------------------------------------------------------+

Таким чином, загалом ви можете просто включити, immintrin.hщоб отримати всі розширення Intel, або, x86intrin.hякщо ви хочете, щоб все, в тому числі _bit_scan_forwardі _rdtsc, а також всі векторні вбудовані елементи включали лише AMD. Якщо ви проти включити більше того, що вам насправді потрібно, ви можете вибрати правильне включення, поглянувши на таблицю.

x86intrin.h- це рекомендований спосіб отримати властиві для AMD XOP (лише для Bulldozer, навіть не майбутніх процесорів AMD) , а не мати власний заголовок.

Деякі компілятори все ще будуть генерувати повідомлення про помилки, якщо ви використовуєте внутрішні символи для наборів інструкцій, які ви не ввімкнули (наприклад, _mm_fmadd_psбез включення fma, навіть якщо ви включите immintrin.hта ввімкнете AVX2).


1
smmintrin(SSE4.1) - це Пенрін (45nm Core2), а не Nehalem ("i7"). Чи можемо ми перестати використовувати "i7" як ім'я архітектури? Тепер безглуздо, коли Intel продовжує використовувати його для сімейства SnB .
Пітер Кордес

immintrin.hне включають _popcnt32і _popcnt64(не плутати з тими, що в popcntintrin.h!) внутрішніми елементами GCC 9.1.0. Отже, схоже, це x86intrin.hвсе ще служить цілі.
Том Віггерс

12

Оскільки багато відповідей і коментарі заявили, <x86intrin.h>є всеосяжним заголовком для x86 [-64] SIMD вбудованих функцій . Він також пропонує внутрішні тексти, що підтримують інструкції для інших розширень ISA. , і всі з цим погодилися. Мені потрібно було викопати кілька версій, які підтримують заголовок, і я подумав, що може бути корисним перерахувати деякі висновки ...gccclangicc

  • gcc : підтримка x86intrin.hпершого з'являється в gcc-4.5.0. Серія gcc-4випусків більше не підтримується, в той час gcc-6.xяк поточна стабільна версія випуску. gcc-5також представив __has_includeрозширення, присутні у всіх clang-3.xвипусках. gcc-7знаходиться в попередньому випуску (тестування регресії тощо), і, слідуючи поточній схемі версій, буде випущено як gcc-7.1.0.

  • clang : x86intrin.hсхоже, підтримується для всіх clang-3.xверсій. Останній стабільний реліз clang (LLVM) 3.9.1. Галузь розвитку є clang (LLVM) 5.0.0. Незрозуміло, що сталося із 4.xсеріалом.

  • Apple clang : прикро, що версії Apple не відповідають версії LLVMпроектів. Однак, поточний реліз:, clang-800.0.42.1заснований на LLVM 3.9.0. Перша LLVM 3.0ґрунтується версія , здається, Apple clang 2.1ще в Xcode 4.1. LLVM 3.1спочатку з’являється з Apple clang 3.1(числовий збіг) в Xcode 4.3.3.

    Apple , також визначає , __apple_build_version__наприклад, 8000042. Це здається про найбільш стабільну, строго висхідну схему версій, доступну. Якщо ви не хочете підтримувати застарілі компілятори, зробіть одне з цих значень мінімальною вимогою.

Тому будь-яка остання версія clang, включаючи версії Apple, не повинна мати жодних проблем x86intrin.h. Звичайно, поряд із gcc-5, ви завжди можете використовувати наступне:

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

Один трюк, на який ви справді не можете покластися, - це використання __GNUC__версій у clang. Версія з історичних причин застрягла 4.2.1. Версія, яка передує x86intrin.hзаголовку. Іноді це корисно, скажімо, для простих розширень GNU C, які залишаються сумісними назад.

  • icc : наскільки я можу сказати, x86intrin.hзаголовок підтримується принаймні Intel C ++ 16.0. Тестова версія може бути виконана з: #if (__INTEL_COMPILER >= 1600). Ця версія (і, можливо, більш ранні версії) також забезпечує підтримку __has_includeрозширення.

  • MSVC : Схоже, MSVC++ 12.0 (Visual Studio 2013)це перша версія, яка надає intrin.hзаголовок, а не x86intrin.h ... це говорить #if (_MSC_VER >= 1800)про тест версії. Звичайно, якщо ви намагаєтеся написати код, який є портативним для всіх цих різних компіляторів, найменування ваших проблем буде найменуванням заголовка на цій платформі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.