Заголовочные файлы для встроенных функций x86 SIMD

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

5 ответов

Решение
<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

<zmmintrin.h> AVX512

Если вы используете только

#include <x86intrin.h>

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

Название заголовка зависит от вашего компилятора и целевой архитектуры.

  • Для Microsoft C++ (для x86, x86-64 или ARM) и Intel C/C++ Compiler для 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

С этой страницы

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

Как многие из ответов и комментариев заявили, <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,

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

Другие вопросы по тегам