web-dev-qa-db-ja.com

x86 SIMD組み込み関数のヘッダーファイル

さまざまなx86 SIMD命令セット拡張(MMX、SSE、AVXなど)の組み込み関数を提供するヘッダーファイルはどれですか?そのようなリストをオンラインで見つけることは不可能のようです。私が間違っている場合は修正してください。

119
fredoverflow
<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
155
fredoverflow

あなただけを使用する場合

#include <x86intrin.h>

-march=corei7または単に-march=nativeなどのコンパイラスイッチに応じて有効にされるすべてのSSE/AVXヘッダーが含まれます。さらに、bswaprorなどのx86固有の命令が組み込み関数として使用可能になります。

71
Gunther Piez

ヘッダー名は、コンパイラとターゲットアーキテクチャによって異なります。

  • Microsoft C++(x86、x86-64、またはARMを対象とする)およびIntel C/C++ Compiler for Windowsの場合は、intrin.hを使用します
  • X86/x86-64をターゲットとするgcc/clang/iccの場合は、x86intrin.hを使用します
  • NEONでARMをターゲットとするgcc/clang/armccの場合は、arm_neon.hを使用します
  • Gcc/clang/armccターゲティングの場合、WMMXでARMを使用するにはmmintrin.hを使用します
  • VMX(別名Altivec)またはVSXでPowerPCをターゲットとするgcc/clang/xlccの場合は、altivec.hを使用します
  • SPEでPowerPCをターゲットとするgcc/clangの場合は、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
55
Marat Dukhan

これから ページ

+----------------+------------------------------------------------------------------------------------------+
|     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を含めることができます。 -1つだけ。実際に必要なものをさらに含めることに反対する場合は、テーブルを見て正しいインクルードを選択できます。

x86intrin.hは、独自のヘッダーを持つのではなく、 AMD XOP(ブルドーザーのみ、将来のAMD CPUでさえない) の組み込み関数を取得するための推奨される方法です。

有効になっていない命令セットに組み込み関数を使用すると、一部のコンパイラは引き続きエラーメッセージを生成します(例:_mm_fmadd_psを含めてAVX2を有効にしても、fmaを有効にせずにimmintrin.h)。

39
ecerulm

回答とコメントの多くが述べているように、<x86intrin.h>the x86 [-64] SIMD組み込み関数の包括的なヘッダーです。また、他のISA拡張機能の命令をサポートする組み込み関数も提供します。 gccclang、およびiccはすべてこれで解決しました。私はヘッダーをサポートするバージョンを掘り下げる必要があり、いくつかの調査結果をリストすることが役立つと思いました...

  • gccx86intrin.hのサポートが最初に表示されるのはgcc-4.5.0です。 gcc-4リリースシリーズは現在メンテナンスされていませんが、gcc-6.xcurrent安定リリースシリーズです。 gcc-5は、__has_includeリリースすべてに存在するclang-3.x拡張も導入しました。 gcc-7はプレリリース(回帰テストなど)であり、現在のバージョン管理スキームに従って、gcc-7.1.0としてリリースされます。

  • clangx86intrin.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)。これは、利用可能な最も安定した、厳密に昇順のバージョン管理スキームについてのようです。レガシーコンパイラをサポートしたくない場合は、これらの値のいずれかを最小要件にしてください。

したがって、Appleバージョンを含むclangの最近のバージョンでは、x86intrin.hに問題はありません。もちろん、gcc-5とともに、次のものをいつでも使用できます。

#if defined (__has_include) && (__has_include(<x86intrin.h>))
#include <x86intrin.h>
#else
#error "upgrade your compiler. it's free..."
#endif

本当に頼りにできないトリックの1つは、clang__GNUC__バージョンを使用することです。バージョン管理は、歴史的な理由により、4.2.1で止まっています。 x86intrin.hヘッダーの前にあるバージョン。たとえば、下位互換性を維持している単純なGNU C拡張に対して有用です。

  • icc:私の知る限り、x86intrin.hヘッダーは少なくともIntel C++ 16.0以降でサポートされています。バージョンテストは、#if (__INTEL_COMPILER >= 1600)で実行できます。このバージョン(および場合によっては以前のバージョン)は、__has_include拡張機能のサポートも提供します。

  • MSVCMSVC++ 12.0 (Visual Studio 2013)intrin.hヘッダーを提供する最初のバージョンであるようです-notx86intrin.h...これは、バージョンテストとして#if (_MSC_VER >= 1800)を示唆しています。もちろん、これらすべての異なるコンパイラー間で移植可能なコードを作成しようとしている場合、このプラットフォームのヘッダー名が問題の最小になります。

11
Brett Hale