3
int main()
{
    int a=0;
    omp_set_num_threads(2);
    #pragma omp parallel reduction(+ : a)
    {
        a = omp_get_thread_num()+1;
    }
    std::cout << "Output:" << a;
    return 1;
}

openmp reduction を使用して間違った出力が得られます...次のコードでは、reduction(+) は threadnum() の合計の出力を示しますが、reduction (-) について言及すると、同じ出力が得られます... "+" と "-" は 3 として出力されます。

4

2 に答える 2

8

OpenMP 関数のリダクションは次のとおりです。各スレッドにはリダクション変数のローカル コピーが与えられ、 や などの操作はローカル コピー+=-=影響します。次に、最後に次のリダクション操作が実行されます。

a = init_value op a_0 op a_1 op a_2 op ... op a_(N-1)

ここNで、 はスレッド数でありinit_value、リダクション操作の初期化値です。+とリダクション操作の両方の初期化値-は 0 (ゼロ) です。ただし、減算には問題があり、最終値が形成される方法に対するコメントとして OpenMP 標準で説明されています (§2.9.3.6reduction節)。

(減算リダクションの部分的な結果が加算されて、最終値が形成されます。)

これは、reduction(-:a)すべてのプライベート値が一緒に加算されることを意味します。つまり、+-リダクションの両方が同等です。-リダクションはvar -= exprorvar = var - expr式とのみ結合されると想定されているため、これは正しい実装方法です。したがって、あなたのプログラムは標準に準拠しておらず、OpenMP の複雑な詳細を読まないことに値するものを得ることができます。

の正しい例は次のようにreduction(-:a)なります。

#pragma omp parallel reduction(-:a)
{
    a -= omp_get_thread_num() + 1;
}
于 2013-05-15T12:28:53.163 に答える
0

-減算演算子の可換性がないため、 を使用した還元は常に注意が必要です...すべてを加算してから結果を否定する方がよいでしょう。標準を読まなくても、コードを読めば誰にでも明らかです。

于 2013-05-15T12:42:31.613 に答える