2011-10-27 19 views
4

以下のコードを実行します(下記参照)。私は2つの独立したスレッドを生成したい、それぞれは並列のforループを実行するだろう。残念ながら、私はエラーが発生します。明らかに、forsectionの内部では生成できません。それを解決するには?OpenMP、ループ内のループ

#include <omp.h> 
#include "stdio.h" 

int main() 
{ 

omp_set_num_threads(10); 

#pragma omp parallel  
#pragma omp sections 
    { 
#pragma omp section 
#pragma omp for 
    for(int i=0; i<5; i++) { 
     printf("x %d\n", i); 
    } 

#pragma omp section 
#pragma omp for 
    for(int i=0; i<5; i++) { 
     printf(". %d\n", i); 
    } 
    } // end parallel and end sections 
} 

とエラー:

main.cpp: In function ‘int main()’: 
main.cpp:14:9: warning: work-sharing region may not be closely nested inside of work-sharing, critical, ordered, master or explicit task region [enabled by default] 
main.cpp:20:9: warning: work-sharing region may not be closely nested inside of work-sharing, critical, ordered, master or explicit task region [enabled by default] 

答えて

3

のOpenMPは並列領域内の並列領域を作成することはできません。これはOpenMPがプログラムnum_threadsパラレルスレッドの始めに作成します。非並列領域では、他のスレッドは使用されず、スリープします。新しいスレッドの頻繁な生成は、スリープスレッドをスリープ状態にすることに比べてかなり遅いため、これを行っています。

のであなただけのループを並列化する必要があります

#include <omp.h> 
#include "stdio.h" 

int main() 
{ 

omp_set_num_threads(10); 

#pragma omp parallel for 
    for(int i=0; i<5; i++) { 
     printf("x %d\n", i); 
    } 

#pragma omp parallel for 
    for(int i=0; i<5; i++) { 
     printf(". %d\n", i); 
    } 
} 
+0

しかし、おそらくomp_set_num_threads()は5以下になるべきです... –

+0

この場合、あなたは5に設定する必要がありますが、10であれば問題ありません。他の5は何もしません。 – tune2fs

+0

私は同意する、それは何も破壊しない。 –

6

をここでは、ネストされた並列処理を使用する必要があります。 sectionsomp forの問題は、スコープ内のすべてのスレッドがomp forに参加する必要があり、それらが明らかにセクションによって分割されていないことです。—だからあなたは関数を導入しなければならず、関数内で並列化を入れなければなりません。

#include <stdio.h> 
#include <omp.h> 

void doTask1(const int gtid) { 
    omp_set_num_threads(5); 
#pragma omp parallel 
    { 
     int tid = omp_get_thread_num(); 
     #pragma omp for 
     for(int i=0; i<5; i++) { 
      printf("x %d %d %d\n", i, tid, gtid); 
     } 
    } 
} 

void doTask2(const int gtid) { 
    omp_set_num_threads(5); 
#pragma omp parallel 
    { 
     int tid = omp_get_thread_num(); 
     #pragma omp for 
     for(int i=0; i<5; i++) { 
      printf(". %d %d %d\n", i, tid, gtid); 
     } 
    } 
} 


int main() 
{ 
    omp_set_num_threads(2); 
    omp_set_nested(1); 

#pragma omp parallel  
    { 
     int gtid = omp_get_thread_num(); 
#pragma omp sections 
     { 
#pragma omp section 
      doTask1(gtid); 

#pragma omp section 
      doTask2(gtid); 
     } // end parallel and end sections 
    } 
} 
+0

スレッドの数( 'omp_set_num_thread()')にハードコーディングがあるとか、ネストされた並列処理が有効になっている( 'omp_set_nested()')コードは、ベストプラクティスと不愉快なものの間のどこかにあります。通常はユーザーが環境変数を使用してこれらを設定できるようにします。チュートリアルの目的でのみここに明示的に設定されています。 –

1

実際には、最適なスレッド数は使用可能なCPUコアの数に等しいです。したがって、の場合はすべてと並列に処理してください。ompセクションの内部では使用できないすべてのコアで処理する必要があります。だから、あなたが達成しようとしていることは、最適ではありません。セクションを持たない2つのループを実行するための提案は理にかなっており、可能な限り最良のパフォーマンスを提供します。別の機能の中で並列ループを実行することもできますが、この「不正行為」はパフォーマンスを向上させるものではありません。

+0

2つの5反復ループと少なくとも10のコアからなる、合計10の高価な独立タスクが完全に可能です。その場合、どちらのループでも5つ以上のコアを使用することができないため、この方法で分割するのは理にかなっています。 –

+0

@Jonathan Dursi - この場合、あなたの提案はOKです。主にOpenMPの専門分野である画像処理のような長いループについて考えました。 –