インテル® C++ コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス
このトピックは、インテル® グラフィックス・テクノロジーをターゲットとする場合にのみ適用されます。
インテル® Cilk™ Plus は、インテル® C++ コンパイラー 18.0 では非推奨の古い機能です。プロセッサー・グラフィックスへオフロードする代替手段は、将来のリリースで提供される予定です。詳細は、「インテル® Cilk™ Plus の代わりに OpenMP* またはインテル® TBB を使用するためのアプリケーションの移行」を参照してください。
オフロードコードには次の制約があります。
#pragma offload target(gfx) は、_Cilk_for ループとして明記された完全入れ子ループの前、あるいはインテル® Cilk™ Plus の配列表記文の前でのみ指定できます。
#pragma offload 文に続く文の内部で __GFX__ マクロを使用しないでください。ただし、プラグマから呼び出されるサブプログラムでこのマクロを使用することはできます。
#pragma offload 領域内のマクロはすべて、同じ変数を使用してコードを評価しなければなりません。例えば、次のコードは N、inputArray および outputArray がコードの CPU バージョンで使用されていないため、未定義の動作を引き起こします
#pragma offload target(gfx) pin(inputArray, outputArray: length(N))
_Cilk_for (int i = 0; i < N; i++){
#ifdef __GFX__
outputArray[i] = inputArray[i]/N;
#else
// 何もしない
#endif
この制約は Windows* 8 以降および Windows Server* 2012 以降には適用されません。ターゲットへのオフロードはグラフィックス・ドライバーにアクセスできるセッションでのみ可能です。次のことが言えます。
オフロードは次の場合に可能です。
ローカル・デスクトップ・セッションから (デスクトップがロック状態でなくスクリーンセーバーが動作していない場合)
リモート・デスクトップ接続から (リモート・デスクトップ・クライアントのウィンドウが開いている場合)
Windows Vista*、Windows* 7、Windows Server* 2008、および以降のバージョンでは、すべてのサービスが実行されているとセッション 0 からオフロードすることはできません。
デフォルトでは、システム回復タイムアウト時間 (通常は 2 秒) より長くオフロードタスクを実行することはできません。オフロードランタイムでは、タスクは別のタイムアウト (32 秒) 後にハングまたは異常終了します。オフロードタスクを 32 秒より長く実行できるようにするには、タイムアウト検出と回復 (TDR) レジストリー・キーに関する Microsoft* のドキュメントを参照し、システム・レジストリーを編集してタイムアウトによる回復を無効にします。
この制約は Windows* 8 以降および Windows Server* 2012 以降には適用されません。専用グラフィックス・カードが搭載されているマシンでターゲットにオフロードするには、プライマリー・グラフィックス・デバイスをターゲットにする必要があります。
#pragma offload と関連する並列ループは完全な入れ子でなければなりません。並列ループは、_Cilk_for の要件を満たし、ループ・インデックス変数の型は int または unsigned のいずれかで、ストライドはコンパイル時に既知でなければなりません。
アプリケーションがターゲットとホストのコードを並列に実行する場合、フォルス・シェアリング問題を回避するため、ホストとターゲットが同じキャッシュラインを変更しないようにする必要があります。例えば、キャッシュラインのサイズの倍数になるように pin 節に渡す変数をパディングします。ホストとターゲットが同じ配列を処理する場合は、並列オフロードコードの書き込みアクセスが対応するようにします。変数に __declspec(avoid_false_share) を指定すると、その変数がアライメント (パディング) され、ほかの変数とのフォルス・シェアリングを回避できます。
ヘッダーファイル math.h は単精度関数 (sinf など) を倍精度に拡張するため、コンパイラーが単精度に戻すときにパフォーマンスが低下したり、問題が発生することがあります。この問題を回避するには、代わりに mathimf.h を使用します。
コンパイラーは数学関数のサブセットのみサポートします。これらの数学関数は、インテル® グラフィックス・テクノロジーの命令セット・アーキテクチャーに直接マップされるか (可能な場合)、コンパイラーと一緒に提供される SVML で実装されます。次の関数のみサポートされています。
acos/acosf
acosh/acoshf
asin/asinf
asinh/asinhf
atan/atanf
atanh/atanhf
cbrt/cbrtf
sqrt/sqrtf
ceil/ceilf
cos/cosf
erf/erff
erfc/erfcf
exp/expf
exp10/exp10f
exp2/exp2f
expm1/expm1f
fabs/fabsf
floor/floorf
invsqrt/invsqrtf
log/logf
log10/log10f
log1p/log1pf
log2/log2f
nearbyint/nearbyintf
rint/rintf
round/roundf
sin/sinf
sinh/sinhf
tan/tanf
tanh/tanhf
trunc/truncf
copysign/copysignf
atan2/atan2f
fmax/fmaxf
fmin/fminf
hypot/hypotf
pow/powf
倍精度の除算もサポートされており、SVML 関数の呼び出しに変換されます。
コンパイラーはヘテロジニアス・コードで可変長配列割り当てをサポートしません。例えば、float myArray[variableSize]; (variableSize は変数) を使用する代わりに float myArray[CONSTANT_SIZE]; (CONSTANT_SIZE はコンパイル時定数) を使用します。
long double 型の演算はターゲットコードではサポートされていません。
longjump/setjump はターゲットコードではサポートされていません。
次の間接制御フローはターゲットコードではサポートされていません。
関数のアドレスを受け取り、ポインターで関数を呼び出す関数ポインター
仮想関数の呼び出し
switch 文はターゲットコードではサポートされています。
例外はターゲットコードでは許可されていません。
RTTI はターゲットコードではサポートされていません。
可変長引数 (…) の関数はターゲットコードではサポートされていません。
次の制約は、共有仮想メモリー (SVM) モードには適用されません。
ホストとターゲット間でのポインターの共有およびコピーはサポートされていません。ポインターはターゲットとホストで異なる意味を持つため、ホストで有効なポインター値がターゲットで有効であるとは限りません。ポインター値の自動変換は行われません。
オフロードコードでは、ポインター型要素の配列、ポインターへのポインター、構造体やクラスのポインター型メンバーは使用できません。
target(gfx) ベクトル関数のポインター型または参照型の引数は linear または uniform のいずれかでなければなりません。ベクトル関数はポインター型または参照型の値を返すことはできません。
グローバル変数または静的変数はポインター型または参照型にできません。
ポインター型と非ポインター型の変換は許可されていません。
ポインターまたは参照のアドレスをとることはできません。
pragma offload の次の修飾子はサポートされていません。
alloc_if
free_if
alloc
into
in/out/inout/pin 節の次の修飾子はサポートされていません。
alloc_if
free_if
#pragma offload target (target-name [ :target-number ]) の target-number は無視されます。
ローカルスカラー変数は #pragma offload の in 節でのみ渡すことができます。
コンパイラーは #pragma offload 文の語彙スコープで使用される変数を in 節に自動的に追加するため、ローカルスカラー変数を in 節に追加することは冗長であり省略できます。ローカルスカラー変数は値で渡されます。オフロード後は、ターゲットコード内の変数に対する更新をホスト側で見ることはできません。
例えば、次のコードは var = 55、i = 0 を出力します。
int var = 55;
int i = 0;
#pragma offload target(gfx)
_Cilk_for (i = 0; i < 1; i++)
{
++var;
}
printf("var = %d, i = %d\n", var, i);
ローカル変数 var は in 節にのみリストできるため、次のコードはコンパイル時にエラーになります。
int var = 55;
int i = 0;
#pragma offload target(gfx) inout(var)
…
グローバル変数または静的変数は #pragma offload の pin 節にリストできません。
プロセッサー・グラフィックスでは、OpenMP* ランタイム・ライブラリー・ルーチンを利用できません。並列処理はホスト側で行われるため、ランタイム API を呼び出してターゲット側の動作 (タスク・スケジュールなど) を変更することはできません。OMP_、KMP_、GOMP_ で始まるものを含む、すべての OpenMP* 環境変数はサポートされません。
ドライバーにより管理される共有仮想メモリー (SVM) の使用には、次の制約があります。
ターゲット・ハードウェア・プラットフォームには、インテル® HD グラフィックス内蔵の第 5 世代インテル® Core™ プロセッサーが搭載されていなければなりません。
Windows* の場合、ターゲット OS は Windows® 10 以降でなければなりません。Linux* の場合、リリースノートでターゲット OS の要件を確認してください。