小さなOpenMPプログラムは時々フリーズします(GCC、C、Linux)
質問
小さなOMPテストを書くだけで、常に正しく機能しません。
#include <omp.h>
int main() {
int i,j=0;
#pragma omp parallel
for(i=0;i<1000;i++)
{
#pragma omp barrier
j+= j^i;
}
return j;
}
の使用 j
この例では、すべてのスレッドから書くことは間違っていますが、
jには非決定的価値だけが必要です
フリーズがあります。
でコンパイルされています gcc-4.3.1 -fopenmp a.c -o gcc -static
4コアX86_CORE2 Linuxサーバーで実行: $ ./gcc
凍結しました(時には; 4-5の高速走行で1回のフリーズなど)。
ストラス:
[pid 13118] futex(0x80d3014, FUTEX_WAKE, 1) = 1
[pid 13119] <... futex resumed> ) = 0
[pid 13118] futex(0x80d3020, FUTEX_WAIT, 251, NULL <unfinished ...>
[pid 13119] futex(0x80d3014, FUTEX_WAKE, 1) = 0
[pid 13119] futex(0x80d3020, FUTEX_WAIT, 251, NULL
<freeze>
なぜフリーズ(デッドロック)があるのですか?
解決
私をプライベートにしてみてください。各ループには独自のコピーがあります。
もっと時間があるので、私は説明しようとします。デフォルトでは、OpenMPの変数が共有されます。変数をプライベートにするデフォルトがあるケースがいくつかあります。平行領域はそれらの1つではありません(したがって、マークの応答が間違っています)。元のプログラムでは、2つのレース条件があります。1つはIに、もう1つはJに1つあります。問題はiのものです。各スレッドはループを数回実行しますが、各スレッドによって変更されているため、スレッドがループを実行する回数は不確定です。すべてのスレッドが障壁を満たすためにバリアを実行する必要があるため、すべてのスレッドが同じ数にそれを実行するわけではないため、決して終わらない障壁につかむことができるケースを思いつきます。
OpenMP Specは、「遭遇するワークシェアリング領域とバリア領域のシーケンスはチーム内のすべてのスレッドで同じでなければならない」と明確に述べているため(OMP Spec v3.0、セクション2.8.3バリアコンストラクト)、そのため、不確定な動作があります。
他のヒント
複数のスレッドから同じ場所に追加しようとしています。並行してやろうとしていることはできません。合計を並行して行いたい場合は、それを小さな部分に分割して、その後収集する必要があります。
A5Bによる更新:正しいアイデアですが、コードの間違った部分が発見されました。 i
変数は両方のスレッドによって変更されます。
@ejd、私がプライベートとしてマークされた場合、私のプログラムは準拠していますか?
申し訳ありませんが、この質問を見ました。技術的には、変数「i」をプライベートとしてマークする場合、プログラムはOpenMPに準拠します。ただし、「J」にはまだ人種条件があり、プログラムが準拠している間(人種条件を持つ有効なケースがあるため)、「J」の値は不特定です(OpenMP仕様に従って)。
以前の回答の1つで、バリアの実装の速度を測定しようとしていると言いました。さまざまなOpenMPコンストラクトの結果を公開している結果を見たいと思うかもしれない「ベンチマーク」がいくつかあります。 1つはマーク・ブル(エディンバラ大学EPCC)によって書かれたもので、別の(スフィンクス)はローレンス・リバモア国立研究所(LLNL)から来ており、3番目(Parkbench)は日本のコンピューティングパートナーシップから来ています。彼らはあなたにいくつかのガイダンスを提供するかもしれません。