2013-05-08 11 views
5

申し訳ありませんが、タイトルが不明な場合は大変です。私はこれをどのように言葉にするのか分かりません。OpenMP反復の並列領域のループ

私は次の操作を行うことができますどのような方法があります場合、私は思ったんだけど:

#pragma omp parallel 
{ 
    for (int i = 0; i < iterations; i++) { 
     #pragma omp for 
     for (int j = 0; j < N; j++) 
      // Do something 
    } 
} 

このようなループのために民間の指定子を省略したものを無視して、私は私の外側の外にスレッドをフォークすることができますどのような方法があります私はちょうど内側のループを並列化することができるようにループ?私の理解から(私が間違っている場合は私を修正してください)、すべてのスレッドは外側のループを実行します。私は内部ループの動作については不明ですが、forはそれに遭遇する各スレッドにチャンクを配布すると思います。

私がしたいことは、外ループでiterations回をフォーク/ジョインする必要はありません。これは正しい戦略ですか?

外部ループが並列化されるべきでない場合はどうなりますか?それは、誰かが私がより良いのOpenMPを使用する際に利用するための戦略を理解することができるように、大規模なアプリケーションは、OpenMPを使用して並列化の例に私を指すようにした場合、それは素晴らしいことだ...

#pragma omp parallel 
{ 

    for (int i = 0; i < iterations; i++) { 
     for(int k = 0; k < innerIterations; k++) { 
      #pragma omp for 
      for (int j = 0; j < N; j++) 
       // Do something 

      // Do something else 
     } 
    } 
} 

です。私は何かを見つけることができないようです。

説明:ループの順序付けを変更したり、ブロック、キャッシング、および一般的なパフォーマンスの考慮事項を含まないソリューションを探しています。私は、これが指定されたループ構造上でOpenMPでどのように行われるのかを理解したいと思います。 // Do somethingには依存関係がある場合もあれば、依存関係が存在しない場合もあります。

+0

多分、あなたがしたいことの例を挙げることができます。私はコードに記入することを意味する//何かを行う –

+0

@raxman、それは役に立たないでしょう。これは、特定のアプリケーションの解決策ではなく、そのような問題に対する一般的な解決策の要求であることを意味します。 – Pochi

+0

あなたは先に進み、ある答えをupvote/acceptすることができます。人々が何か努力をして、すべてのことに対して非常に最小限のアップフォースを得たように見えます。 –

答えて

1

私はあなたの質問に答えることができません。私は数ヶ月前からOpenMPを使用してきましたが、このような質問に答えるときは、私が以下に示すようなhello world printfテストを行います。私はあなたの質問に答えるのに役立つと思います。また、#pragma omp for nowaitを試して、何が起こるか見てみましょう。

同じメモリアドレスに書き込まず、競合状態を作成する「//何かを実行し、//何か他のことを行う」ことを確認してください。また、多くの読み書きをしている場合は、キャッシュを効率的に使用する方法について考える必要があります。

#include "stdio.h" 
#include <omp.h> 
void loop(const int iterations, const int N) { 
    #pragma omp parallel 
    { 
     int start_thread = omp_get_thread_num(); 
     printf("start thread %d\n", start_thread); 
     for (int i = 0; i < iterations; i++) { 
      printf("\titeration %d, thread num %d\n", i, omp_get_thread_num()); 
      #pragma omp for 
      for (int j = 0; j < N; j++) { 
       printf("\t\t inner loop %d, thread num %d\n", j, omp_get_thread_num()); 
      } 
     } 
    } 
} 

int main() { 
    loop(2,30); 
} 

パフォーマンス面では、このようにループを融合させることを検討してください。

#pragma omp for 
for(int n=0; n<iterations*N; n++) { 
    int i = n/N; 
    int j = n%N;  
    //do something as function of index i and j 
} 
0

本当にコード内の依存関係に依存しているため、答えにくいです。しかし、これを解決するための一般的な方法は、このように、ループのネストを反転させることである。

#pragma omp parallel 
{ 
    #pragma omp for 
    for (int j = 0; j < N; j++) { 
     for (int i = 0; i < iterations; i++) { 
      // Do something 
     } 
    } 
} 

オフもちろん、これはあるいはあなたのコードはループ内にあるものに依存し、可能ではないことができます。

3

2つのforループを扱う方法は、あなたが望む振る舞いを達成するという意味で、私の右に見えます。外側のループは並列化されず、内側のループは並列化されています。よりよい何が起こるかを明確にするために

、私はあなたのコードにいくつかのメモを追加してみましょう:

#pragma omp parallel 
{ 
    // Here you have a certain number of threads, let's say M 
    for (int i = 0; i < iterations; i++) { 
     // Each thread enters this region and executes all the iterations 
     // from i = 0 to i < iterations. Note that i is a private variable. 
     #pragma omp for 
     for (int j = 0; j < N; j++) { 
      // What happens here is shared among threads so, 
      // according to the scheduling you choose, each thread 
      // will execute a particular portion of your N iterations 
     } // IMPLICIT BARRIER    
    } 
} 

暗黙のバリアは、スレッドがお互いを待つ同期のポイントです。親指の一般的なルールとして、内部ループではなく、の外部ループを並列化することが好ましい(上記で作成したiterationsポイントの代わりに)iterations*N繰り返しの単一の同期点が作成されるためです。

+0

外側のループは、アルゴリズムの複数のパスを指定することになっているため、並列化することはできません。申し訳ありませんが、私はそれについて明確ではなかった。 – Pochi

+0

外部ループは並列化されていません。その上にworksharingディレクティブがありません。 – Massimiliano

+0

"hello world printf"テストをコードで実行すると、すべてのことが示されます。バリアが削除されたことを示すラベルが追加されていることがわかります。言い換えれば、外部ループが並行化されていない状態で、それと並行しています。 –

関連する問題