インテル® C++ コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス

プロセッサー・グラフィックス向けの共有ローカルメモリーのプログラミング拡張

2 レベルの並列処理

2 レベルのループの入れ子の並列処理では、オフロードカーネルを構成する並列ループの入れ子にほかの並列ループの入れ子が含まれます。

カーネルを実行するスレッドも 2 レベルで構成されます。多次元のスレッド空間全体が、同じサイズと形状のスレッドグループに分割されます。各スレッドグループに分割されるスレッド空間は連続する矩形領域で、グループ内の個々のスレッドにさらに分割されます。

各スレッドグループにはマスタースレッドがあります。

コンパイラーとオフロードランタイムは、第 1 レベルの並列ループの入れ子と第 2 レベルの並列ループの入れ子の反復を、ランタイムに作成されるスレッド空間にマップし、ループの入れ子を並列に実行します。並列処理は、次のように行われます。

  1. 第 1 レベルの入れ子の反復はスレッドグループ間で分配され、各グループは 1 反復だけ実行します。反復に含まれるコードは、各グループ内のすべてのスレッドによって並列に実行されます。このコードには、1 つ以上の第 2 レベルの入れ子が含まれていなければなりません。第 2 レベルの入れ子が複数ある場合は、間にシリアルコードと呼ばれるコードが含まれることがあります。

  2. コンパイラーは、反復がグループ内のスレッド間で分配され、並列に実行されるように第 2 レベルの入れ子を変換します。ただし、シリアルコードは変換されず、グループ内のすべてのスレッドによってそのまま実行されます。後述するシリアルコードの制約事項は、シリアル領域の実行時にすべてのスレッドが同じプログラムステートになることを保証します。つまり、すべてのスレッドで、すべてのローカル変数の値が同じになります。

スレッドバリアは、グループ内のすべてのスレッドがバリアに到達するまで、ほかのスレッドがそこで待機するようにします。

第 2 レベルの入れ子の最後に暗黙のスレッドバリアはありません。そのため、必要に応じて追加する必要があります。_gfx_gpgpu_thread_barrier 関数はスレッドバリアを挿入します。

スレッド・グループ・ローカル・データ

スレッド・グループ・ローカル (TGL) 変数と呼ばれる特殊な変数があり、各スレッドグループには 1 つの TGL 変数があります。この変数は、スレッドグループの開始前に割り当てられ、終了後に破棄されます。TGL 変数はグループ内のスレッド間で共有されるため、TGL 変数への変更は他のスレッドも直ちに利用できます。TGL 配列の同じ要素にアクセスする場合などにデータ競合が発生する可能性があります。ただし、通常、スレッドは TGL データへ段階的にアクセスし、各フェーズでそれぞれのスレッドは TGL データの一部にのみアクセスするため、ほかのスレッドと競合することはありません。また、この場合、フェーズ間にスレッドバリアを追加することで簡単に競合を回避できます。

一般に、このプログラミング拡張を利用してプロセッサー・グラフィックスへオフロードできるのは、TGL データ宣言、第 2 レベルの並列ループの入れ子、スレッドバリア、シリアルコードを含む第 1 レベルの並列ループの入れ子です。次に例を示します。

<第 1 レベルの並列ループの入れ子> {
  <slm データ宣言>
  <第 2 レベルの並列ループの入れ子>
  <slm データ宣言>
  <シリアルコード>
  <バリア>
  <第 2 レベルの並列ループの入れ子>
}

構文

次の表は、SLM の実装に使用するキーワードの説明です。

キーワード

説明

_Thread_group

スレッドグループ間で反復が分配される第 1 レベルの並列ループの入れ子を構成するループをマークします。このキーワードは、第 1 レベルの並列ループの各ループの入れ子に追加します。

このキーワードが指定されていないループの入れ子は第 2 レベルのループの入れ子です。

例: 2 次元の第 1 レベルのループの入れ子と 2 次元のスレッドグループ空間

#pragma offload target(gfx)
 _Cilk_for _Thread_group (...){
   _Cilk_for _Thread_group (...){
     ...// ループの入れ子の本体
   }
  }

インテル® Cilk™ Plus は、インテル® C++ コンパイラー 18.0 では非推奨の古い機能です。プロセッサー・グラフィックスへオフロードする代替手段は、将来のリリースで提供される予定です。詳細は、「インテル® Cilk™ Plus の代わりに OpenMP* またはインテル® TBB を使用するためのアプリケーションの移行」を参照してください。

__thread_group_local

スレッド・グループ・ローカル・データのメモリー領域に対応する名前付きアドレス空間を指定するアドレス空間の型修飾子です。この修飾子を使用して、次のものを宣言できます。

  • TGL 変数または配列。コンパイラーは、この変数をスレッド・グループ・ローカル・ストレージに配置し、スレッドグループ内のスレッドが同じ位置を使用してこの変数にアクセスするように (つまり、この変数を共有するように) しなければなりません。例えば、次の構文は、配列 arr をグループ内のスレッド間で共有されるように宣言します。

    __thread_group_local int arr[100];
  • スレッド・グループ・ローカル・ストレージに割り当てられたデータへのポインター。コンパイラーは、このようなポインターの逆参照で、汎用アドレス空間にあるポインターとは異なるコードを生成することがあります。例えば、次の構文は、スレッド・グループ・ローカル・データへのポインターを宣言します。

    float __thread_group_local *p;

このアドレス空間は常に共有ローカルメモリーにマップします。

関連情報