web-dev-qa-db-ja.com

firstprivateとlastprivateは、OpenMPのprivate句とどのように異なりますか?

私は公式の定義を見てきましたが、それでもかなり混乱しています。

firstprivate:各スレッドは変数の独自のインスタンスを持ち、変数は変数の値で初期化される必要があることを指定します。これは、変数が並列構造の前に存在するためです。

私には、それはプライベートのように聞こえます。私は例を探しましたが、それがどのように特別なのか、どのように使用できるのか理解していないようです。

lastprivate:変数の囲みコンテキストのバージョンが、最後の反復(forループ構造)または最後のセクション(#pragmaセクション)を実行するスレッドのプライベートバージョンに等しく設定されることを指定します。

次の例のおかげで、これをもう少しよく理解したように感じます。

#pragma omp parallel
{
   #pragma omp for lastprivate(i)
      for (i=0; i<n-1; i++)
         a[i] = b[i] + b[i+1];
}
a[i]=b[i];

したがって、この例では、lastprivateを使用すると、iをループ外で最後の値として返すことができます。

今日からOpenMPの学習を始めました。

67
SaiyanGirl

private変数は初期化されません。つまり、他のローカル自動変数と同様にランダムな値で始まります(そして、各スレッドのスタックで自動変数を使用して実装されることがよくあります)。例としてこの簡単なプログラムを取り上げます。

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

int main (void)
{
    int i = 10;

    #pragma omp parallel private(i)
    {
        printf("thread %d: i = %d\n", omp_get_thread_num(), i);
        i = 1000 + omp_get_thread_num();
    }

    printf("i = %d\n", i);

    return 0;
}

4つのスレッドを使用すると、次のようなものが出力されます。

thread 0: i = 0
thread 3: i = 32717
thread 1: i = 32717
thread 2: i = 1
i = 10

(another run of the same program)

thread 2: i = 1
thread 1: i = 1
thread 0: i = 0
thread 3: i = 32657
i = 10

これは、iの値が並列領域内でランダム(初期化されていない)であり、並列領域の後にその変更が表示されないことを明確に示しています(つまり、変数は領域に入る前に値を保持します)。

ifirstprivateにすると、並列領域の前にある値で初期化されます。

thread 2: i = 10
thread 0: i = 10
thread 3: i = 10
thread 1: i = 10
i = 10

並列領域内のiの値に対する変更は、その後は表示されません。

lastprivateについてはすでに知っています(ワークシェアリング構造がないため、単純なデモプログラムには適用できません)。

はい、firstprivatelastprivateprivateの特殊なケースです。 1つ目は値を外部コンテキストから並列領域に取り込み、2つ目は値を並列領域から外部コンテキストに転送します。これらのデータ共有クラスの背後にある理論的根拠は、並列領域内ではすべてのプライベート変数が外部コンテキストからの変数をシャドウすることです。つまり、代入操作を使用して内部からiの外部値を変更することはできません並列領域。

128
Hristo Iliev

firstprivatelastprivateは、privateの特殊なケースです。

1つ目は値を外部コンテキストから並列領域に取り込み、2つ目は値を並列領域から外部コンテキストに転送します。

3
Amol Jain