インテル® C++ コンパイラー 16.0 ユーザー・リファレンス・ガイド
reduction 節でリダクション演算子として利用可能なユーザー定義のリダクション (UDR) 関数 (リダクション識別子) を宣言します。
#pragma omp declare reduction (reduction-identifier : typename-list : combiner) [initializer-clause] |
reduction-identifier |
識別子または次の演算子のいずれか: +、-、*、&、|、^、&&、|| |
typename-list |
型名リスト |
combiner |
部分的な結果を組み合わせて 1 つの値にする方法を示す式 |
initializer-clause |
initializer (initializer-expr)。ここで、initializer-expr は omp_priv = initializer または function-name ( argument-list )。 1 つの initializer-clause を指定できます。 initializer-clause を省略すると、プライベート変数は、静的記憶域期間を持つオブジェクトの初期化に関する次の C 規則に従って初期化されます。 initializer-expr を省略すると、プライベート変数は、デフォルトの初期化に関する次の C++ 規則に従って初期化されます。 |
カスタム・リダクションを定義する場合、reduction-identifier と型が declare reduction プラグマを識別します。reduction-identifier は、declare reduction プラグマで指定した型の変数を使用して、後で reduction 節で利用できます。プラグマが複数の型に適用される場合、型ごとに個別の declare reduction プラグマがあるかのように扱われます。
この宣言は、プログラムで変数を宣言するのと同じくらい簡単に利用できます。combiner と initializer-expr (指定する場合) のコンテキストが declare reduction プラグマのコンテキストになります。combiner と initializer-expr は、プログラムで関数の本体を定義する場合と同様に、C/C++ 規則に従っていなければなりません。
現在の範囲において、reduction-identifier を同じ型や C/C++ 規則で互換性がある型で再宣言することはできません。
combiner には次の規則と制約事項が適用されます。
combiner では、reduction-identifier でレデュースされる変数の型の特殊な変数識別子 omp_in と omp_out を使用できます。これ以外の変数は combiner で許可されません。
omp_in 識別子は、各スレッドの部分的な結果 (ローカル変数) を参照し、omp_out 識別子は combiner 実行後の結合値が格納されたストレージを参照します。
reduction 節での combiner の実行回数と実行順序は不定です。
オプションの initializer-expr には次の規則と制約事項が適用されます。
initializer-clause を指定すると、リダクション・リスト項目のプライベート・コピーの初期化子として initializer-expr 値が使用されます。ここで、omp_priv 識別子は初期化されるストレージを参照します。
initializer-clause では、omp_priv 変数と omp_orig 変数のみ許可されます。
特殊な識別子である omp_orig は、レデュースされるオリジナルの変数のストレージを参照します。initializer-clause で omp_orig が変更された場合、動作は不定です。
initializer-expr の評価回数と評価順序は不定です。
initializer-expr が引数リストを含む関数名の場合:
引数の 1 つは、omp_priv またはomp_priv のアドレスでなければなりません。
initializer-expr は、指定された引数リストで関数を呼び出して評価されます。
そうでない場合、C/C++ initializer-expr が omp_priv の宣言と初期化を指定します。
combiner または initializer-expr の実行が、OpenMP* 構文や OpenMP* API 呼び出しの実行につながる場合、動作は不定です。
例 |
---|
#define abs(x) (x<0 ? -x : x) #define LARGENUM 2147483647 #define N 1000000 int data[N]; // data[N] にあるすべての整数値から最小値を返します int find_min_abs() { int i; int result = LARGENUM; #pragma omp declare reduction(minabs : int : \ omp_out = abs(omp_in) > omp_out ? omp_out : abs(omp_in) \ initializer (omp_priv=LARGENUM) #pragma omp parallel for reduction(minabs:result) for (i=0; i<N; i++) { if (abs(data[i]) < result) { result = abs(data[i]); } } return result; } |