4

OpenMP を使用した for ループの進行状況を知りたいです。リダクション ディレクティブが機能しないことはわかっていますが、次のように書きました。

#pragma omp for reduction (+:sum)
    for (int i=0; i < size; i++){
    // do something that takes about 10seconds 
    sum++;
#pragma omp critical
    cout << sum << " / " << size << endl; 
    }

これは次のようなものを返します:

1 / 100
1 / 100
2 / 100
1 / 100
...

しかし、私はこれが欲しい:

1 / 100
2 / 100
3 / 100

. ..

ディレクティブ中に正しいsum値を取得する方法はありますか? reductionまたは別の方法を使用する必要がありますか?

4

3 に答える 3

0

(共有カウンターの更新による)通信の必要性を回避するために、スレッド番号をこれまでに処理したアイテムの数と一緒に印刷することができます。

#pragma omp parallel
{
   int count = 0;
#pragma omp for schedule(dynamic)           // or whatever schedule you want
  for(int i=0; i<size; ++i) {
    // ...
    printf("@ %d: done %d loops\n",
           omp_get_thread_num(),++count);   // should not need a critical section
  }
}

特定のケースでは、作業に約10秒かかるため、通信は重要ではありませんが、特に作業が異なる場合は、動的なスケジュールを使用する価値がありますi

于 2012-09-15T17:55:07.767 に答える
0

この句には、最新の OpenMP 標準reductionのセクション 2.9.3.6 で詳細に説明されている、非常に明確に定義された意味があります。上記の目的で使用できるとは思えません。

とにかく、ソースにわずかな変更を加えるだけで、その動作を実装できる場合があります。

sum = 0
#pragma omp for shared(sum) schedule(guided)
for (int i=0; i < size; i++){
    // do something that takes about 10seconds 
#pragma omp critical(PRINT)
    {
      sum++;
      cout << sum << " / " << size << endl;     
    }
}

このようにして、一度に 1 つのスレッドのみが「合計」をインクリメントして画面に表示しようとすることが保証されます。各反復には長い時間がかかるため、この同期によってパフォーマンスの問題が発生することはありません。

于 2012-09-17T10:41:39.980 に答える
0

別の方法を使用する必要があります。リダクションはスレッドプライベート変数 (あなたの場合はsum) を作成し、すべてのスレッドが参加する最後にのみリダクションします。リダクションは実装に大きく依存します。すべてのスレッドが終了するのを待ったり、スレッドが終了するにつれて縮小したり、リダクション ツリーを作成したりできます。

代わりに、進行状況を追跡するために、numDone各スレッドが原子的に増加する別の変数を使用できます。

編集

ウィキペディアはそれをかなりうまく説明しています:

reduction(operator | embedded : list): 変数は各スレッドにローカル コピーを持ちますが、ローカル コピーの値はグローバル共有変数に要約 (縮小) されます。

于 2012-09-15T13:36:46.023 に答える