高レベルな最適化 (HLO) とは、高水準プログラミング言語で開発されたアプリケーションに含まれているソースコード上の特性 (ループや配列など) を利用した最適化手法です。HLO では、ループ変換の手法に次のものがあります。
ループ並べ替え/交換
ループ分配
ループ融合
ループアンロール
データ・プリフェッチ
スカラー置換
アンロール/ジャム
ループ・ブロッキング/タイリング
部分和最適化
ロードペア最適化
プレディケート最適化
ランタイムデータ依存性のチェックによるループ・バージョニング (IA-64 アーキテクチャーのみ)
低いトリップカウントのチェックによるループ・バージョニング
ループ逆転
プロファイルに基づくループアンロール
ループピーリング
データ変換: malloc の結合と memset の結合
ループ・リローリング
memset および memcpy の認識
完全なループ入れ子作成用の文除去
デフォルトの最適化レベル、-O2 (Linux* OS および Mac OS* X) オプションまたは /O2 (Windows* OS) オプションでもいくつかの高レベルの最適化 (データ・プリフェッチやアンロールなど) が行われますが、-O3 (Linux および Mac OS X) または /O3 (Windows) を指定すると、メモリーアクセスを最適化するループ変換を実行する機会が得られます。これらのオプションで有効になる最適化は IA-32 アーキテクチャー、インテル® 64 アーキテクチャー、IA-64 アーキテクチャーで異なります。
ベクトル化オプション -ax および -x (Linux および Mac OS X)、/Qax および /Qx (Windows) と -O3 オプション (Linux および Mac OS X)、/O3 オプション (Windows) を組み合わせて指定すると、-O2 (Linux および Mac OS X)、/O2 (Windows) よりも詳細にデータの依存性を解析します。
プロセッサーで利用できるプリフェッチのサポートのため、コンパイラーのプリフェッチは無効にされます。
-O3 オプション (Linux および Mac OS X)、/O3 オプション (Windows) は、-O2 オプション (Linux および Mac OS X)、/O2 オプション (Windows) を有効にして、さらに強力な最適化 (ループ変換など) を追加します。O3 は、速度が最大になるように最適化を行いますが、パフォーマンスが向上しないプログラムもあります。
-ivdep-parallel (Linux) オプションまたは /Qivdep-parallel (Windows) オプションは、ivdep プラグマが指定されたループにループ伝播の依存がないことを示唆します。(この手法は、スパース・マトリクス・アプリケーションに役立ちます。)
次のステップに従って IA-64 アーキテクチャー向けアプリケーションをチューニングします。
-O3 (Linux)、/O3 (Windows) と -ipo (Linux)、/Qipo (Windows) を使用してプログラムをコンパイルします。可能な限り、プロファイルに基づく最適化 (PGO) を使用します。
高レベルな最適化レポートを生成します。
ループがソフトウェア・パイプライン化されていない理由を確認します。
前の手順の結果で示された変更を行います。
期待する最適化レベルに達するまで、これらの手順を繰り返します。
一般に、次の手法で複数のアーキテクチャー向けのアプリケーションをチューニングできます。
#pragma ivdep を使用して、依存性がないことを示します。コンパイルする際にループ運搬の依存がないことを示す -ivdep-parallel オプション (Linux および Mac OS X) または /Qivdep-parallel オプション (Windows) が必要な場合があります。
#pragma swp を使用して、ソフトウェアのパイプライン化を有効にします (不適当なコントロールや不明なループカウントに役立ちます)。
必要に応じて、#pragma loop count(n) を使用します。
-ansi-alias (Linux および Mac OS X) または /Qansi-alias (Windows) は便利なオプションです。
restrict キーワードを追加して、エイリアシングを回避します。-restrict (Linux) または /Qrestrict (Windows) を使用してコンパイルします。
-fargument-alias (Linux および Mac OS X) または /Qalias-args- (Windows) 引数がエイリアス化されないことを示します。
#pragma distribute point を使用して、大きなループを分割します (通常、これは自動的に行われます)。
C コードの場合、ループのインデックスに unsigned int を使用しないでください。HLO は、添字オーバーフローが原因で、最適化をスキップする場合があります。上限がポインター参照の場合、可能な限りローカル変数に割り当ててください。
プリフェッチが正しく設定されていることを確認します。#pragma prefetch を使用して、必要に応じて設定を上書きします。