Заголовочные файлы для x86 SIMD intrinsics

Какие файлы заголовков предоставляют встроенные функции для разных наборов инструкций для SIM-карт x86 (MMX, SSE, AVX, …)? Невозможно найти такой список в Интернете. Поправьте меня если я ошибаюсь.

 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) в качестве теста версии. Конечно, если вы пытаетесь написать код, переносимый для всех этих разных компиляторов, имя заголовка на этой платформе будет наименее из ваших проблем.

  • Заставить программу на x86?
  • Как планируется x86 uops?
  • В чем разница между MOV и LEA?
  • Почему (или нет?) SFENCE + LFENCE эквивалентно MFENCE?
  • Безопасно ли читать конец конца буфера на одной странице на x86 и x64?
  • Относительная производительность команды x86 inc vs. add
  • Изменение целевых настроек процессора в Visual Studio 2010 Express
  • Assembly x86 Date to Number - разбиение строки на более мелкие разделы
  • Что означает `dword ptr`?
  • Цикл с вызовом функции быстрее, чем пустой цикл
  • Что происходит, когда запускается компьютерная программа?
  • Давайте будем гением компьютера.