インテル® C++ コンパイラー XE 13.1 ユーザー・リファレンス・ガイド

simd

simd プラグマは、ループのベクトル化を実行します。

構文

#pragma simd [clause[ [,] clause]...]

引数

clause

clause (節) は次のいずれかです。

vectorlength(n1[, n2]...)

n はベクトル長 (VL) です。2 のべき乗の整数値で、2、4、8、または 16 でなければなりません。複数の n を指定すると、ベクトライザーは指定された値から VL を選択します。

ベクトルループのそれぞれの反復は、スカラーループを n 回実行するのと同じ分の演算を実行します。複数の vectorlength 節は結合されます。

vectorlengthfor(data type)

data type はビルトインの整数型 (8、16、32、または 64 ビット)、ポインター型 (ポインターのサイズの整数として処理される)、浮動小数点型 (32 または 64 ビット)、または複素数型 (64 または 128 ビット) のいずれかでなければなりません。そうでない場合の動作は不定です。

ベクトルループのそれぞれの反復は、スカラーループを n 回実行するのと同じ分の演算を実行します。n は次のように計算されます: size_of_vector_register/sizeof(data_type)

例えば、vectorlengthfor(float) は、インテル® SSE2 からインテル® SSE4.2 対応のターゲット・プロセッサー (128 ビットの XMM レジスターでパックド浮動小数点演算に対応) では n=4、インテル® AVX 対応のターゲット・プロセッサー (256 ビットの YMM レジスターでパックド浮動小数点演算に対応) では n=8 になります。vectorlengthfor(int) は、インテル® SSE2 からインテル® AVX 対応のターゲット・プロセッサーで n=4 になります。

vectorlength() 節と vectorlengthfor() 節は互いに排他的です。つまり、同時に両方を指定することはできません。

複数の vectorlengthfor 節を指定した場合の動作は不定です。

private(var1[, var2]...)

var はスカラー変数です。

ループのそれぞれの反復に対して各変数がプライベートになります。firstprivate 節で変数が指定されている場合を除き、特定の反復における変数の初期値は未定義です。 lastprivate 節で変数が指定されている場合を除き、ループ終了時の変数の値は未定義です。複数の private 節は結合されます。

firtsprivate/lastprivate 節を指定して SIMD ループを実行すると、ループがベクトル化されなかった場合でも、同じコードをシリアル実行した場合と異なります。

firstprivate(var1[, var2]...)

private 節で指定される機能のスーパーセットを指定します。firstprivate 節でリストする変数には、private 節のセマンティクスが適用されます。さらに、その初期値は、SIMD ループに入る前に、各反復のすべてのプライベート・インスタンスにブロードキャストされます。

lastprivate(var1[, var2]...)

private 節で指定される機能のスーパーセットを指定します。lastprivate 節でリストする変数には、private 節のセマンティクスが適用されます。さらに、SIMD ループ終了時の各変数の値は、その SIMD ループシーケンスの最後の反復の結果になります (最後の反復で値が代入されなかった場合は未定義となります)。

linear(var1:step1 [,var2:step2]...)

var はスカラー変数です。

step はコンパイル時の正の整数定数式です。

スカラーループのそれぞれの反復で、var1step1var2step2、というように増分されます。そのため、ベクトルループの各反復は、変数を VL*step1、VL*step2、…、VL*stepN のように増分します。var に複数の step が指定されている場合は、コンパイル時にエラーが発生します。複数 の linear 節は結合されます。

reduction(oper:var1 [,var2]…)

oper はリダクション演算子です。

var はスカラー変数です。

oper で示されたベクトルリダクションを var1var2、…、varN に適用します。simd プラグマには、演算子が同じまたは異なる複数の reduction 節を含めることができます。 var に複数のリダクション演算子が関連付けられている場合は、コンパイル時にエラーが発生します。

[no]assert

ベクトル化に失敗したときに、報告するかどうかをコンパイラーに指示します。デフォルトは noassert です。この節が複数指定された場合は、コンパイル時にエラーが発生します。

[no]vecremainder

オリジナルのループがベクトル化された場合に残りのループをベクトル化するかどうかをコンパイラーに指示します。関連情報: vector

説明

より多くのループのベクトル化を行うようにコンパイラーに指示するには、simd プラグマを使用します。simd プラグマを使用したベクトル化は、完全に自動化されたアプローチを補完します (ただし、置き換えることはできません)。

明示的に vectorlength() 節または vectorlengthfor() 節が指定されていない場合、コンパイラーは独自のコストモデルを使用して vectorlength を選択します。 privatefirstprivatelastprivatelinear、および reduction で正しくない変数が指定されたり、あるいは適切な変数が指定されていない場合、ランタイムエラーや正しくない結果など、意図しない問題が発生する可能性があります。

特定の変数は、privatelinear、または reduction 節の 1 つのインスタンスでのみ指定することができます。

コンパイラーがループをベクトル化できない場合は、警告が出力されます (assert 節を使用して警告をエラーとすることができます)。

なんらかの理由でベクトライザーがループのベクトル化を停止する必要がある場合は、SIMD ループに fast 浮動小数点モデルが使用されます。

simd プラグマは、すべての自動ベクトル化が可能なループに影響するわけではありません。いくつかのループでは SIMD ベクトル・セマンティクスを表現できません。

simd プラグマには、次の制限が適用されます

より多くのベクトル化を行う変換を無効にするには、-no-vec -no-simd (Linux* および OS X*) または /Qvec- /Qsimd- (Windows*) オプションを指定してください。

ユーザー指示によるベクトル化 (SIMD ベクトル化とも呼ぶ) では、#pragma simd アノテーション付きのループのベクトル化に失敗した場合、エラーを報告するかどうか指定できます。 デフォルトでは、#pragma simdnoassert に設定されていて、ループのベクトル化に失敗すると、コンパイラーは警告を発行します。 #pragma simd アノテーション付きのループのベクトル化に失敗した場合、コンパイラーにエラーを報告するように指示するには、#pragma simdassert 節を追加します。 #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];
  }
}

このヘルプトピックについてのフィードバックを送信