インテル® C++ コンパイラー XE 13.1 ユーザー・リファレンス・ガイド
simd プラグマは、ループのベクトル化を実行します。
clause |
clause (節) は次のいずれかです。
|
より多くのループのベクトル化を行うようにコンパイラーに指示するには、simd プラグマを使用します。simd プラグマを使用したベクトル化は、完全に自動化されたアプローチを補完します (ただし、置き換えることはできません)。
明示的に vectorlength() 節または vectorlengthfor() 節が指定されていない場合、コンパイラーは独自のコストモデルを使用して vectorlength を選択します。 private、firstprivate、lastprivate、linear、および reduction で正しくない変数が指定されたり、あるいは適切な変数が指定されていない場合、ランタイムエラーや正しくない結果など、意図しない問題が発生する可能性があります。
特定の変数は、private、linear、または reduction 節の 1 つのインスタンスでのみ指定することができます。
コンパイラーがループをベクトル化できない場合は、警告が出力されます (assert 節を使用して警告をエラーとすることができます)。
なんらかの理由でベクトライザーがループのベクトル化を停止する必要がある場合は、SIMD ループに fast 浮動小数点モデルが使用されます。
simd プラグマは、すべての自動ベクトル化が可能なループに影響するわけではありません。いくつかのループでは SIMD ベクトル・セマンティクスを表現できません。
simd プラグマには、次の制限が適用されます
simd プラグマの対象となる可算ループは、OpenMP* のワークシェア・ループ構造の for ループ形式に適合していなければなりません。また、ループ制御変数は符号付き整数型でなければなりません。
ベクトル値は、8、16、32、または 64 ビットの符号付き整数、単精度または倍精度の浮動小数点数、あるいは単精度または倍精度の複素数でなければなりません。
SIMD ループには別のループ (for、while、do-while) が入れ子される場合があります。入れ子構造のループの内側から外側へのジャンプはサポートされていません。ブレークと継続はサポートされています。このような内部ループは、インライン展開により作成されることがあり、ソースレベルでは明らかではないことがあります。
SIMD ループは無条件にメモリー参照を実行します。そのため、すべてのアドレス計算結果は、ループがシーケンシャルに実行されたときにはアクセスされない場合でも、有効なメモリーアドレスでなければなりません。
より多くのベクトル化を行う変換を無効にするには、-no-vec -no-simd (Linux* および OS X*) または /Qvec- /Qsimd- (Windows*) オプションを指定してください。
ユーザー指示によるベクトル化 (SIMD ベクトル化とも呼ぶ) では、#pragma simd アノテーション付きのループのベクトル化に失敗した場合、エラーを報告するかどうか指定できます。 デフォルトでは、#pragma simd は noassert に設定されていて、ループのベクトル化に失敗すると、コンパイラーは警告を発行します。 #pragma simd アノテーション付きのループのベクトル化に失敗した場合、コンパイラーにエラーを報告するように指示するには、#pragma simd に assert 節を追加します。 #pragma simd アノテーション付きのループがコンパイラーによりベクトル化されなかった場合、そのループはシリアル・セマンティクスを保持します。
#pragma simd を使用します。
この例では、関数 add_floats() で不明なポインターを多く使用しているため、コンパイラーの自動ランタイム独立性チェックによる最適化が行われます。#pragma simd を使用してこのループのベクトル化を行うことで、ランタイムチェックにかかるオーバーヘッドを回避することができます。
void add_floats(float *a, float *b, float *c, float *d, float *e, int n){
int i;
#pragma simd
for (i=0; i<n; i++){
a[i] = a[i] + b[i] + c[i] + d[i] + e[i];
}
}