2009-09-19 21 views
74

これらの2つの違いは何ですか?omp parallel対omp parallel

[A]

#pragma omp parallel 
{ 
    #pragma omp for 
    for(int i = 1; i < 100; ++i) 
    { 
     ... 
    } 
} 

[B]

#pragma omp parallel for 
for(int i = 1; i < 100; ++i) 
{ 
    ... 
} 

答えて

50

私は1つが他のショートカットで、任意の違いがあるとは思いません。あなたの正確な実装は、それらを別々に扱うかもしれません。

合わせ平行ワークシェア構築物は、一つワークシェアリング構造 なし他のステートメントを含む並列構造を特定 ためのショートカットです。許可された句は、パラレルおよびワークシェアリングコンストラクトに許可されている句の和集合です( )。

http://www.openmp.org/mp-documents/OpenMP3.0-SummarySpec.pdf

から撮影のOpenMPのための仕様はここにある:

http://openmp.org/wp/openmp-specifications/

44

はこれらは等価です。

#pragma omp parallelはスレッドのグループを生成し、#pragma omp forは生成されたスレッド間でループの反復を分割します。融合した#pragma omp parallel for指令で両方の作業を同時に行うことができます。

+0

私のコードでは、私はこの非常に構造を使用しています。しかし、 'schedule(static、chunk)'句をディレクティブに使用すると問題が発生します。コードは正常に動作しますが、MPIプログラムからこのコードを呼び出すと、無限ループに入ります。ループカウンタは、このループのすべての反復でゼロです。私は '#pragma omp parallel'ディレクティブでプライベートとして定義されたループカウンタを持っています。 MPIがコードを呼び出すときになぜ失敗するのかは分かりません。重要なのであれば、各MPIプロセスがクラスタの別のプロセッサ上で実行されているとは確信しています。スケジュールが問題を引き起こしているかどうかは考えられません。 –

+0

'#pragma omp parallel for'ディレクティブを使うと、同じことがうまくいきます。いくつかの違いがあるはずです。 –

+1

更新:それが判明したので、私はスケジュール句を使用するときにのみこの問題を観察していますので、組み合わせ並列または2つの異なる指令を使用するかどうかによって異なります。 –

2

私は4.7.0 ++グラムでforループを取るときstarkly異なるランタイムを見て、シリアルコード(なしopenmp

std::vector<double> x; 
std::vector<double> y; 
std::vector<double> prod; 

for (int i = 0; i < 5000000; i++) 
{ 
    double r1 = ((double)rand()/double(RAND_MAX)) * 5; 
    double r2 = ((double)rand()/double(RAND_MAX)) * 5; 
    x.push_back(r1); 
    y.push_back(r2); 
} 

int sz = x.size(); 

#pragma omp parallel for 

for (int i = 0; i< sz; i++) 
    prod[i] = x[i] * y[i]; 

を使用していますが79ミリ秒で実行されます。 "parallel for"コードは29ミリ秒で実行されます。 forを省略し、#pragma omp parallelを使用すると、ランタイムは最大179msになります。 はシリアルコードよりも遅いです。ここlibgomp

+2

omp parallelは別のスレッドでスレッドを分割せずにループを実行するので、メインスレッドは2番目のスレッドが終了するのを待っているからだと思います。時間は同期化に費やされます。 – Antigluk

+6

これは、 '#pragma omp for'がなければ、ループのマルチスレッド共有はまったくないからです。しかし、それはOPのケースではありませんでした。「#pragma omp parallel」の中で追加の '#pragma omp for'を使ってやり直してください。また、' #pragma omp parallel for'のように。 –

+0

私はこの答えが最高のものであると見ています。それは、 –

19

コードリンク(機械8のHW並行性を有する)parallelforhereを分離使用の一例です。つまり、いくつかのスレッドでforサイクルを実行する前に、OpenMPスレッドプライベートアレイの動的割り当てに使用できます。 parallel forケースでは同じ初期化を行うことはできません。

UPD: 質問例では、1つのプラグマと2つのプラグマに違いはありません。しかし、実際には、分離されたパラレルとディレクティブを使って、スレッド認識の動作をより多くすることができます。例えば 一部コード:

#pragma omp parallel 
{ 
    double *data = (double*)malloc(...); // this data is thread private 

    #pragma omp for 
    for(1...100) // first parallelized cycle 
    { 
    } 

    #pragma omp single 
    {} // make some single thread processing 

    #pragma omp for // second parallelized cycle 
    for(1...100) 
    { 
    } 

    #pragma omp single 
    {} // make some single thread processing again 

    free(data); // free thread private data 
} 
4

既に他の回答で述べたように、特定の実施例の両方のバージョンは、等価であるが、それらの間に1つの小さな差が依然として存在します。最初のバージョンには、 "omp for"の終わりに不必要な暗黙のバリアが含まれています。もう1つの暗黙的な障壁は、平行領域の終わりに見いだすことができます。 "nowait"を "omp for"に追加すると、少なくともOpenMPの観点から、2つのコードが同等になります。これは、OpenMPコンパイラが2つのケースで少し異なるコードを生成する可能性があるためです。