2017-11-27 15 views
2

簡略化された例を考えてみましょう。私は、以下の機能を持っていることを言う:ompを使用して並列に参照を使用する関数

int foo(int x, int y, bool &flag) { 
    if (x == y) 
    flag = true; 
    return x + y; 
} 

、その後のOpenMPを使用して並列に実行される:

bool flag = false; 

#pragma omp parallel for 
    for (int i = 0; i < n; i++) { 
    z[i] = foo(x[i], y[i], flag); 
    } 

私はここでの問題は、関数が並列し、それぞれで複数回呼び出されるということであることを推測しますのインスタンスは、同じflagを指しています。どのような簡単な解決法を使ってこれを修正するのが最善の方法ですか?

免責事項:例外が発生した場合フラグ:私は多くの人々がこのような方法で参照を使用することが悪いですが、私の場合には、それは、タスクを達成するための最も簡単な方法であると言うだろうとを知って

+0

参照は問題ではありません。問題はデータ競争です。たとえコードがインラインで書かれていても、それを得ることができます。 – StoryTeller

+0

@StoryTeller私は名前を知らなかったが、これはまさに私が意味していたものです。 – Tim

答えて

5

これはあなたにレースを与えるでしょう。この特殊なケースでは、はスレッドが変数を一方向に変更するだけなので、問題がないので、2つのスレッドが同じ時刻に書き込む場合、最終結果は同じになります。しかし、それでもなお悪いです。

参照は問題ではありませんが、外部関数を呼び出さないと同じ問題が発生します。次の例では、私は外部関数を使用しませんが、それは要点を変更しません。各スレッドは、今flagの独自のコピーを持っています

int main() { 
    int const n = 4; 
    int x[n]; 
    int y[n]; 
    int z[n]; 

    bool flag = false; 
#pragma omp parallel for reduction(|| : flag) 
    for (int i = 0; i < n; i++) { 
    if (x[i] == y[i]) 
     flag = true; 
    z[i] = x[i] + y[i]; 
    } 
} 

ソリューションは、OpenMPの減少を使用することです。 parallelブロックの最後(ループはfor)では、ローカルコピーは "or"を使用して縮小され、スレッドグローバル変数flagに格納されます。

場合によっては、をそのifステートメントの周りに置くこともできますが、パフォーマンスが大幅に低下します。

+2

関数への参照として 'flag'を渡すのか、それとも並列ループ内で直接使用するのかは関係ありません。 – Zulan

+0

@ズラン:確かに、それは良い点です。私はそれを私の答えに加えました。 –

関連する問題