データを生成する大きなループがあります。各反復には、たとえば1秒かかり、データのチャンクが生成されます。すべてのチャンクを正しい順序でファイルに書き込む必要があります。
ループを並列化するだけの場合は、次のように記述できます(非常に単純化されています)。
FILE* f = fopen("output.txt", "w");
omp_lock_t lock;
omp_init_lock(&lock);
int nIterations = 1000000;
#pragma omp parallel for
for(int thread=0; thread<4; thread++)
{
int a=0, b=0, c=0;
for(int n=thread; n<nIterations; n+=4)
{
int value = do_computations(&a, &b, &c);
omp_set_lock(&lock);
fprintf(f, "%d\n", value);
omp_unset_lock(&lock);
}
}
#pragma omp barrier
fclose(f);
omp_destroy_lock(&lock);
これにより、出力がファイルに取り込まれますが、エントリの順序は保証されません。
すべてのスレッドがタスクを実行し、マスタースレッドがファイルに書き込み、スレッドが再開するように、実行を同期させたいと思います。言い換えれば、私はこのようなものが欲しいです:
#pragma omp parallel for
for(int thread=0; thread<4; thread++)
{
int a=0, b=0, c=0;
int values[4];
for(int n=thread; n<nIterations; n+=4)
{
values[n] = do_computations(&a, &b, &c);
#pragma omp barrier
if(thread == 0)
{
for(int i=0; i<4; i++)
fprintf(f, "%d\n", values[i]);
}
#pragma omp barrier
}
}
#pragma omp barrier
ただし、説明のつかない理由により、これはOpenMP仕様で禁止されています。
または私は試すことができます
#pragma omp parallel for
for(int thread=0; thread<4; thread++)
{
int a=0, b=0, c=0;
for(int n=thread; n<nIterations; n+=4)
{
int value = do_computations(&a, &b, &c);
#pragma omp ordered
{
fprintf(f, "%d\n", value);
}
}
}
#pragma omp barrier
fclose(f);
ただし、「for構文を使用したループの反復は...複数の順序付きディレクティブを実行してはならない」ため、これも機能しません。
コードを単一のループとして書き直したくないし、ループを交換したくない。
他のスレッド/同期ツールを使用せずに、OpenMPでこれを行うためのクリーンな方法はありますか?