Какие файлы заголовков предоставляют встроенные функции для разных наборов инструкций для SIM-карт x86 (MMX, SSE, AVX,...)? Невозможно найти такой список в Интернете. Исправьте меня, если я ошибаюсь.
Заголовочные файлы для x86 SIMD intrinsics
Ответ 1
<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
Ответ 2
Если вы используете только
#include <x86intrin.h>
он будет включать в себя все заголовки SSE/AVX, которые активируются в соответствии с коммутаторами компилятора типа -march=corei7
или просто -march=native
. Кроме того, некоторые х86 конкретные инструкции, такие как bswap
или ror
, становятся доступными как встроенные.
Ответ 3
Название заголовка зависит от вашей компиляции и целевой архитектуры.
- Для Microsoft С++ (таргетинг на x86, x86-64 или ARM) и компилятор Intel C/С++ для 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 (aka 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
Ответ 4
Из этого страница
+----------------+------------------------------------------------------------------------------------------+
| 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
- рекомендуемый способ получить intrinsics для AMD XOP (только для Bulldozer, даже для будущих процессоров AMD), вместо того, чтобы его собственный заголовок.
Некоторые компиляторы все равно будут генерировать сообщения об ошибках, если вы используете встроенные средства для наборов инструкций, которые вы не включили (например, _mm_fmadd_ps
без включения fma, даже если вы включили immintrin.h
и включили AVX2).
Ответ 5
Как было сказано в большинстве ответов и комментариев, <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
. -
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 free..."
#endif
Один трюк, на который вы не можете положиться, - это использовать версии __GNUC__
в clang
. Версии по историческим причинам застревают в 4.2.1
. Версия, предшествующая заголовку x86intrin.h
. Это иногда полезно, например, для простых расширений GNU C, которые остались обратно совместимыми.
-
icc: насколько я могу судить, заголовок
x86intrin.h
поддерживается, по крайней мере, с Intel С++ 16.0. Тест версии может быть выполнен с помощью:#if (__INTEL_COMPILER >= 1600)
. Эта версия (и, возможно, более ранние версии) также поддерживает поддержку расширения__has_include
. -
MSVC. Похоже, что
MSVC++ 12.0 (Visual Studio 2013)
является первой версией, предоставляющей заголовокintrin.h
- notx86intrin.h
... это предполагает:#if (_MSC_VER >= 1800)
как тест версии, Конечно, если вы пытаетесь написать код, который переносится во всех этих разных компиляторах, имя заголовка на этой платформе будет наименьшим из ваших проблем.