インテル® Fortran コンパイラー 19.0 デベロッパー・ガイドおよびリファレンス
ここでは、自動ベクトル化とループの相互作用について詳しく説明します。
[Q]parallel と [Q]x オプションを組み合わせると、1 回のコンパイルで、自動並列化と自動ループベクトル化の両方を試みることができます。
このオプションを使用すると、互換マイクロプロセッサーおよびインテル製マイクロプロセッサーの両方で並列化が有効になります。実行ファイルは、互換マイクロプロセッサーよりもインテル製マイクロプロセッサーにおいてより優れたパフォーマンスが得られる可能性があります。また、並列化は、/arch (Windows*)、-m (Linux* および macOS*)、[Q]x などの特定のオプションによる影響を受けます。
このオプションを使用すると、インテル製マイクロプロセッサーおよび互換マイクロプロセッサーの両方で、デフォルトの最適化レベルのベクトル化が有効になります。ベクトル化により呼び出されるライブラリー・ルーチンは、互換マイクロプロセッサーよりもインテル製マイクロプロセッサーにおいてより優れたパフォーマンスが得られる可能性があります。また、ベクトル化は、/arch (Windows*)、-m (Linux* および macOS*)、[Q]x などの特定のオプションによる影響を受けます。
多くの場合、コンパイラーは、並列化には最外ループ、ベクトル化には最内ループを認識します。しかし、有効であると判断された場合、コンパイラーは同じループに並列化とベクトル化を適用します。
「自動並列化のプログラミング」および「ベクトル化のプログラミングにおけるガイドライン」を参照してください。
まれに、ループ並列化 (自動または OpenMP* ディレクティブのいずれかによって) が成功すると、コンパイラーにレポートされるベクトル化されなかったループのメッセージに影響することがあります。例えば、Qopt-report:2Qopt-report-phase:vec (Windows*) または qopt-report=2qopt-report-phase=vec (Linux* および macOS*) オプションでは、ループのベクトル化が成功しなかったことが示されます。
整数ループの場合、128 ビットのインテル® ストリーミング SIMD 拡張命令 (インテル® SSE) とインテル® アドバンスト・ベクトル・エクステンション (インテル® AVX) は 32 ビット、16 ビット、8 ビット、および限定対応の 64 ビットの整数データ型を使用するほとんどの算術演算子と論理演算子に対して SIMD 命令を提供します。
整数丸め演算の最終的な精度が保持される場合は、ベクトル化が可能です。例えば、最後に格納された値が 16 ビット整数である場合には、32 ビットの右シフト演算子は 16 ビット・モードではベクトル化されません。また、インテル® SSE およびインテル® AVX 命令セットは完全に直交型ではない (例えば、バイト・オペランドのシフトはサポートされていない) ため、実際にはすべての整数演算をベクトル化ができないので注意してください。
32 ビット単精度および 64 ビット倍精度の浮動小数点数を操作するループの場合、インテル® SSE は次の算術演算子に対して SIMD 命令を提供します。
加算 (+)
減算 (-)
乗算 (*)
除算 (/)
また、インテル® SSE は、MIN、MAX という二項演算子、および SQRT という単項演算子に SIMD 命令を提供しています。これ以外の複数の算術演算子の SIMD バージョン (三角関数 SIN、COS、TAN など) は、インテル® Fortran コンパイラーで提供されるベクトル数値ランタイム・ライブラリー内のソフトウェアでサポートしています。
ベクトル化が可能であるためには、ループは次の条件を満たしていなければなりません。
可算ループ: ループの反復回数は、ランタイム時にループの入口で判明していなければなりません。ただし、コンパイル時に判明している必要はありません (つまり、反復回数は変数にできますが、ループの実行中は一定である必要があります)。これは、ループの出口はデータに依存してはならないことを意味します。
入れ子構造の最内ループである: 通常ベクトル化は最内ループに対して行われます。唯一の例外は、ループアンロール、ループ結合、ループ交換など、優先されるその他の最適化フェーズの結果として、オリジナルの外側のループが内側のループに変換される場合です。
関数の呼び出しがない: print 文でさえもループのベクトル化の妨げになります。通常、ベクトル化レポートには「非標準のループはベクトル化候補ではありません」と出力されます。関数呼び出しを含むループはベクトル化されません。例外として、算術組込み関数とインライン展開可能な関数です。
算術組込み関数は、コンパイラーのランタイム・ライブラリーにベクトル化されたバージョン が含まれているため、利用できます。このような関数を次にリストします。多くは float と double の両方があります。
acos | atanh | exp2 | tan |
acosh | ceiling | floor | tanh |
anint | cos | log | |
asin | cosh | log10 | |
asinh | erf | sin | |
atan | erfc | sinh | |
atan2 | exp | sqrt |
次の例のループは、sqrtf() がベクトル化可能で、func() がインライン展開されるため、ベクトル化できます。デフォルトの最適化により、同じソースファイル内のすべての関数のインライン展開が有効になります。インライン展開レポートは Qopt-report:2Qopt-report-phase:ipo (Windows*) または qopt-report=2qopt-report-phase=ipo (Linux*) オプションを指定して取得できます。
ベクトル化可能な演算は、浮動小数点データと整数データとで異なります。
整数配列の演算
ループ本体の文には、算術演算または論理演算 (これも、通常は配列) を使用できます。算術演算は、加算、減算、ABS、MIN、および MAX に制限されます。論理演算には、ビット単位の AND、OR、および XOR の演算子を含んでいます。データ型は混在させられますが、効率性の低下につながる恐れがあります。
上記の浮動小数点演算と整数演算以外の文は使用できません。上記で説明された以外、ループの本体には、関数呼び出しは使用できません。
データ依存性とは、シリアルループに含まれている各演算の実行順序を制限する関係のことです。ベクトル化によって演算の実行順序が並び替えられるため、自動ベクトル化では任意のデータ依存性の解析を自由に使用できなければなりません。
データの依存関係によりベクトル化が妨げられる例を次に示します。この例に示す配列の各要素の値は、前の繰り返しで計算された前後の要素の値により決まります。
例 1: データ依存性を持つループ |
---|
|
上記の例に示すループは、ベクトル化できません。これは、現在の要素 data(i) への WRITE が直前の要素 data(i-1) の使用に依存しており、この要素が直前の反復時にすでに書き込まれ変更されているためです。このことは、次の例に示すように、配列のアクセスパターンの最初の 2 回の反復を見れば分かります。
例 2: データ依存性を持つループをベクトル化したもの |
---|
|
このループが示す通常のシーケンスでは、2 回目の反復時に読み込まれる DATA(1) の値は、最初の反復時に書き込まれます。ベクトル化を行うためには、元のループのセマンティクスを変えることなく、対象となるすべての反復を並列に実行しなければなりません。
例 3: データに依存しないループ |
---|
|
データ依存性の解析とは、2 つのメモリーアクセスの重なり合う条件を見つけることです。その条件は、1 つのプログラムの中で参照を 2 回行うと仮定した場合は、次の 2 つの事項によって規定されます。
参照するいくつかの変数が、メモリー内の同じ領域のエイリアスであるかどうか (つまり、互いに重複しているかどうか)
配列参照の場合は、添字同士の関連性
配列参照のデータ依存アナライザーは一連のテストとして構成され、時間とスペースコストに加えて性能においても段階的に強化していきます。
いずれかの次元で独立性が認められれば、それによって依存関係が排除できるため、最初は 1 次元ずつ単純なテストをいくつか実行します。宣言されている次元境界を超える恐れのある多次元配列参照は、テストを実施する前に、線形形式に変換できます。
簡単なテストとして、高速最大公約数 (GCD) テストや拡張限界テストなどを使用できます。GCD テストでは、ループ・インデックスの係数の GCD で定数項を均等に等分できない場合、データの独立性が証明されます。拡張限界テストでは、添字式において極値がオーバーラップする可能性があるかどうかをチェックします。
どの単純なテストでも独立性を証明できなかった場合は、最終的に Fourier-Motzkin 法の消去を用いた強力な階層型依存性解法を使用して、すべての次元におけるデータ依存性問題を解決します。
最適化に関する注意事項 |
---|
インテル® コンパイラーでは、インテル® マイクロプロセッサーに限定されない最適化に関して、他社製マイクロプロセッサー用に同等の最適化を行えないことがあります。これには、インテル® ストリーミング SIMD 拡張命令 2、インテル® ストリーミング SIMD 拡張命令 3、インテル® ストリーミング SIMD 拡張命令 3 補足命令などの最適化が該当します。インテルは、他社製マイクロプロセッサーに関して、いかなる最適化の利用、機能、または効果も保証いたしません。本製品のマイクロプロセッサー依存の最適化は、インテル® マイクロプロセッサーでの使用を前提としています。インテル® マイクロアーキテクチャーに限定されない最適化のなかにも、インテル® マイクロプロセッサー用のものがあります。この注意事項で言及した命令セットの詳細については、該当する製品のユーザー・リファレンス・ガイドを参照してください。 注意事項の改訂 #20110804 |