Заголовочные файлы для x86 SIMD intrinsics
Какие файлы заголовков предоставляют встроенные функции для разных наборов инструкций для SIM-карт x86 (MMX, SSE, AVX, …)? Невозможно найти такой список в Интернете. Поправьте меня если я ошибаюсь.
- Какова цель инструкции «ПАУЗА» в x86?
- Инструкция INC против ADD 1: Это имеет значение?
- Как выполнить инверсию _mm256_movemask_epi8 (VPMOVMSKB)?
- Использует ли xor reg, reg преимущество над mov reg, 0?
- Что означает `rep ret`?
- Я продолжаю получать BSOD. Как я могу отслеживать, какое приложение / драйвер вызывает его?
- Заказ локального распределения переменных в стеке
- Получение максимального значения в векторе __m128i с SSE?
MMX SSE SSE2 SSE3 SSSE3 SSE4.1 SSE4.2 SSE4A AES AVX AVX512
Если вы используете только
#include
он будет включать все заголовки SSE / AVX, которые includeся в соответствии с ключами компилятора, такими как -march=corei7
или просто -march=native
. Кроме того, некоторые х86 конкретные инструкции, такие как bswap
или ror
становятся доступными как внутренние.
Название заголовка зависит от вашей компиляции и целевой архитектуры.
- Для 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 с использованием
mmintrin.h
используйтеmmintrin.h
- Для gcc / clang / xlcc для PowerPC с VMX (aka Altivec) и / или VSX используйте
altivec.h
- Для gcc / clang таргетинга PowerPC с SPE использует
spe.h
Вы можете обрабатывать все эти случаи с помощью условных предпроцессорных инструкций:
#if defined(_MSC_VER) /* Microsoft C/C++-compatible compiler */ #include #elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) /* GCC-compatible compiler, targeting x86/x86-64 */ #include #elif defined(__GNUC__) && defined(__ARM_NEON__) /* GCC-compatible compiler, targeting ARM with NEON */ #include #elif defined(__GNUC__) && defined(__IWMMXT__) /* GCC-compatible compiler, targeting ARM with WMMX */ #include #elif (defined(__GNUC__) || defined(__xlC__)) && (defined(__VEC__) || defined(__ALTIVEC__)) /* XLC or GCC-compatible compiler, targeting PowerPC with VMX/VSX */ #include #elif defined(__GNUC__) && defined(__SPE__) /* GCC-compatible compiler, targeting PowerPC with SPE */ #include #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
, а также все векторные встроенные _rdtsc
, включали только AMD. Если вы против включения большего, что вам действительно нужно, вы можете выбрать правильный вариант, посмотрев на таблицу.
x86intrin.h
– это рекомендуемый способ получить встроенные средства для AMD XOP (только для Bulldozer, даже не для будущих процессоров AMD) , а не для собственного заголовка.
Некоторые компиляторы будут генерировать сообщения об ошибках, если вы используете встроенные средства для наборов инструкций, которые вы не включили (например, _mm_fmadd_ps
без включения fma, даже если вы включили immintrin.h
и immintrin.h
AVX2).
Как было сказано многими ответами и комментариями,
– это всеобъемлющий заголовок для x86 [-64] SIMD-функций. Он также предоставляет встроенные инструкции для других расширений ISA. gcc
, clang
и icc
все 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()) #include #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)
в качестве теста версии. Конечно, если вы пытаетесь написать код, переносимый для всех этих разных компиляторов, имя заголовка на этой платформе будет наименее из ваших проблем.