omp parallelとomp parallel for


105

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

[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)
{
   ...
}

回答:


65

違いはないと思います。1つはもう1つのショートカットです。あなたの正確な実装はそれらを異なって扱うかもしれませんが。

組み合わせた並列ワークシェアリング構成は、1つのワークシェアリング構成を含み他のステートメントを含まない並列構成を指定するためのショートカットです。許可された条項は、並行およびワークシェアリング契約に許可された条項の和集合です。

http://www.openmp.org/mp-documents/OpenMP3.0-SummarySpec.pdfから取得

OpenMPの仕様は次のとおりです。

https://openmp.org/specifications/


66

これらは同等です。

#pragma omp parallelスレッドのグループを#pragma omp for生成し、生成されたスレッド間でループ反復を分割します。fuse #pragma omp parallel forディレクティブを使用すると、両方を一度に実行できます。


私のコードでは、まさにこの構造を使用しています。しかしschedule(static, chunk)、forディレクティブで句を使用すると、問題が発生します。コードは問題なく実行されますが、MPIプログラムからこのコードを呼び出すと、無限ループに陥ります。ループカウンターは、このループのすべての反復でゼロです。ループカウンターを#pragma omp parallelディレクティブでプライベートとして定義しています。MPIがコードを呼び出すときにのみ失敗する理由はわかりません。問題がある場合は、各MPIプロセスがクラスターの異なるプロセッサで実行されていることをいくらか確信しています。スケジュールが問題の原因かどうかはわかりません。
Rohit Banga

#pragma omp parallel forディレクティブを使用しても同じことがうまくいきます。いくつかの違いがあるはずです。
Rohit Banga、2011年

1
更新:結局のところ、この問題はschedule句を使用しているときにのみ観察されているので、組み合わせた並列forを使用するか、2つの異なるディレクティブを使用するかに依存しないと思います。
Rohit Banga

28

これは分離された使用例parallelfor ここです。つまりfor、複数のスレッドでサイクルを実行する前にOpenMPスレッドプライベートアレイの動的割り当てに使用できます。parallel forケースで同じ初期化を行うことは不可能です。

UPD:質​​問の例では、単一のプラグマと2つのプラグマの間に違いはありません。しかし実際には、分離された並列ディレクティブとforディレクティブを使用して、スレッド対応の動作を増やすことができます。たとえば、いくつかのコード:

#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
}

9

特定の例の両方のバージョンは同等ですが、他の回答ですでに述べたように、それらの間にはまだ1つの小さな違いがあります。最初のバージョンには、「omp for」の最後で発生する不要な暗黙のバリアが含まれています。他の暗黙のバリアは、並列領域の終わりにあります。「omp for」に「nowait」を追加すると、少なくともOpenMPの観点からは、2つのコードは同等になります。OpenMPコンパイラーが2つのケースでわずかに異なるコードを生成する可能性があるため、これについて言及します。


7

g ++ 4.7.0でforループを使用して使用すると、まったく異なるランタイムが表示されます

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];

シリアルコード(なしopenmp)は79ミリ秒で実行されます。「並列」コードは29ミリ秒で実行されます。省略した場合forを使用した#pragma omp parallel場合、ランタイムは最大179msを撮影します。これはシリアルコードよりも低速です。(マシンのハードウェア同時実行数は8です)

コードのリンク先 libgomp


2
それは、omp parallelがループをスレッドに分割せずに別のスレッドで実行するため、メインスレッドが2番目のスレッドの終了を待機しているためだと思います。同期に時間を費やしています。
Antigluk、2012年

7
これは#pragma omp for、ループがないとマルチスレッドでループを共有できないためです。とにかく、それはOPのケースではありませんでした。#pragma omp for内部に追加で再試行してください。バージョン#pragm omp parallelと同じように実行されます(同じでない場合)#pragma omp parallel for
Christian Rau 2013年

2
それは、彼らが「同等」ではありません示しように私は最高の一つとしてこの回答を参照してください
失敗した科学者

6

明らかにたくさんの答えがありますが、これは非常にうまく答えます(ソース付き)

#pragma omp for現在のチームの異なるスレッドにループの一部のみを委任しますチームは、プログラムを実行するスレッドのグループです。プログラムの開始時、チームは単一のメンバー(プログラムを実行するマスタースレッド)のみで構成され ています。

スレッドの新しいチームを作成するには、parallelキーワードを指定する必要があります。周囲のコンテキストで指定できます。

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

そして:

何が:並列、for、チーム

parallel、parallel for、forの違いは次のとおりです。

チームは、現在実行されているスレッドのグループです。プログラムの開始時、チームは単一のスレッドで構成されています。並列構造は、次のブロック/ステートメントの期間中、現在のスレッドを新しいスレッドのチームに分割し、その後、チームは1つにマージされます。forループの作業を現在のチームのスレッド間で分割します。

スレッドは作成されません。現在実行中のチームのスレッド間で作業が分割されるだけです。parallel forは、2つのコマンドを一度に簡略化したものです。Parallelは新しいチームを作成し、そのチームを分割してループのさまざまな部分を処理します。プログラムに並列構造が含まれていない場合、スレッドは1つしかありません。非スレッドプログラムと同様に、プログラムを開始して実行するマスタースレッド。

https://bisqwit.iki.fi/story/howto/openmp/

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.