8

シミュレーションのインスタンスを並行して実行するために openMP を使用しています。

#pragma omp parallel for private(part) shared(P,lfcc,temp)
for (part = 0; part < P->Parts; part++)

ループの一部は、インデックス番号「part」の出力ファイルが既に存在するかどうかをチェックします (そのため、「Parts」の特定の値に対してシミュレーションを実行し、後で既存の結果を上書きせずに値を増やすことができます)。ただし、これには反復を順番に実行する必要があります。つまり、n スレッドの場合、最初に (1) から (n) の部分を同時に実行し、次に (n+1) から (2n) の部分を実行する必要があります。現在 (3 つのスレッドが並行して実行されており、"parts" が N に設定されている)、最初の部分 (0),(N/3),(2N/3) に続いて (1),(N) が実行され、動作が異なります。 /3+1)、(2N/3+1) など。

ここで、最初に 30 個のパーツがすべて完成したとします。次に、さらにパーツが必要であると判断し、「パーツ」を 45 に変更します。次に、最初のスレッドがパーツ (1)-(15)、2 番目のスレッド (16)-(30)、3 番目のスレッド (31-45) を取得します。最初の 2 つのスレッドは、割り当てられたすべての部分が既に完了していることをすぐに確認し、最後のスレッドをそのままにしておきます (プログラムが終了する前にバリア句を配置した場合)。

簡単な解決策の 1 つは、"part" 変数を 0 ではなく m+1 で開始することです。ここで、m は以前に完了したパーツの数です。しかし、openMP に上記の太字で示されている順序で反復を実行させることができるかどうか疑問に思っていました。

4

2 に答える 2

7

各スレッドが句1内で取得する反復ブロックのサイズを変更できます。3 つのスレッドの場合、最初のスレッドは反復 0、3、6、9 などを処理し、2 番目のスレッドは反復 1、4、7、10 などを処理し、3 番目のスレッドは反復 2、5、8 などを処理します。 11など。スレッドがすべてのステップを同時に同じ速度で実行するという保証はないため、ループのどこかで同期する必要があります (各反復の最後にバリアを配置して、反復の次のブロックが開始される前に同期することができます)。 )。scheduleschedule(static,1)

もう 1 つの解決策は、OpenMP タスク構造を使用することです。これを使用すると、1 つのスレッドで大きなループを実行して、計算タスクを生成できます。このループ内で出力ファイルの存在をチェックし、必要な場合にのみ新しいタスクを作成できます (たとえば、出力ファイルが存在しない場合)。

#pragma omp parallel
{
    ...
    #pragma omp single
    for (part = 0; part < P->Parts; part++)
    {
        if (!output_file_exists(part))
           #pragma omp task
           {
              ... computation for that part ...
           }
    }
    #pragma omp taskwait
    ...
}

あなたの問題を正しく理解できたことを願っています。

于 2012-09-19T08:19:00.077 に答える