1

私はこのparallel forループを持っています

struct p
{
    int n;
    double *l;
}

#pragma omp parallel for default(none) private(i) shared(p)
for (i = 0; i < p.n; ++i)
{
    DoSomething(p, i);
}

現在、新しい要素が に追加されているため、内部DoSomething()のが増加している可能性があります。これらの要素を並行して処理したいと思います。OpenMP のマニュアルには、リストでは使用できないと記載されているため、これらの新しい要素を別のリストに追加し、順次処理してから で結合します。私はこの回避策が好きではありません。これを行うためのよりクリーンな方法を知っている人はいますか?p.np.lparallel forDoSomething()p.lp.l

4

1 に答える 1

3

動的実行をサポートするための構造が OpenMP 3.0 に追加され、それがtask構造です。タスクはキューに追加され、可能な限り同時に実行されます。サンプル コードは次のようになります。

#pragma omp parallel private(i)
{
    #pragma omp single
    for (i = 0; i < p.n; ++i)
    {
       #pragma omp task
       DoSomething(p, i);
    }
}

これにより、新しい並列領域が生成されます。スレッドの 1 つがforループを実行し、 の値ごとに新しい OpenMP タスクを作成しますi。それぞれの異なるDoSomething()呼び出しはタスクに変換され、後でアイドル スレッド内で実行されます。ただし、問題があります。タスクの 1 つが に新しい値を追加するとp.l、作成者スレッドが既にforループを終了した後に発生する可能性があります。これは、タスク同期構造と次のような外側のループを使用して修正できます。

#pragma omp single
{
   i = 0;
   while (i < p.n)
   {
      for (; i < p.n; ++i)
      {
         #pragma omp task
         DoSomething(p, i);
      }
      #pragma omp taskwait
      #pragma omp flush
   }
}

このtaskwait構造は、キューに入れられたすべてのタスクが実行されるまでスレッドを待機させます。新しい要素がリストに追加された場合、の条件がwhile再び true になり、新しいラウンドのタスク作成が発生します。コンストラクトは、スレッド間でメモリ ビューを同flush期し、たとえば、最適化されたレジスタ変数を共有ストレージの値で更新することになっています。

OpenMP 3.0 は、OpenMP 2.0 でスタックしている MSVC を除くすべての最新の C コンパイラでサポートされています。

于 2012-08-13T08:09:19.380 に答える