インテル® C++ コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス
このトピックは、インテル® メニー・インテグレーテッド・コア (インテル® MIC) アーキテクチャーをターゲットとする場合にのみ適用されます。
コードのオフロード領域の実行時間と実行中のデータ転送量を測定することができます。
ホストとターゲットで実行が進むと、オフロードに関する情報を含むオフロードレポートを取得することができます。オフロードレポートには次の情報が含まれます。
コードのオフロード領域の実行時間
ホストとターゲット間のデータ転送量
デバイスの初期化と個々の変数の転送を含む詳細
次のメカニズムを使用してオフロードレポートを有効または無効にすることができます。
OFFLOAD_REPORT 環境変数
_Offload_report API
コンパイラー・オフロード・レポートの行は、(インテル® MKL からのオフロードのようなほかのオフロードとは異なり) コンパイラーのオフロードからの出力であることを明確に示すために [オフロード] で始まります。
ホスト上の処理は [ホスト] と表記され、ターゲット上の処理は [MIC n] (n はオフロードされるコプロセッサーの論理番号) と表記されます。レポートの先頭に、論理デバイスと物理デバイスの割り当てが表示されます。
OFFLOAD_DEVICES 環境変数を指定すると、オフロードされたプログラムは物理デバイスのサブセットを使用できます。
複数のホストスレッドでオフロードを開始する場合、もしくは非同期オフロードが指定された場合、複数のオフロードが同時に行われることがあるため、特定の offload プラグマに関連する出力すべてにタグを付ける必要があります。タグがない場合、同時に進行する複数のオフロードからの情報が混在し、どの行がどのオフロードから出力されたものか判断できなくなります。[タグ n] 形式のタグは、特定のオフロードに属するオフロードレポートの行を識別します。
レポートの最初の 2 つの行は各オフロードのソースファイル名と offload プラグマの行番号です。その後、そのオフロードにタグを割り当てる行が出力されます。そのオフロード用に出力される後のレポート行では、そのオフロードに関連する行に、[タグ n] が使用されます。
レポートの残りの部分には、主要な処理の行が含まれます。これらの行では、処理がどのオフロードに属するか識別するタグの後に、処理のアノテーションが続きます。アノテーションは次のとおりです。
行マーカー | 説明 |
---|---|
[状態] | オフロードの一部として実行されている処理。 |
[変数] | 転送された変数名および転送の向き。 |
[CPU 時間] | ホスト上の offload プラグマの実行時間。 |
[MIC 時間] | ターゲット上のオフロード実行時間。 ホストとターゲット間のデータ転送時間を除く、ターゲット上の実行時間のみカウントされます。 |
[CPU->MIC データ] | ホストからターゲットへ転送されたデータのバイト数。 |
[MIC->CPU データ] | ターゲットからホストへ転送されたデータのバイト数。 |
[状態] の後に出力されるさまざまな情報は、オフロード・ライブラリーの内部処理に関する説明で、ランタイムエラーが発生する可能性のあるポイントの診断に役立ちます。ほとんどの場合、この情報から処理について知ることができます。
この例 example.c のオフロードレポートは次のようになります。
1 int Hysum(int * abc, int * efg, int siz)
2 {
3 int sumT = 0;
4 int k;
5
6 #pragma offload target(mic:0) \
7 in(abc : length(siz)) \
8 out(efg : length(siz/2)) \
9 nocopy(k)
10 {
11 if (_Offload_get_device_number() > -1) {
12 printf("On device : %d\n",_Offload_get_device_number());
13 fflush(0);
14 }
15
16 sumT = 0;
17 for (k=0; k < (siz/2) ;k++) {
18 efg[k] = abc[k] + abc[k + (siz/2)];
19 sumT += efg[k];
20 }
21 }
22 return sumT;
23 }
24
25 int main()
26 {
27 int j = 10;
28 int i = 0;
29 int n;
30 int *tuv, *xyz;
31
32 tuv = _mm_malloc(j * sizeof(int), 64);
33 xyz = _mm_malloc( (j/2) * sizeof(int), 64);
34
35 for (n=0; n < j; n++) {
36 tuv[n] = n;
37 }
38 xyz[0:(j/2)] = 0;
39
40 i = Hysum(tuv, xyz, j);
41
42 for (n=0; n < (j/2); n++) {
43 printf(" xyz[%d]=%d ",n,xyz[n]);
44 }
45 printf("\n sum total=%d\n", i);
46
47 return 0;
48 }
offload キーワードを指定して [Q]opt-report-phase コンパイラー・オプションを使用すると、ホストとターゲット間のデータ転送に関するサマリー情報が得られます。ソースコードで定義されているオフロード領域ごとに 2 つのレポートが出力されます。1 つ目のレポートは、ターゲット MIC へのオフロード情報で、ホスト向けのコンパイルにより出力されます。2 つ目のレポートは、オフロード領域の概要で、ターゲット向けのコンパイルにより出力されます。 このレポートには、OFFLOAD_REPORT 環境変数を 3 に設定した場合と似た情報が含まれます。
$ icc example.c -o exampleC_exe -qopt-report-phase=offload example.c(6-6):OFFLOAD:Hysum: ターゲットへのオフロード MIC <expr> sumT, INOUT のデフォルトが OUT に変更されました。 siz_2_V$2, INOUT のデフォルトが IN に変更されました。 sumT, INOUT のデフォルトが OUT に変更されました。 siz_2_V$2, INOUT のデフォルトが IN に変更されました。 ホストからターゲットへ送られたデータ abc_2_V$0, (<expr>) 要素へのポインター siz_2_V$2, スカラーサイズ 4 バイト ホストがターゲットから受け取ったデータ efg_2_V$1, (<expr>) 要素へのポインター sumT, スカラーサイズ 4 バイト example.c(6-6):OFFLOAD:Hysum: アウトライン・オフロード領域 sumT, INOUT のデフォルトが OUT に変更されました。 siz_2_V$2, INOUT のデフォルトが IN に変更されました。 sumT, INOUT のデフォルトが OUT に変更されました。 siz_2_V$2, INOUT のデフォルトが IN に変更されました。 ターゲットがホストから受け取ったデータ abc_2_V$0, (<expr>) 要素へのポインター siz_2_V$2, スカラーサイズ 4 バイト ターゲットからホストへ送られたデータ efg_2_V$1, (<expr>) 要素へのポインター sumT, スカラーサイズ 4 バイト
ここからは、上記のソースプログラムのオフロードレポートについて説明します。
ホストとターゲットはそれぞれ独立して実行するため、いったんオフロードが開始されると、ホスト出力とターゲット出力を予測することはできず、実行ごとに異なります。ただし、すべてのホスト出力とすべてのターゲット出力はそれぞれ同じシーケンスになります。
ターゲットデバイスが初期化され、論理デバイスと物理デバイス間の割り当てが示されています。
[オフロード] [ホスト] [状態] 初期化 論理カード 0 = 物理カード 0 [オフロード] [ホスト] [状態] 初期化 論理カード 1 = 物理カード 1
example.c のオフロードコードは、行 6 でターゲットにオフロードされます。
[オフロード] [MIC 0] [ファイル] example.c [オフロード] [MIC 0] [行] 6
このオフロードに関するレポートを識別できるように、このオフロードにタグ値 Tag0 が割り当てられます。
[オフロード] [MIC 0] [タグ] Tag0
ホストでオフロードが開始されます。
[オフロード] [ホスト] [タグ 0] [状態] オフロードを開始
オフロードするターゲット関数を初期化します。
[オフロード] [ホスト] [タグ 0] [状態] 関数を初期化 __offload_entry_example_c_6Hysum
ポインターデータのデータ転送バッファーを作成します。
[オフロード] [ホスト] [タグ 0] [状態] ホストメモリーからバッファーを作成 [オフロード] [ホスト] [タグ 0] [状態] MIC メモリーからバッファーを作成 [オフロード] [ホスト] [タグ 0] [状態] ホストメモリーからバッファーを作成 [オフロード] [ホスト] [タグ 0] [状態] MIC メモリーからバッファーを作成
DMA を使用して、abc 変数のポインターデータがホストからターゲットへ送られます。
[オフロード] [ホスト] [タグ 0] [状態] ポインターデータを送信 [オフロード] [ホスト] [タグ 0] [状態] CPU->MIC ポインターデータ 40
siz 変数の非ポインターデータが収集され、ホストからターゲットへ送られます。
[オフロード] [ホスト] [タグ 0] [状態] コピーインデータを集約 [オフロード] [ホスト] [タグ 0] [状態] CPU->MIC コピーインデータ 4
ターゲット上でオフロードされたコード (行 6) が開始されます。
[オフロード] [ホスト] [タグ 0] [状態] MIC のタスクを計算
オフロードが完了しました。ターゲットからデータの受信を開始します。
DMA を使用してターゲットの efg 変数からポインターデータを受け取ります。
[オフロード] [ホスト] [タグ 0] [状態] ポインターデータを受信 [オフロード] [ホスト] [タグ 0] [状態] MIC->CPU ポインターデータ 20
これはターゲットからの出力です。ターゲット上でオフロードコードが呼び出されます。
[オフロード] [MIC 0] [タグ 0] [状態] ターゲット関数を開始 __offload_entry_example_c_6Hysum
このオフロードで abc 変数は IN です。
[オフロード] [MIC 0] [タグ 0] [変数] abc_2_V$0 IN
このオフロードで efg 変数は OUT です。
[オフロード] [MIC 0] [タグ 0] [変数] efg_2_V$1 OUT
このオフロードで sumT 変数は OUT です。
[オフロード] [MIC 0] [タグ 0] [変数] sumT OUT
このオフロードで siz 変数は IN です。
[オフロード] [MIC 0] [タグ 0] [変数] siz_2_V$2 IN
ターゲット上で、非ポインターデータがターゲットメモリーにコピーされます。
[オフロード] [MIC 0] [タグ 0] [状態] コピーインデータを分散
ユーザープログラムの出力:
On device : 0
ターゲット上で非ポインターデータ sumT 変数が収集され、ターゲットからホストへ送られます。
[オフロード] [MIC 0] [タグ 0] [状態] コピーアウト・データを集約 [オフロード] [MIC 0] [タグ 0] [状態] MIC->CPU コピーアウト・データ 4
非ポインターデータがターゲットメモリーにコピーされます。
[オフロード] [ホスト] [タグ 0] [状態] コピーアウト・データを分散
ターゲット上のホスト時間はゼロです。
[オフロード] [ホスト] [タグ 0] [CPU 時間] 0.832872 (秒)
ホストからターゲットに転送されたポインターデータと非ポインターデータ (abc 変数と siz 変数) の合計が出力されます。
[オフロード] [MIC 0] [CPU->MIC データ] 44 (バイト)
ターゲット上での実行時間が出力されます。
[オフロード] [MIC 0] [MIC 時間] 0.000298 (秒)
ターゲットからホストに転送されたポインターデータと非ポインターデータ (efg 変数と sumT 変数) の合計が出力されます。
[オフロード] [MIC 0] [MIC->CPU データ] 24 (バイト)
ユーザープログラムの出力:
xyz[0]=5 xyz[1]=7 xyz[2]=9 xyz[3]=11 xyz[4]=13 sum total=45
プログラムの最後にクリーンアップされます。
[オフロード] [MIC 1] [状態] データテーブルを登録解除 [オフロード] [MIC 0] [状態] データテーブルを登録解除 [オフロード] [ホスト] [状態] データテーブルを登録解除