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