ここでは、自動ベクトル化とループの相互作用について詳しく説明します。
「ベクトル化のプログラミングにおけるガイドライン」を参照してください。
まれに、(自動または OpenMP* ディレクティブのいずれかによって) ループ並列化が成功すると、コンパイラーにレポートされるベクトル化されなかったループのメッセージに影響することがあります。
整数ループの場合、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 など) は、インテル® oneAPI DPC++/C++ コンパイラーで提供されるベクトル数値ランタイム・ライブラリー内のソフトウェアでサポートしています。
ベクトル化が可能であるためには、ループは次の条件を満たしていなければなりません。
可算ループ: ループの反復回数は、ランタイム時にループの入口で判明していなければなりません。ただし、コンパイル時に判明している必要はありません (つまり、反復回数は変数にできますが、ループの実行中は一定である必要があります)。これは、ループの出口はデータに依存してはならないことを意味します。
1 つの入口と 1 つの出口: ループは可算ループでなければならないことを意味します。
直列型コード: SIMD 命令は、オリジナルループと同じ演算を実行するため、反復ごとに異なる制御フローを持つことはできません。つまり、分岐してはなりません。switch 文も使用できません。ただし、if 文はマスク付きの代入として実装できる場合のみ使用できます (通常は使用可能)。演算はすべてのデータ要素に対して実行されますが、結果はマスクが TRUE に評価された要素のみ格納されます。
入れ子構造の最内ループである: 通常ベクトル化は最内ループに対して行われます。唯一の例外は、ループアンロール、ループ結合、ループ交換など、優先されるその他の最適化フェーズの結果として、オリジナルの外側のループが内側のループに変換される場合です。
関数の呼び出しがない: print 文でさえもループのベクトル化の妨げになります。通常、ベクトル化レポートには「非標準のループはベクトル化候補ではありません」と出力されます。関数呼び出しを含むループはベクトル化されません。例外として、算術組込み関数とインライン展開可能な関数です。
算術組込み関数は、コンパイラーのランタイム・ライブラリーにベクトル化されたバージョンが含まれているため、利用できます。このような関数を次にリストします。多くは float と double の両方があります。
acos | ceil | fabs | round |
acosh | cos | floor | sin |
asin | cosh | fmax | sinh |
asinh | erf | fmin | sqrt |
atan | erfc | log | tan |
atan2 | erfinv | log10 | tanh |
atanh | exp | log2 | trunc |
cbrt | exp2 | pow |
ベクトル化可能な演算は、浮動小数点データと整数データとで異なります。
整数配列の演算
ループ本体内の文では、char、unsigned char、short、unsigned short、int、unsigned int 型を使用できます。sqrt や fabs といった関数を呼び出すこともできます。使用可能な算術演算は、加算、減算、ビット単位 AND、ビット単位 OR、ビット単位 XOR、除算 (ランタイム・ライブラリー・コール経由)、乗算、min、および max だけです。データ型は混在させられますが、効率性の低下につながる恐れがあります。例えば、乗算演算子、シフト演算子、単項演算子は混在させられます。
上記の浮動小数点演算と整数演算以外の文は使用できません。特に、特殊なデータ型である __m64、__m128、__m256 はベクトル化できないので注意してください。ループ本体に関数呼び出しを含めることはできません。インテル® SSE の組込み関数 (例: _mm_add_ps) またはインテル® AVX 組込み関数 (例: _mm256_add_ps) は使用できません。
性能は、使用法、構成、およびその他の要因によって異なります。詳細については、www.Intel.com/PerformanceIndex (英語) を参照してください。 注意事項の改訂 #20201201 |