パフォーマンス拡張手法の適用

パフォーマンスを向上するには、最適化するアプリケーションの特性を識別することから開始します。次の表は、いくつかの一般的なアプリケーションの特性をリストし、パフォーマンスに影響を与える可能性のある問題と推奨する解決方法を示します。これらの手法は多くの場合に役立ちます。これらの手法を使用する鍵は経験です。

推奨する手法により達成できるパフォーマンス向上の可能性は、「影響」カテゴリーに示されています。アプリケーションやコードの設計に関する問題の場合は、示されたパフォーマンスの向上を達成できないこともあります。しかし、ここで示されている影響は一般的に正しいものです。「影響」カテゴリーは、推奨する手法を実行する前と比較して、どの程度パフォーマンスが向上するかを、次の 4 段階で示しています。

次の表は、アプリケーションの特性、および最も影響を与える手法の順に記述されています。

アプリケーションの特性

影響

推奨する手法

テクニカル・アプリケーション

ループの多いコードを含むテクニカル・アプリケーション

テクニカル・アプリケーションとは、ループの入れ子で合計 CPU サイクルの大部分を消費する関数のサブセットを含むプログラムです。

-O3 (Linux* および Mac OS*) または /O3 (Windows*) を使用してターゲットのループを入れ子し、ループ変換やプリフェッチを有効にします。

高レベルの最適化 (HLO) レポートを使用して、コンパイラーがどの HLO 最適化を選択したかを確認します。

「HLO レポート」を参照してください。

(上記と同じ)
Itanium(R) のみ

-O2-O3 (Linux)、/O2/O3 (Windows) の場合、SWP レポートを使用して、鍵となるループでソフトウェアのパイプライン化が発生したかどうか、発生しなかった場合はその理由を判断します。

次のような場合、ソフトウェアのパイプライン化を許可するようにコードを変更できます。

  • 存在しないことを想定していた再帰がレポートで報告された場合、(例えば、restrict キーワードを使用して) エイリアス問題を解決するか、ループで ivdep プラグマを使用します。

  • ループが大きすぎるか、レジスターを使い果たしてしまう場合、ループを手動で、または distribute プラグマを使用して、より小さなセグメントに分けます。

  • コンパイラーが Global Acyclic Scheduler はより良い結果を生成できると判断した場合でも、ユーザーがループをパイプライン化すべきであると判断した場合、ループで SWP プラグマを使用します。

(上記と同じ)
IA-32 およびインテル(R) EM64T のみ

使用できるオプションについては、「ベクトル化の概要」および「自動ベクトル化」セクションの残りのトピックを参照してください。

コードの変更に関する詳細は、「ベクトル化レポート」を参照してください。

(上記と同じ)

PGO プロファイルに基づいて他の最適化を行います。

「プロファイルに基づく最適化の概要」を参照してください。

多くの正規化されていない浮動小数点値の演算を含むアプリケーション

最高

適切な場所で FTZ を使用します。

高い精度が必要かどうかを判断します。必要ない場合、FTZ の使用が役立ちます。デノーマル値を処理するには、ハードウェアまたはオペレーティング・システムの介入が必要です。正規化されていない浮動小数点値は、正規化で表現するには小さすぎます。つまり、仮数は左揃えにできません。FTZ を使用すると、ハードウェアによってゼロと解釈されるデノーマル値が発生します。

いくつかの一般的な手法を使用して浮動小数点デノーマル値を削除します。

  • データ型をより大きなデータ型に変更する。

  • ターゲットのアーキテクチャーに応じて、FTZ またはベクトル化オプションを使用する。

IA-32 およびインテル EM64T

  • FTZ モードは SSE2 命令ではデフォルトで有効です。インテル EM64T 対応コンパイラーは、デフォルトで SSE2 命令を生成します。IA-32 用コンパイラーの場合、-xW-xN-xB または -xP (Linux)、/QxW/QxN/QxB または /QxP (Windows) を使用して、SSE2 命令を有効にします。 

  • 詳細は、「ベクトライザーのオプション」を参照してください。

Itanium:

  • 最も一般的で簡単な FTZ (Flush-to-Zero) 手法は、main() を含むソースファイルで -ftz オプション (Linux) または /Qftz オプション (Windows) を使用することです。

  • -O3 (Linux) または /O3 (Windows) を選択すると、自動的に -ftz (Linux) または /Qftz (Windows) が有効になります。

FTZ を使用した後、正規化されていない値をゼロとして解釈した場合でも、プログラムが正しい結果を出力していることを確認します。

スパース・マトリックス・アプリケーション

(下記の) メモリーポインター一義化に対して推奨する手法を参照してください。

prefetch プラグマまたは prefetch 組み込み関数を使用します。間接配列で異なるプリフェッチ方式を試します。

プリフェッチの使用については、「高レベルな最適化の概要」または「プリフェッチのサポート」を参照してください。

サーバー・アプリケーション

分岐中心のコードを含む適切なフラット・プロファイル・サーバー・アプリケーション

フラット・プロファイル・アプリケーションとは、単一のモジュールが CPU サイクルを極端に消費しないアプリケーションのことです。

PGO を使用して、コンパイラーに最も頻繁に使用されるパスと関数を知らせます。この結果、インテル(R) コンパイラーは最適な方法でコードをアレンジできます。

利用可能なアプリケーション上で PGO を使用します。

「プロファイルに基づく最適化の概要」を参照してください。

大規模なサーバー・アプリケーション
(上記と同様)

-O1 (Linux および Mac OS) または /O1 (Windows) を使用して、アプリケーションを最適化します。ストリームラインを利用可能な最も汎用的な方法でコード化します。

この手法は、生成されるコードの量を減らし、インライン展開を無効にし、スペキュレーションを無効にし、できるだけ多くの命令コードのキャッシュを有効にします。

データベース・エンジン

-O1 (Linux および Mac OS) または /O1 (Windows) および PGO を使用して、アプリケーション・コードを最適化します。

(上記と同じ)

アプリケーション全体に -ipo (Linux および Mac OS) または /Qipo (Windows) を使用します。

「プロシージャー間の最適化の概要」を参照してください。

その他のアプリケーション

複数の場所から呼び出される小さな関数を多く含むアプリケーション

-ip (Linux および Mac OS) または /Qip (Windows) を使用して、単一ソースモジュール内でプロシージャー間のインライン展開を有効にします。

ストリームラインは、関数を呼び出したコードブロック内のコードを複写することで単純な関数の実行をコード化します。これによりアプリケーションのサイズは増加します。

一般的に、大きく複雑な関数はインライン展開しないでください。

「プロシージャー間の最適化の概要」を参照してください。

(上記と同じ)

-ipo (Linux および Mac OS) または /Qipo (Windows) を使用して、複数のソースモジュール内と複数のソースモジュール間の両方でプロシージャー間のインライン展開を有効にします。-ip (Linux および Mac OS) または /Qip (Windows) を使用することでアプリケーションのサイズが増加することがあります。

このオプションを使用すると、発生する拡張プログラムフロー解析により、リンク時間が長くなります。

プロシージャー間の最適化 (IPO) は、プログラム全体の解析を実行してメモリーポインターの一義化を助けます。

上記にリストされたアプリケーション固有の推奨する手法とは別に、以下の表で示すように、パフォーマンスを向上する、アプリケーション固有、OS/ライブラリー固有、およびハードウェア固有の推奨事項があります。

アプリケーション固有の推奨事項

アプリケーション・エリア

影響

推奨する手法

キャッシュ・ブロッキング

-O3 (Linux および Mac OS) または /O3 (Windows) を使用して、自動キャッシュ・ブロッキングを有効にします。HLO レポートを使用して、コンパイラーがキャッシュ・ブロッキングを自動的に有効にしたかどうかを判断します。有効にならなかった場合、手動キャッシュ・ブロッキングを検討します。

「キャッシュ・ブロッキング」を参照してください。

より良いエイリアス解析のためのコンパイラー・プラグマ

ベクトルの依存性を無視します。ivdep およびその他のプラグマを使用して、アプリケーションの速度を向上させます。

「ベクトル化のサポート」を参照してください。

メモリーポインター一義化コンパイラー・キーワードおよびオプション

restrict キーワードと -restrict オプション (Linux) または /Qrestrict オプション (Windows) を使用して、メモリーポインターを一義化します。

ソースコードで restrict キーワードを使用した場合、コンパイル中に -restrict オプション (Linux) または /Qrestrict オプション (Windows) を使用する必要があります。

restrict キーワードとオプションを使用する代わりに、次のコンパイラー・オプションを使用します

  • -fno-fnalias (Linux)

  • -ansi-alias (Linux) または /Qansi-alias (Windows)

  • /Oa (Windows)

  • /Ow (Windows)

  • -alias-args (Linux) または /Qalias-args (Windows)

軽量なメモリー参照の一貫性を保証するコードを生成

一部のアプリケーションは、volatile 属性を使用してメモリー操作を保証します。ハードウェアで積極的なメモリー・オーダリングを行う必要はありません。

Itanium:

  • -mno-serialize-volatile を使用します。

数学関数

単精度データ型に float 組み込み関数 (例えば、sqrt() ではなく sqrtf()) を使用します。

ユーザーコードの代わりにマス・カーネル・ライブラリー (MKL) を呼び出します。

アセンブリー・コードで関数を呼び出す代わりに組み込み関数を使用

インテル・コンパイラーは組み込み関数をインクルードします。これらの組み込み関数を使用してコードを最適化します。コンパイラーの組み込み関数を使用することで、コードの移植性を高めつつ、アプリケーションのパフォーマンスを向上できます。

OS/ライブラリーの推奨事項

エリア

影響

説明

ライブラリー関数

Itanium ベース・システムのみ。 setjump 関数を使用している場合、setjmp の代わりに _setjmp を使用して、setjmp バッファーに保存される浮動小数点状態の量を減らすことを検討します。

シンボル・プリエンプション

Linux のシンボル・プリエンプション・モデルは、Windows よりもパフォーマンスに影響を与えます。Linux はフル・プリエンプションを使用しています。Windows はプリエンプションを使用していません。-fminshared -fvisibility=protected を使用します。

「シンボルの可視属性オプション」を参照してください。

メモリーの割り当て

サードパーティーのメモリー管理ライブラリーを使用すると、広範囲なメモリー割り当てが必要なアプリケーションのパフォーマンス向上に役立ちます。

ハードウェア/システムの推奨事項

コンポーネント

影響

説明

ディスク

ハードドライブへの格納手法をより高度なものにします。例えば、IDE の代わりに SCSI を使用します。

適切な RAID レベルを使用します。

システムのハードドライブの数を増やします。

メモリー

システムのメモリーを増やすと、パフォーマンスが向上します。例えば、4 つのメモリースロットのうち 2 つのスロットにしかメモリーをセットしていない場合、残りの 2 つのスロットにメモリーを増設することで、パフォーマンスが向上します。

プロセッサー

 

多くのアプリケーションでは、パフォーマンスはプロセッサーの速度、プロセッサーの数、プロセッサーのコアの種類、およびキャッシュサイズに直接影響されます

その他の最適化手法情報

高度で特殊な最適化手法についての詳細は、インテル(R) デベロッパー・サービス: デベロッパー・センター (http://www.intel.com/cd/ids/developer/asmo-na/eng/19284.htm) Web サイトを参照してください。

以下のデベロッパー・センターにリストされているトピックエリアのトピックおよび追加リソースへのリンクを参照してください。

Tools and Technologies:

Intel(R) Processors: