1

私は次のような状況にあります:

#pragma omp parallel for private(i, j, k, val, p, l)

for (i = 0; i < num1; i++)  
    {  
   for (j = 0; j < num2; j++)  
       {
         for (k = 0; k < num3; k++)     
             {  
              val = m[i + j*somenum + k*2]  

              if (val != 0)  
              for (l = start; l <= end; l++)  
                  {  
                    someFunctionThatWritesIntoGlobalArray((i + l), j, k, (someFunctionThatGetsValueFromAnotherArray((i + l), j, k) * val));  
                  }

              }  
         }  

        for (p = 0; p < num4; p++)  
            {  
               m[p] = 0;  
            }    
      }

読んでくれてありがとう、おい!シリアル実装に対して上記(3倍高速)を使用すると、結果にごくわずかな違い(0.999967[omp]と1[シリアル])が異なることに気づきました。今、私はここで間違いをしていることを知っています...特にループ間の関係は明らかです。ompセクションを使用してこれを並列化することは可能ですか?shared(p)を作成するなどのいくつかのオプションを試しましたが、{これを行うと、シリアル形式のように正しい値が得られました}が、そのときは高速化されませんでした。

多数のforループでopenmpプラグマを処理するための一般的なアドバイスも、私にとっては素晴らしいことです。

4

1 に答える 1

1

これは実際には以前の質問の言い換えまたは改良です。「新しい」質問をするのではなく、それを編集した方が SOers に役立ちます。まだ ...

コードを記述すると、OpenMP は最も外側のループ (ステートメントによって制御されるループ) の反復を分割します。

for (i = 0; i < num1; i++)

利用可能なスレッドに。したがって、デフォルトのループ スケジュールを使用すると、4 つのスレッドがある場合、それぞれが反復の 1/4 を実行します。これはおそらく、スレッド 0 が繰り返しi = 0,1,2,...を実行し、スレッド 1 が繰り返し(num1/4)+1, (num1/4)+2,...を実行することを意味します。 OpenMP プログラミングの初心者であれば、ループの反復がスレッド間でどのように分散されているかを自分で調べる必要があります。また、ループ スケジューリングを変更した場合の影響も調査する必要があります。これは、並列プログラミングを学ぶ上で不可欠な部分です。

その後、OpenMP は各スレッドで内部ループを実行するため、各スレッドは変数によって制御されるループを実行しますj,k,l,p。これらはさらに並列化されません。プログラムは動的スレッド管理を実装していません。

この結果の 1 つは、すべてのスレッドがmのすべての値の配列を更新することですp。これは私には賢明に見えません。

シリアル実装の結果とパラレル実装の結果の間に矛盾があると書いています。ただし、どの結果が異なるかは指定しません。ループの最後で異なる値を持つ変数はどれですか? 一般に、fp 演算の実行順序は重要であるため、直列プログラムと並列プログラムで浮動小数点の結果が完全に等しいとは期待しないでください。fp 算術は、真に可換ではなく、真に結合的でも真に分配的でもありません。数値を加算する単純な操作でさえ、一般的なケースでは、同じプログラムのシリアル実行とパラレル実行で同じであることは保証できません。

ただし、報告する結果がどのように計算されるかを知らなければ、なぜ違いが得られるのかを説明することはまったく不可能です。これは「正常な」動作である可能性がありますが、エラーである可能性があります。

于 2010-04-21T16:35:15.983 に答える