インテル® C++ コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス
このトピックは、インテル® メニー・インテグレーテッド・コア (インテル® MIC) アーキテクチャーまたはインテル® グラフィックス・テクノロジーをターゲットとする場合にのみ適用されます。
デフォルトでは、offload プラグマを使用すると、プラグマに到達した CPU スレッドは次の文へ進む前にオフロードの完了を待機します。CPU がオフロードを開始してすぐに次の文へ進むように指定することで、非同期オフロード計算を実行できます。
非同期オフロード計算を指定するには、offload プラグマで signal 節を指定して計算を開始し、続いて offload_wait プラグマを使用してオフロード計算の完了を待機します。
または、インテル® MIC アーキテクチャー上では、非ブロック API _Offload_signaled() を使用して、特定のターゲットデバイスでオフロードコードのセクションの実行が完了したかどうか判断することもできます。
インテル® AVX MIC アーキテクチャー上では、signal 節と wait 節、offload_wait 構造、および _Offload_signaled() API は、特定のターゲットデバイスに関連するため、target() 節で target-number を指定する必要があります。
シグナルが開始される前にシグナルを照会すると、未定義の動作を引き起こし、アプリケーションはランタイムアボートします。例えば、ターゲットデバイス 1 で開始されたシグナル (SIG1) をターゲットデバイス 0 で照会する場合について考えてみます。シグナルはターゲットデバイス 1 で開始されているため、ターゲットデバイス 0 に関連付けられたシグナル (SIG1) はなく、アプリケーションはアボートします。
次の例では、別の CPU スレッドを追加することなく、CPU はオフロード計算を行い、同時に処理を続行します。
// インテル® MIC アーキテクチャーの例
char signal_var;
do {
#pragma offload target (mic:0) signal(&signal_var)
{
long_running_mic_compute();
}
concurrent_cpu_activity();
#pragma offload_wait target (mic:0) (&signal_var)
} while (1);
// プロセッサー・グラフィックスの例
int* in1 = (int*)malloc(SIZE * sizeof(int));
int* in2 = (int*)malloc(SIZE * sizeof(int));
int* res = (int*)malloc(SIZE * sizeof(int));
res[0:SIZE] = __sec_implicit_index(0);
#pragma omp target map(from: in1[0:SIZE]) nowait // CPU はすぐに実行を継続
#pragma omp parallel for
for (int i = 0; i < SIZE; i++) {
in1[i] = 1;
}
#pragma omp parallel for
for (int i = 0; i < SIZE; i++) {
in2[i] = i;
}
#pragma omp taskwait // 上記の並列 for ループの完了を待機
#pragma omp parallel for
for (int i = 0; i < SIZE; i++) {
res[i] = in1[i] + in2[i];
}
int errors = 0;
for (int i = 0; i < SIZE; i++) {
if (i + 1 != res[i]) {
errors++;
}
}
if (errors > 0) {
printf("FAIL\n");
}
else {
printf("pass\n");
}
free(in1);
free(in2);
free(res);