次の方法で共有


2.7.1 threadprivate ディレクティブ

threadprivate ディレクティブは、variable-list で指定されている名前付きファイル スコープ、名前空間スコープ、または静的ブロック スコープの変数を、スレッドに対してプライベートとして指定します。 variable-list は、不完全型でない変数のコンマ区切りリストです。 threadprivate ディレクティブの構文は次のとおりです。

#pragma omp threadprivate(variable-list) new-line

threadprivate 変数の各コピーは、そのコピーへの最初の参照が発生する前のプログラム内の未指定のポイントで、通常の方法で (マスター コピーがプログラムの逐次実行中に初期化される方法で) 1 回初期化されます。 オブジェクトが threadprivate 変数の明示的な初期化子で参照され、オブジェクトの値が、その変数のコピーを最初に参照する前に変更される場合、その動作は未定義です。

プライベート変数と同様、スレッドは、別のスレッドの threadprivate オブジェクトのコピーを参照することはできません。 プログラムのシリアル領域およびマスター領域上では、マスター スレッドのオブジェクト コピーが参照されます。

最初の並列領域が実行された後、動的スレッド機構が無効であり、またすべての並列領域に対してスレッド数が変わらない場合にのみ、threadprivate オブジェクト内のデータは維持されます。

threadprivate ディレクティブに対する制限は次のとおりです。

  • ファイル スコープまたは名前空間スコープの変数に対する threadprivate ディレクティブは、あらゆる定義または宣言の外側にある必要があり、構文的に、そのリスト内の変数に対するどの参照よりも先行している必要があります。

  • ファイル スコープまたは名前空間スコープでの threadprivate ディレクティブの variable-list 内の各変数は、構文的にそのディレクティブの前にあるファイル スコープまたは名前空間スコープの変数宣言を参照する必要があります。

  • 静的ブロック スコープ変数の threadprivate ディレクティブは、その変数のスコープ内に現れる必要があり、入れ子になったスコープ内に現れることはできません。 ディレクティブは構文的に、そのリスト内の変数に対するすべての参照よりも先行している必要があります。

  • ブロック スコープ内の threadprivate ディレクティブの variable-list 内の各変数は、構文的にそのディレクティブの前にある同じスコープ内の変数宣言を参照する必要があります。 変数宣言は、静的ストレージ クラスの指定子を使用する必要があります。

  • 1 つの翻訳単位内の threadprivate ディレクティブで変数を指定する場合、その変数が宣言されているすべての翻訳単位内の threadprivate ディレクティブでその変数を指定する必要があります。

  • threadprivate 変数は、copyincopyprivateschedulenum_threads、または if 句以外の句では指定できません。

  • threadprivate 変数のアドレスは、アドレス定数ではありません。

  • threadprivate 変数の型は、不完全型または参照型にはなれません。

  • 非 POD クラス型の threadprivate 変数は、明示的な初期化子で宣言されている場合、アクセス可能な、明白なコピー コンストラクターを持っている必要があります。

次の例では、初期化子内に現れる変数を変更するとどのように未定義動作の原因になるかを示し、補助オブジェクトとコピー コンストラクターを使用することにより、この問題を回避する方法を示しています。

int x = 1;
T a(x);
const T b_aux(x); /* Capture value of x = 1 */
T b(b_aux);
#pragma omp threadprivate(a, b)

void f(int n) {
   x++;
   #pragma omp parallel for
   /* In each thread:
   * Object a is constructed from x (with value 1 or 2?)
   * Object b is copy-constructed from b_aux
   */
   for (int i=0; i<n; i++) {
      g(a, b); /* Value of a is unspecified. */
   }
}

クロス リファレンス

  • 動的なスレッドについては、39 ページの「3.1.7 omp_set_dynamic 関数」を参照してください。

  • OMP_DYNAMIC 環境変数については、49 ページの「4.3 OMP_DYNAMIC」を参照してください。