この記事は、インテル® ソフトウェア・ネットワークに掲載されている「Guided Auto-Parallel (GAP)」(http://software.intel.com/en-us/articles/guided-auto-parallel-gap/) の日本語参考訳です。
ガイド付き自動並列化の概要
インテル® コンパイラーのガイド付き自動並列化機能は、シリアルコードのアプリケーション・パフォーマンスをベクトル化や並列化により向上させるためのアドバイスを提供します。
通常、コンパイラーにより生成されるアドバイスは、次の 3 つのカテゴリーに分けられます。
- ローカル変数の使用に関するアドバイス: ループの入れ子構造やルーチンの簡単なソース変更を行うようアドバイスします。例えば、ループの上限に対して (クラスメンバーの代わりに) ローカル変数を使用するようなアドバイス、またはループ本体の初めでローカル変数を無条件に初期化するようなアドバイス、あるいは関数定義のポインター引数に restrict キーワードを追加するようなアドバイス (適切な場合) などが表示されます。
- プラグマの適用に関するアドバイス: プラグマのセマンティクスが満たされる場合 (確認が必要)、特定のループレベルに新しいプラグマを適用するようアドバイスします。多くの場合、コンパイラーの利点を活用できるプラグマを適用し (つまり、暗黙に新しいプラグマ/ループ・プロパティーをアサートすることで)、最適化を改善することができます。
- コンパイラー・オプションの追加に関するアドバイス: 新しいプロパティーをアサートする新しいコマンドライン・オプションを追加するようアドバイスします。このアドバイスは特有のものですが、取り入れても、取り入れなくてもかまいません。このアドバイスを受けるには、-guide [Linux* および Mac OS* X] または /Qguide [Windows*] コンパイラー・オプションを指定するだけです。ガイド付き自動並列化によるコンパイル時は、オブジェクト・ファイルや実行ファイルは生成されません。
通常使うコンパイラー・オプションに加えて、-guide または /Qguide オプションを使用してください。指定された最適化レベルで有効になる最適化に関するアドバイスが出力されます。ガイド付き自動並列化で推奨されたアドバイスに従う場合は、推奨されたようにコードを変更するか、推奨されたコンパイラー・オプションを使用して、プログラムを再コンパイルします。この場合、-guide または /Qguide オプションは使用しないでください。再コンパイル後、プログラムのパフォーマンスは向上するでしょう。
自動並列化オプション [-parallel または /Qparallel] を指定してシリアルコードを並列化し、ガイド付き自動並列化による並列化のアドバイスを受ける場合は、ガイド付き自動並列化オプションを自動並列化オプションとともに使用します。
シングルスレッド・コードのパフォーマンスを向上する場合や、コンパイラーの自動並列化に依存しない明示的にスレッド化したアプリケーションのパフォーマンスを向上する場合は、自動並列化を有効にせずにガイド付き自動並列化オプションを使用します。
ガイド付き自動並列化 (GAP) 向けにプロジェクトを準備する
1) インテル® C++ プロジェクトに変換する
2) ビルド構成を「Release」に変更する
a. GAP はオプション /O2 以上でのみ有効になります。
3) 変換後、[ビルド] メニューから [クリーン] を選択します。
図 1: インテル® C++ プロジェクトへの変換
ガイド付き自動並列化 (GAP) を実行する
IDE でガイド付き自動並列化 (GAP) を実行する方法は、解析する対象 (ソリューション全体、プロジェクト、単一ファイル、関数、またはソースコードの一部の範囲) により複数あります。このチュートリアルでは、単一ファイルの解析を行います。
1) scalar_dep.cpp を右クリックして、[インテル(R) C++ Composer XE] > [ガイド付き自動並列化] > [ファイル “scalar_dep.cpp” の解析の実行] を選択します。
a. [解析の設定] ダイアログボックスで [解析の実行] をクリックします。
図 2: ガイド付き自動並列化解析の実行
図 3: 解析の設定
ガイド付き自動並列化 (GAP) から結果を表示する
GAP による出力結果は、IDE の標準 [出力] ウィンドウか、[エラー一覧] の [メッセージ] ウィンドウで確認できます。標準 [出力] ウィンドウの GAP メッセージの内容は、「GAP レポート記録開始」から「GAP レポート記録終了」までです。
図 4: IDE の標準 [出力] ウィンドウの GAP メッセージ
図 5: [エラー一覧] の [メッセージ] ウィンドウの GAP メッセージ
GAP メッセージはファイルに出力することもできます。[リマークをファイルに送る] チェックボックスをオンにして出力します。
図 6: GAP メッセージをファイルに出力するオプションを選択する
このオプションを選択すると、GAP メッセージは [出力] ウィンドウまたは [エラーリスト] ウィンドウには表示されません。
GAP メッセージの解析
GAP による出力結果を解析し、特定の推奨内容がソースコードに適しているかどうかを判断します。
このチュートリアルのサンプルでは、GAP は scalar_dep.cpp の 49 行目のループに対して次のメッセージが出力されます。
for (i=0; i < n; i++) { if (A[i] > 0) {b=A[i]; A[i] = 1 / A[i]; } if (A[i] > 1) {A[i] += b;} }
1>GAP レポート記録開始 Tue Jun 29 12:13:54 2010
1>
1>リマーク #30761: コンパイラーに自動並列化を向上させるアドバイスを生成させる場合は -Qparallel オプションを追加します。
1>C:\gap_test\test\scalar_dep.cpp(49): リマーク #30515: (VECT) 行 49 のループ は、次の変数への条件付き代入があるためベクトル化できません: b。
このループをベクトル化するには、この変数を各反復の最初で無条件に初期化します。
[確認] ループの各反復で変数の値を読み取る場合は、同じ反復でそれ以前に書き込まれた値でなければなりません。
1>このコンパイルセッションで出力されたアドバイス・メッセージの数: 1。
1>GAP レポート記録終了
デフォルトでは、コンパイラーは自動並列化を有効にし、自動並列化を向上させるアドバイスを取得するように、リマーク #30761 を出力します。リマーク #30515 は、if 変数 b が無条件で割り当てられれば、コンパイラーはループをベクトル化できることを示しています。
並列化について GAP のアドバイスを得るには、並列化 (/Qparallel) を有効にして GAP 解析を再度実行します。
図 7: 並列化 (/Qparallel) を有効にする
1>GAP レポート記録開始 Tue May 18 11:42:58 2010
1>
1>C:\test\scalar_dep.cpp(49): リマーク #30521: (PAR) 行 49 のループ は、次の変数への条件付き代入があるためベクトル化できません: b。
このループを並列化するには、この変数を各反復の最初で無条件に初期化します。
[確認] ループの各反復で変数の値を読み取る場合は、同じ反復でそれ以前に書き込まれた値でなければなりません。
1>C:\test\scalar_dep.cpp(49): リマーク #30525: (PAR) 行 49 のループのトリップカウントが 188 よりも大きい場合は、”#pragma loop count min(188)” を使用してこのループを並列化できます。
[確認] ループの反復回数が 188 以上であることを確認してください。
1>このコンパイルセッションで出力されたアドバイス・メッセージの数: 2。
1>GAP レポート記録終了
リマーク #30521 は、変数 b が条件付きで割り当てられるため、行番号 49 のループが並列化できないことを示し、リマーク #30525 は、コンパイラーがループを並列化するには、ループのトリップカウントが 188 以上でなければならないことを示しています。
GAP の推奨内容が適切で、プログラムのセマンティクスを変更しないことを確認したら、必要な変更を行い、ソースファイルを再コンパイルします。このループについては、GAP が推奨するように、ループの並列化とベクトル化を有効にします。
#pragma loop count min (188) for (i=0; i < n; i++) { b = A[i]; if (A[i] > 0) {A[i] = 1 / A[i];} if (A[i] > 1) {A[i] += b;} }
ループが並列化/ベクトル化されたことを確認するには:
1) GAP が推奨するようにコードを変更した後、変更箇所をベクトル化レポートや並列化レポートで確認します。
2) [追加のオプション] ダイアログボックスに /Qvec-report1 /Qpar-report1 オプションを追加します。(Visual Studio* では、インテル® コンパイラーを使用している場合に /Qipo を有効にする /GL オプションがデフォルトで有効になります。/Qipo が有効でない場合は、[C/C++] > [コマンドライン] > [追加のオプション] で追加する必要があります。)
3) ガイド付き自動並列化を有効にせずに再コンパイルします。
図 8: /Qvec-report1 /Qpar-report1 を追加して並列化レポート/ベクトル化レポートを出力する
[出力] ウィンドウに main.cpp の 23 行目の関数呼び出しがベクトル化および並列化されたことを示すメッセージが出力されます。これは、/Qipo (複数ファイルにわたるインライン展開) が有効になり、scalar_dep.cpp のループを含む関数が main.cpp でインライン展開されたことで、コンパイラーにより行 23 が自動的にベクトル化および並列化されたためです。まとめ
シリアル・アプリケーションの並列化は容易ではありません。インテル® コンパイラーのガイド付き自動並列化機能は、アプリケーションの並列化とベクトル化を支援する効率良いツールです。
最適化に関する注意事項 |
---|
インテル® コンパイラーは、互換マイクロプロセッサー向けには、インテル製マイクロプロセッサー向けと同等レベルの最適化が行われない可能性があります。これには、インテル® ストリーミング SIMD 拡張命令 2 (インテル® SSE2)、インテル® ストリーミング SIMD 拡張命令 3 (インテル® SSE3)、ストリーミング SIMD 拡張命令 3 補足命令 (SSSE3) 命令セットに関連する最適化およびその他の最適化が含まれます。インテルでは、インテル製ではないマイクロプロセッサーに対して、最適化の提供、機能、効果を保証していません。本製品のマイクロプロセッサー固有の最適化は、インテル製マイクロプロセッサーでの使用を目的としています。インテル® マイクロアーキテクチャーに非固有の特定の最適化は、インテル製マイクロプロセッサー向けに予約されています。この注意事項の適用対象である特定の命令セットの詳細は、該当する製品のユーザー・リファレンス・ガイドを参照してください。 改訂 #20110804 |