Які файли заголовків містять суттєві характеристики для різних розширень набору інструкцій 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.hx86intrin.harm_neon.hmmintrin.haltivec.hspe.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. , і всі з цим погодилися. Мені потрібно було викопати кілька версій, які підтримують заголовок, і я подумав, що може бути корисним перерахувати деякі висновки ...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)про тест версії. Звичайно, якщо ви намагаєтеся написати код, який є портативним для всіх цих різних компіляторів, найменування ваших проблем буде найменуванням заголовка на цій платформі.
#include <x86intrin.h>витягнути все, що вам потрібно.