0

OpenMP の lastprivate コンストラクトの機能を理解するために、次のコードを実行しようとしています。lastprivate の定義によると、変数 lastprivate を宣言すると、すべてのスレッドに対してプライベートになり、並列ループの最後の反復を順番に実行しているスレッドの値が領域外の変数にコピーされます。コードは次のとおりです。

int main(void) 
{
    omp_set_num_threads(5);
    int i;
    int k =3;
    #pragma omp parallel private(i)
    {
        #pragma omp for lastprivate(k) 
        for(i=0; i< 5; i++ )
        {
            int iam = omp_get_thread_num();
            k = iam;
            printf("k=%d, iam=%d\t",k, iam);
        }
    }

    printf("\n k = %d", k);
}

次のような出力が生成されます。

k=0, iam=0  k=4, iam=4  k=3, iam=3  k=2, iam=2  k=1, iam=1  
k = 4

「for」で作業するスレッドのチームがある場合、どのスレッドが最後に実行されるかを実際に保証することはできません。したがって、最後のスレッドの値がグローバル 'k' に反映されるはずです。ただし、コードを何回実行しても、「k」の値は全体的に (つまり、並列セクションが終了した後) 4 のままです。

出力された値からも、スレッド 1 が最後に実行されたことがわかります。プリントがスレッドの正確な実行シーケンスを取得する信頼性がないと仮定したとしても、スレッド 4 が常に最後に実行され、その値が「k」に反映されることは明らかではないようです。

この問題に関するヘルプをいただければ幸いです。ありがとう。

4

2 に答える 2

1

どのスレッドが最後に実行されるかを確認するには、反復インデックスの値を出力する必要があります (スレッド ID を複製しないでください)。

#include<stdio.h>
#include<omp.h>

int main() {
  int kk;
#pragma omp parallel
  {
#pragma omp for schedule(runtime) lastprivate(kk) 
    for(int ii=0; ii < 1000; ii++ ) {
      kk = omp_get_thread_num();
      printf("ii = %d, kk = %d\n",ii,kk);
    }
  }
  printf("kk = %d\n", kk);
  return 0;
}

このプログラムを実行すると、反復を実行するスレッドが999の値を設定することがわかりますkk

この文について(私の強調):

「for」で動作するスレッドのチームがある場合、どのスレッドが最後に実行されるかを実際に保証することはできません

あなたの言うことは一般的に trueですが、1 つの例外があります (OpenMP 3.1 標準のセクション 2.5):

同じスケジュールと反復回数を持つ異なるループ領域は、同じ並列領域で発生した場合でも、スレッド間で異なる方法で反復を分散できます。唯一の例外は静的スケジュールの場合です...

ここで、スケジュールを指定しなかったため、次のルールが適用されます。

ループ ディレクティブにスケジュール句がない場合、def-sched-var ICV の現在の値によってスケジュールが決定されます。

def-sched-var決定した場合schedule(static)(私が経験したように、何度もそうです)、プログラムの最終的な出力は常に k = 4

于 2013-06-25T18:11:28.787 に答える