Які файли заголовків містять суттєві характеристики для різних розширень набору інструкцій SIM86 x86 (MMX, SSE, AVX, ...)? Здається, неможливо знайти такий список в Інтернеті. Виправте мене, якщо я помиляюся.
Які файли заголовків містять суттєві характеристики для різних розширень набору інструкцій SIM86 x86 (MMX, SSE, AVX, ...)? Здається, неможливо знайти такий список в Інтернеті. Виправте мене, якщо я помиляюся.
Відповіді:
У ці дні вам слід просто включити <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.
<zmmintrin.h>
безпосередньо; gcc навіть не надає. Просто використовуйте<immintrin.h>
або навіть ще більш повне <x86intrin.h>
. Ця відповідь в основному застаріла, якщо ви навмисно не уникаєте включення внутрішніх текстів для новіших версій SSE, оскільки ваш компілятор не скаржиться під час використання інструкції SSE4.1 під час компіляції для SSE2. (gcc / clang не скаржаться, тому вам просто слід використовувати immintrin.h для них. IDK про інших.)
На 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 /
<x86intrin.h>
, але <intrin.h>
досягає подібного ефекту. Вам, звичайно, потрібна умовна збірка. :-(
#include <immintrin.h>
. Використовуйте це для внутрішніх технологій SIMD. Вам потрібен лише ще більший (і трохи повільніший для компілятора) x86intrin.h
або intrin.h
якщо вам потрібні такі речі, як цілі внутрішні обертання / біт-сканування (хоча Intel документує деякі з них, як це доступно immintrin.h
в їх посібнику з внутрішньої роботи ).
x86intrin.h
/, intrin.h
але не в immintrin.h
.
Назва заголовка залежить від компілятора та цільової архітектури.
intrin.h
x86intrin.h
arm_neon.h
mmintrin.h
altivec.h
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
З цієї сторінки
+----------------+------------------------------------------------------------------------------------------+
| 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).
smmintrin
(SSE4.1) - це Пенрін (45nm Core2), а не Nehalem ("i7"). Чи можемо ми перестати використовувати "i7" як ім'я архітектури? Тепер безглуздо, коли Intel продовжує використовувати його для сімейства SnB .
immintrin.h
не включають _popcnt32
і _popcnt64
(не плутати з тими, що в popcntintrin.h
!) внутрішніми елементами GCC 9.1.0. Отже, схоже, це x86intrin.h
все ще служить цілі.
Оскільки багато відповідей і коментарі заявили, <x86intrin.h>
є всеосяжним заголовком для x86 [-64] SIMD вбудованих функцій . Він також пропонує внутрішні тексти, що підтримують інструкції для інших розширень ISA. , і всі з цим погодилися. Мені потрібно було викопати кілька версій, які підтримують заголовок, і я подумав, що може бути корисним перерахувати деякі висновки ...gcc
clang
icc
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)
про тест версії. Звичайно, якщо ви намагаєтеся написати код, який є портативним для всіх цих різних компіляторів, найменування ваших проблем буде найменуванням заголовка на цій платформі.
#include <x86intrin.h>
витягнути все, що вам потрібно.