インテル® C++ コンパイラー 14.0 ユーザー・リファレンス・ガイド
プラグマに続くループ文を、それらがターゲットで実行される際に並列に実行します。このプラグマは、インテル® グラフィックス・テクノロジーにのみ適用されます。
入れ子構造のループを並列化するには、このプラグマとともに offload 宣言子を使用します。完全入れ子ループを並列に実行するには、collapse 節を使用します。
ターゲットが利用できない場合、プラグマは無視され、CPU はループ反復をシリアルに実行します。CPU でループ反復を並列に実行するには、cilk_for キーワードなどの別の方法を使用します。
このプラグマに続くループ反復は cilk_for ループと同じ規則に従っていなければなりません。
prefetch/noprefetch
simd
次のキーワードとプラグマはこのプラグマに続くループで使用できません。
cilk_for
cilk_spawn
cilk_sync
OpenMP* プラグマ
プラグマに続く文が for ループでない。
配列表記が正しくない。
ループが cilk_for キーワードを使用したループの規則に従っていない。
for ループの数が collapse (n) 節で指定した数よりも少ない。
次に、このプラグマを使用してインテル® グラフィックス・テクノロジーをサポートするターゲットでループを並列に実行する方法を示します。
bool CrossFade::execute_offload (int do_offload)
{
unsigned char * inputArray1 = m_inputArray1, * inputArray2 = m_inputArray2,
* outputArray = m_outputArray;
int arrayWidth = m_arrayWidth, arrayHeight = m_arrayHeight, arraySize = m_arraySize;
unsigned a1 = 256 - m_blendFactor;
unsigned a2 = m_blendFactor;
// 次のコードを指定したターゲットで実行
#pragma offload target(gfx) if (do_offload) \
pin(inputArray1, inputArray2, outputArray: length(arraySize))
// このループを並列に実行
#pragma parallel_loop
for (int i=0; i<arraySize; i++)
{
outputArray[i] = (inputArray1[i] * a1 + inputArray2[i] * a2) >> 8;
}
return true;
}
次に、collapse (n) 節を使用してループ反復を分離し、完全入れ子ループをターゲットで実行する方法を示します。
bool MatmultLocalsAN::execute_offload(int do_offload)
{
int m = m_height, n = m_width, k = m_common;
float (* A)[k] = (float (*)[])m_matA;
float (* B)[n] = (float (*)[])m_matB;
float (* C)[n] = (float (*)[])m_matC;
// 次のコードを指定したターゲットで実行
#pragma offload target(gfx) if (do_offload) \
pin(A: length(m*k)), pin(B: length(k*n)), pin(C: length(m*n))
// 最初の 2 つのループ反復は完全入れ子ループの例。
// 残りのループ反復はループ外部のほかの関数を呼び出す。
// 残りのループ反復を含めると不完全入れ子ループになる。
// 完全入れ子ループの部分を実行するには、
// collapse 節を使用して並列に実行するループ反復を
// 指定する。
#pragma parallel_loop collapse(2)
for (int r = 0; r < m; r += TILE_m)
{
for (int c = 0; c < n; c += TILE_n)
{
float atile[TILE_m][TILE_k], btile[TILE_n], ctile[TILE_m][TILE_n];
#pragma unroll
ctile[:][:] = 0.0f;
// 残りのループ反復を含めると不完全入れ子ループに
// なる。
for (int t = 0; t < k; t += TILE_k)
{
#pragma unroll
atile[:][:] = A[r:TILE_m][t:TILE_k];
#pragma unroll
for (int rc = 0; rc < TILE_k; rc++)
{
btile[:] = B[t+rc][c:TILE_n];
#pragma unroll
for (int rt = 0; rt < TILE_m; rt++)
{
ctile[rt][:] += atile[rt][rc] * btile[:];
}
}
}
#pragma unroll
C[r:TILE_m][c:TILE_n] = ctile[:][:];
}
}
return true;
}