インテル® C++ コンパイラー 17.0 デベロッパー・ガイドおよびリファレンス
このトピックは、インテル® メニー・インテグレーテッド・コア (インテル® MIC) アーキテクチャーにのみ適用されます。
インテル® MIC アーキテクチャー向けのインテルのオフロード拡張を使用する場合、#pragma offload で使用されるポインター変数の値が、オフロードプロセスによって CPU 上で変更されることはありません。 ポインター変数に格納される CPU アドレスは、インテル® MIC アーキテクチャー上の動的メモリー割り当ての追跡に使用されます。オフロード・ライブラリーは、インテル® MIC アーキテクチャー上のメモリーと関連付けられた CPU アドレスを管理し、データ転送時にそのマッピング情報を使用します。
ただし、それには、インテル® MIC アーキテクチャー上に割り当てられたメモリー範囲が、CPU 上に割り当てられたメモリー範囲と一致していなければなりません。場合によっては、必要ない CPU メモリーを割り当てなければならないことがあります。
targetptr 修飾子と preallocated 修飾子は、CPU で対応するメモリーを割り当てずに、インテル® MIC アーキテクチャーで動的メモリー割り当てを可能にします。
targetptr 修飾子は、インテル® MIC アーキテクチャー上でのみメモリーを割り当てます。
alloc_if(1) でメモリー割り当てを行う際に targetptr 修飾子を指定すると、CPU 変数はインテル® MIC アーキテクチャー上に割り当てられたメモリーアドレスで更新されます。 この値は CPU では意味がないため、有効な CPU アドレスが割り当てられない限り、オフロードプラグマのデータ転送元/転送先としてのみ使用できます。
targetptr 修飾子は、オフロードが必須の場合のみ使用できます。 targetptr と同時に指定できるオフロード修飾子は、align と alloc です。
alloc_if 修飾子と free_if 修飾子は、インテル® MIC アーキテクチャー上でのメモリー割り当て/割り当て解除を制御し、さらにオフロードランタイムによって管理されるランタイムテーブルへ割り当てられたメモリー範囲を追加/削除します。
次の例は、#pragma offload_transfer、#pragma offload、および targetptr 修飾子を使用してメモリーを割り当てます。
01 #define ALLOC alloc_if(1) free_if(0) 02 #define REUSE alloc_if(0) free_if(0) 03 #define FREE alloc_if(0) free_if(1) 10 int* cpu_p = (int*)malloc(1000*sizeof(int)); 11 __declspec(target(mic)) int* mic_p; 20 // targetptr を指定してインテル® MIC アーキテクチャー上にメモリーを割り当てます 21 // mic_p の値は、割り当て前は未定義、割り当て後は MIC 上のメモリーアドレスになります 22 #pragma offload_transfer target(mic) \ 23 nocopy(mic_p[0:1000] : ALLOC targetptr) 30 // CPU からインテル® MIC アーキテクチャーへデータを転送し、処理を行います 31 #pragma offload target(mic) \ 32 in(cpu_p[0:1000] : into(mic_p[0:1000]) REUSE targetptr) 33 { 34 … = *mic_p; // mic_p で指定されたデータを使用します 35 *mic_p = … // mic_p で指定された値を更新します 36 } 40 // インテル® MIC アーキテクチャーから CPU へデータを転送し、メモリーを解放します 41 #pragma offload_transfer target(mic) \ 42 out(mic_p[0:1000] : into(cpu_p[0:1000]) FREE targetptr)
preallocated 修飾子と targetptr 修飾子を同時に使用してインテル® MIC アーキテクチャー上でメモリーを割り当てることができます。 これらの修飾子を使用すると、ユーザーによって割り当て済みのインテル® MIC アーキテクチャー上のメモリーがデータ転送で利用可能になります。
alloc_if 修飾子と free_if 修飾子は、オフロード・ライブラリー・テーブルへの追加/削除にのみ影響し、メモリー割り当てはプログラマーが行います。
preallocated targetptr alloc_if(1) は、in 節とともに使用することはできません。インテル® MIC アーキテクチャー上ではメモリーを割り当て済みですが、そのメモリーアドレスがまだ CPU 上でデータ転送に利用できないためです。 out 節または nocopy 節とともに使用することはできます。 オフロードの終了時に、インテル® MIC アーキテクチャー上のメモリーアドレスが CPU に送られます。CPU 上に送られた変数は、以降のオフロードでメモリーアクセスに利用できます。
次の表は、preallocated targetptr と in、out、inout、nocopy 節、および alloc_if、free_if 修飾子を組み合わせて使用した場合の動作の説明です。
節 | 修飾子 | 説明 |
---|---|---|
in | alloc_if(0) free_if(0) | preallocated targetptr として登録された変数にデータが転送されます。 |
in | alloc_if(0) free_if(1) | preallocated targetptr として登録された変数にデータが転送され、オフロード後にその登録が削除されます。 |
in | alloc_if(1) free_if(0) | 許可されていません。 |
in | alloc_if(1) free_if(1) | 許可されていません。 |
out | alloc_if(0) free_if(0) | preallocated targetptr として登録された変数にデータが転送されます。 |
out | alloc_if(0) free_if(1) | preallocated targetptr として登録された変数からデータが転送され、オフロード後にその登録が削除されます。 |
out | alloc_if(1) free_if(0) | オフロードの終了時に、変数が preallocated targetptr として登録され、データが転送されます。 |
out | alloc_if(1) free_if(1) | オフロードの終了時に、変数が preallocated targetptr として登録され、その変数からデータが転送され、その後登録が削除されます。 |
inout | alloc_if(0) free_if(0) | オフロードの開始時に preallocated targetptr として登録された変数にデータが転送され、オフロードの終了時にその変数からデータが転送されます。 |
inout | alloc_if(0) free_if(1) | オフロードの開始時に preallocated targetptr として登録された変数にデータが転送され、オフロードの終了時にその変数からデータが転送され、登録が削除されます。 |
inout | alloc_if(1) free_if(0) | 許可されていません。 |
inout | alloc_if(1) free_if(1) | 許可されていません。 |
nocopy | alloc_if(0) free_if(0) | データ転送または登録の変更は発生しません。 |
nocopy | alloc_if(0) free_if(1) | データ転送は発生しません。オフロードの終了時に登録が削除されます。 |
nocopy | alloc_if(1) free_if(0) | データ転送は発生しません。オフロードの終了時に登録が追加されます。 |
nocopy | alloc_if(1) free_if(1) | データ転送または登録の変更は発生しません。 |
preallocated 修飾子は、オフロードが必須の場合のみ有効です。 オフロードがオプションの場合、メモリー割り当てを行うオフロードが実行されないと、割り当て済みメモリーを使用する以降のオフロードは失敗します。
preallocated 修飾子はプログラマーによってメモリーが割り当てられるため、align 修飾子と同時に使用することはできません。
alloc 修飾子は同時に使用することができます。
次の例は、#pragma offload と #pragma offload を使用してメモリーを割り当てます。
01 // malloc を使用してインテル® MIC アーキテクチャー上にメモリーを割り当て、登録します 02 #pragma offload target(mic) \ 03 nocopy(mic_p[0:1000] ALLOC preallocated targetptr ) 04 { 05 mic_p = user_malloc(1000*sizeof(int)); 06 } 10 // CPU からインテル® MIC アーキテクチャーへデータを転送し、処理を行います 11 #pragma offload target(mic) \ 12 in(cpu_p[0:1000] : into(mic_p[0:1000]) REUSE targetptr ) 13 { 14 = *mic_p; 15 *mic_p = … 16 } 20 // インテル® MIC アーキテクチャー上のメモリー登録を削除し、メモリーを解放します 21 #pragma offload target(mic) \ 22 nocopy(mic_p : FREE preallocated targetptr ) 23 { 24 free(mic_p); 25 }