インテル® C++ コンパイラー 19.0 デベロッパー・ガイドおよびリファレンス
インテル® アドバンスト・ベクトル・エクステンション 512 (インテル® AVX-512) 命令の組込み関数は、インテル® AVX とインテル® AVX2 の 256 ビット SIMD 命令のほとんどを 512 ビットの数値処理に対応するように拡張します。
インテル® AVX-512 命令のプログラミング・モデルは、インテル® AVX2 命令と同じです。ブロードキャストの拡張、組込みマスクによる予測、組込みの浮動小数点丸め制御、組込みの浮動小数点フォルトの抑止、分散 (Scatter) 命令、高速な数学命令、大きな変位値の簡易表現を提供します。インテル® SSE とインテル® AVX の混在使用ではパフォーマンス・ペナルティーが発生しますが、インテル® AVX とインテル® AVX-512 命令を混在させてもペナルティーは発生しません。
インテル® AVX-512 組込み関数は、32nm プロセス技術で製造される IA-32 およびインテル® 64 アーキテクチャーでサポートされ、インテル® AVX-512 の新しい命令およびその他の 128 ビット/256 ビットの SIMD 拡張命令に直接対応付けられます。
512 ビットのレジスターステートは、45nm プロセス技術で製造されるインテル® 64 プロセッサーで追加された XSAVE/XRSTOR/XSAVEOPT 命令を使用してオペレーティング・システムにより管理されます (詳細は、『Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 2B』と『Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A』を参照してください)。
インテル® SSE レジスターからインテル® AVX レジスターへのマップと同様に、インテル® AVX レジスター YMM0 ~ YMM15 は、インテル® AVX-512 レジスター ZMM0 ~ ZMM15 にマップされます。インテル® AVX-512 対応プロセッサーで、インテル® AVX およびインテル® AVX2 命令は、最初の 16 個の ZMM レジスターの下位 128 ビットまたは下位 256 ビットを操作します。
新しいエンコード・プリフィクス (EVEX) は、最大 512 ビットのベクトルをサポートします。EVEX プリフィクスは VEX プリフィクスをベースにしており、VEX エンコードで利用可能な機能を簡単かつ効率良くエンコードする一方で、ベクトル機能を拡張します。
インテル® AVX-512 組込み関数は、3 つの C データ型をオペランドとして使用します。3 つのデータ型は、組込み関数に対するオペランドとして使用される新しいレジスターを表しています。__m512、__m512d、__m512i のデータ型があります。__m512 データ型は、インテル® AVX-512 組込み関数で使用される拡張 SSE レジスター (ZMM レジスター) の内容を表します。__m512 データ型は、16 個の 32 ビット倍精度浮動小数点値を保持できます。__m512d データ型は、8 個の 64 ビット倍精度浮動小数点値を保持できます。__m512i データ型は、64 個の 8 ビット整数値、32 個の 16 ビット整数値、16 個の 32 ビット整数値、または 8 個の 64 ビット整数値を保持できます。
コンパイラーは、__m512、__m512d、および __m512i 型のローカルデータとグローバルデータのアライメントを、スタック上の 64 バイト境界に合わせます。integer 型、float 型、または double 型の配列のアライメントを合わせるには、__declspec(align) 文を使用します。
インテル® アドバンスト・ベクトル・エクステンション 512 (インテル® AVX-512) 組込み関数のプロトタイプは、zmmintrin.h ヘッダーファイルで定義されていますが、これらの組込み関数を使用する場合、次のように immintrin.h ファイルをインクルードします。
#include <immintrin.h>
インテル® AVX-512 組込み関数には、__m128、__m128i、__m128d、__m256、__m256i、__m256d、__m512、__m512i、および __m512d データ型を使用するバージョンがあります。
ほとんどのインテル® AVX-512 の組込み関数名は、次の表記規則に従います。
_mm512[_<maskprefix>]_<intrin_op>_<suffix>
次の表は、構文の各項目について説明したものです。
_mm512 | プリフィクスは演算中の引数や結果のうち最も大きいベクトルのサイズを表します。 |
<maskprefix> | 指定されている場合、書き込みマスク (_mask) による予測か、ゼロマスク (_maskz) による予測かを示します。 |
<intrin_op> | 組込み関数の基本操作を示します。例えば、加算の場合は add、減算の場合は sub になります。 |
<suffix> | 命令の操作対象となるデータの型を示します。各サフィックスの最初の 1 文字または 2 文字は、データがパックドデータ (p)、拡張パックドデータ (ep)、またはスカラーデータ (s) であることを示します。その他の文字は、次のデータ型を示します。
|
プログラムは、512 ビットのベクトルに 8 個の倍精度浮動小数点値、16 個の単精度浮動小数点値、8 個の 64 ビット整数値、または 16 個の 32 ビット整数値をパックできます。そのため、1 つの命令でインテル® AVX やインテル® AVX2 の 2 倍、あるいはインテル® SSE の 4 倍のデータ要素を処理することができます。
書き込みマスクを使用することで、組込み関数はソースオペランドの選択された SIMD 要素に対して操作を実行し、ほかの SIMD オペランドの要素とブレンド (混合) することができます。次の例について考えてみます。ここで、書き込みマスク k の偶数のビット位置 0、3、5、7、9、11、13、および 15 は 1 に、奇数のビット位置は 0 に設定されています。
__m512 res, src, a, b; __mmask16 k = 0x5555;
次のように組込み関数を呼び出します。
res = _mm512_mask_add_ps(src, k, a, b);
結果 res の偶数の float32 要素は a と b の対応する要素の合計となり、奇数の要素は src の対応する float32 要素からコピー (つまり、ブレンド) されます。
一般に、書き込みマスク付きの組込み関数では、第 1 引数にブレンドされる値 (上記の例では src)、第 2 引数に書き込みマスク k の順で宣言します。一部の組込み関数は、次のように異なる SIMD 引数から値をブレンド (混合) します: _mm512_mask2_permutex2var_epi32。この場合も、マスクは引数の直後に指定します。
ゼロマスクは、書き込みマスクの単純な形式で、ブレンドされる値がありません。代わりに、マスクのビットが 0 の場合、結果要素の対応する要素は 0 に設定されます。次の例について考えてみます。
res = _mm512_maskz_add_ps(k, a, b);
マスク k の 0 にセットされているビットに対応する res の float32 要素は 0 に設定されます。k の 1 にセットされているビットに対応する res の float32 要素は、a と b の対応する要素の合計になります。
一般に、ゼロマスク付きの組込み関数では、ブレンドされる値の引数がないため、第 1 引数にマスクを宣言します。
組込み丸め制御を使用することで、MXCSR コントロール・レジスターの丸め制御を変更せずに、個々の操作に対して浮動小数点丸めモードを明示的に指定できます。すべての例外の抑止機能は、浮動小数点例外フラグを抑止します。
インテル® AVX-512 は、ほとんどの 512 ビット・スカラー浮動小数点操作でこれらの機能を提供しています。通常、これらの機能をサポートする組込み関数は、名前に "_round" が含まれています。
__m512d _mm512_add_round_pd(__m512d a, __m512d b, int rounding);
ゼロ方向への丸めと SAE を指定するには、次のように呼び出します。
__m512d res, a, b; res = _mm512_add_round_pd(a, b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC);
組込みブロードキャストを使用することで、追加の命令なしで 1 つの値をソースオペランド全体にブロードキャストできます。名前に "_set1" を含む組込み関数は、ブロードキャスト操作を行います。コンパイラーは、インテル® AVX-512 命令の EVEX プリフィクスを利用してブロードキャスト操作をエンコードができます。次に例を示します。
__m512 res, a; res = _mm512_add_ps(a, _mm512_set1_ps(3.0f));
この呼び出しは、a の各 float32 要素に 3.0 を加算します。