0

私のコードの概要は次のとおりです。

#pragma omp parallel default(shared)
{
for(i; i<lim; i++)
    do_work();
}

そしてしばらくして:

do_work(){
    foo();
    bar();
}

foo(){
    #pragma omp for //etc
    for(i;i<l;i++) //your typical loop
}

bar(){ //here's the interesting part
    int i;
    int result;

    #pragma omp for reduction(+:result) private(i)
    for(i=0; i<lim; i++)
        result++;
}

コンパイルすると、次のエラーが発生します。

リダクション変数 'result' は外部コンテキストではプライベートです

IBMコンパイラのドキュメントによると、reduction

指定された演算子を使用して、リスト内のすべてのスカラー変数に対してリダクションを実行します。リスト内のリダクション変数はコンマで区切られます。

リスト内の各変数のプライベート コピーがスレッドごとに作成されます。ステートメント ブロックの最後で、リダクション変数のすべてのプライベート コピーの最終的な値が、演算子に適した方法で結合され、結果が共有リダクション変数の元の値に戻されます。

リダクション節で指定された変数:

  • オペレーターに適したタイプでなければなりません。
  • 囲んでいるコンテキストで共有する必要があります。
  • const 修飾されていてはなりません。
  • ポインター型であってはなりません。

強調が追加されました。外側の並列領域はすべての変数を として処理することになっているため、縮小が見つかったら に変換する必要sharedがあります。少なくとも、外側のスコープでは考慮すべきではありませんが、外側のスコープはすべての変数を明示的に. それが私の混乱の元です。resultprivateprivateshared

確かに、IBM コンパイラーの代わりに GCC を使用していますが、この場合に違いはありますか?

だから私の質問は次のとおりだと思います: OpenMP はなぜリダクション変数を扱うのですか? 外部コンテキストで共有として以前に宣言されている場合、プライベート変数として?

私はリダクションでのみこの問題を抱えています。他のすべては想定どおりに機能します(特に、まったく同じことを行う例がある場合)。

4

2 に答える 2

5

bar()は各 OpenMP スレッドによって個別に呼び出され、resultスレッドのスタックには 1 つの変数があるため、スレッドの数と同じ数の変数があります。他のスレッドがどこに s を格納しているかを知るスレッドはなく、それらを一緒に削減することはできません (そして意味がありません)。そのため、並列領域内から呼び出される関数の自動変数は事前に定義されており、スレッドはスタック スペースを共有しないため、これを変更することはできません。並列領域内で宣言された変数にも同じことが当てはまります。それらは領域の前には存在せず、実行中の各スレッドのスタック上にのみ存在します。他のスコープに存在する共有変数でのみ機能します。つまり、並列領域の前に宣言されているか、resultresultprivatereductionstatic、またはグローバルです。

于 2013-10-17T12:25:23.987 に答える
0

並列ブロックで定義されたものはすべて非公開にする必要があります。

あなたのものとあなたが提供したリンクの違いは、リンクresultの並列ブロックの外側ですでに定義されているため、共有として宣言できます。

于 2013-10-17T11:53:02.407 に答える