インテル® C++ コンパイラー 16.0 ユーザー・リファレンス・ガイド

インテル® グラフィックス・テクノロジーでのオフロードの開始

このトピックは、インテル® グラフィックス・テクノロジーをターゲットとする IA-32 およびインテル® 64 アーキテクチャーにのみ適用されます。

#pragma offload target(gfx) の後の _Cilk_for ループや _Cilk_for ループの入れ子構造内部のコード、および #pragma offload target(gfx)#pragma offload target(gfx_kernel) が指定された関数コードは、ターゲットと CPU 用にコンパイルされます。target 属性に加えて、関数コードでは __declspec(target(gfx)) (Windows* および Linux*) または __attribute__((target(gfx))) (Linux* のみ) を使用して vector 属性を指定することもできます。target(gfx_kernel) を使用すると、ホストとターゲット用のバージョンが生成されますが、ターゲット用のバージョンをオフロード領域から呼び出すことはできません。代わりに、引数として非同期オフロード API に渡す必要があります。詳しくは、「非同期オフロード」で説明します。

#pragma offload target(gfx) は、並列ループの前、完全入れ子並列ループの前、またはインテル® Cilk™ Plus の配列表記文の前でのみ指定できます。並列ループは、_Cilk_for ループとして明記されていなければなりません。

インテル® グラフィックス・テクノロジー向けにプログラムしている場合、#pragma offload に次の節を指定できます。

pin 節は、ターゲットがアクセス可能なメモリーとの間でデータをコピーする代わりに、ホストとターゲット間で同じ物理メモリー領域を共有するため、はるかに高速です。このため、pin 節を使用することで、オフロードのコストは大幅に減ります。O(N2)) のように比較的小さなデータサイズの大量のワークを実行するカーネルでは、この最適化は重要ではありません。

ただし、OS は共有されるメモリーページをロックし、スワップできないようにするため、共有変数を多数使用するとシステム全体のパフォーマンスが低下する恐れがあります。

デフォルトでは、コンパイラーはホスト CPU とターゲットの両方で実行するアプリケーションを生成しますが、[Q]offload コンパイラー・オプションの否定形を使用して、同じソースコードから CPU のみで実行するアプリケーションを生成することもできます。

ターゲットへオフロードする例

unsigned parArrayRHist[256][256],
     parArrayGHist[256][256], parArrayBHist[256][256];

#pragma offload target(gfx) if (do_offload) \
     pin(inputImage: length(imageSize)) \
     out(parArrayRHist, parArrayGHist, parArrayBHist)

     __Cilk_for (int ichunk = 0; ichunk < chunkCount; ichunk++){
          …
     }

上記の例では、CPU コードが生成され、ランタイムは次の処理を行います。

完全な入れ子構造の _Cilk_for ループを使用してオフロードする例

float (* A)[k] = (float (*)[k])matA;
float (* B)[n] = (float (*)[n])matB;
float (* C)[n] = (float (*)[n])matC;

#pragma offload target(gfx) if (do_offload) \
     pin(A: length(m*k)), pin(B: length(k*n)), pin(C: length(m*n))

     __Cilk_for (int r = 0; r < m; r += TILE_m) {
          __Cilk_for (int c = 0; c < n; c += TILE_n) {
               …
          }
     }

上の例では、次のことが言えます。

関連情報