ここでは、次のコーディング手法における一般的なガイドラインについて説明します。
MMX® テクノロジおよび、ストリーミング SIMD 拡張命令 (SSE) とストリーミング SIMD 拡張命令 2 (SSE2) をサポートする IA-32 アーキテクチャ
Itanium® アーキテクチャ
このトピックでは、IA-32 および Itanium プロセッサ・ファミリのパフォーマンスを向上させるアーキテクチャ機能と関連のあるコーディング手法、ツール、規則、および推奨事項について説明します。IA-32 プロセッサ用の最適化に関する詳細は、『インテル® アーキテクチャ最適化リファレンス・マニュアル』を参照してください。Itanium プロセッサ・ファミリ用の最適化に関する詳細は、『インテル® Itanium® 2 プロセッサ・リファレンス・マニュアル: ソフトウェアの開発と最適化』 を参照してください。
注
ガイドラインで特定のアーキテクチャのみに適用される部分には、そのアーキテクチャが明記されています。それ以外の部分はすべて、IA-32 アーキテクチャと Itanium アーキテクチャの両方に該当します。
コンパイラで生成されたコードのパフォーマンスは、使用するコンパイラによって異なります。インテル® Fortran コンパイラは、インテル・アーキテクチャ用に高度に最適化されたコードを生成します。コンパイラのさまざまな最適化オプションを使用して、パフォーマンスを大幅に向上させることができます。ここで説明するガイドラインに従うことで、コンパイラによる Fortran プログラムの最適化の効率性をさらに高めることができます。
Fortran アプリケーションで最大限のプロセッサ・パフォーマンスを得るには、次の手順を実行します:
メモリアクセスのストールを回避すること
浮動小数点のパフォーマンスを高めること
SIMD 整数処理のパフォーマンスを高めること
ベクトル化を使用すること
ここで説明するコーディング手法、規則、および推奨事項により、インテル・アーキテクチャ・ベースのプロセッサ上のパフォーマンスを最適化することができます。
インテル・コンパイラは Fortran の配列を列優先順に編成します。例えば、2 次元配列の場合、メモリ内では A(22, 34) と A(23, 34) の各要素が連続して格納されます。最高のパフォーマンスを得るには、内側のループが配列に連続アクセスできるように配列のコーディングを行ってください。次の例について考えてみます。
例 1 のコードは例 2 より優れたパフォーマンスが得られます。
例 1
DO J = 1, N
DO I = 1, N
B(I,J) = A(I, J) + 1
END DO
END DO
このコードでは、内側のループ I で配列 A と配列 B に連続してアクセスするので、パフォーマンスが向上します。
例 2
DO I = 1, N
DO J = 1, N
B(I,J) = A(I, J) + 1
END DO
END DO
このコードでは、内側のループ J で配列 A と配列 B へのアクセス方法が非連続的なので、パフォーマンスが低下します。
内側のループがメモリに連続してアクセスできるように、コンパイラによってコードを変換することも可能です。このコード変換を行うには、-O3 (IA-32 と Itanium アーキテクチャ両方) および -O3 と -ax{K|W|N|B|P} (IA-32 のみ) などの高度な最適化を使用する必要があります。
優れたパフォーマンスを得るにはアライメントが重要な役目を果たします。アライメントされたメモリのアクセスは、アライメントされていないメモリのアクセスより高速に処理されます。複数のファイルに対するプロシージャ間の最適化 (-ipo オプション) を使用する場合、コンパイラがコードを分析し、アライメントされた境界から配列を開始できるよう配列のパディングを行うべきかどうかを判断します。1 つの共通ブロックで複数の配列を指定すると、コンパイラに余分な負担がかかることがあります。例えば、次のような COMMON 文の場合を検討してみます:
COMMON /AREA1/ A(200), X, B(200)
ここでは、コンパイラが A(1) をアライメントするために、16 バイトにアライメントされたアドレスにパディングを追加した場合、B(1) という要素は 16 バイトにアライメントされたアドレスに格納されません。このような場合には、AREA1 を次のように分割します。
COMMON /AREA1/ A(200)
COMMON /AREA2/ X
COMMON /AREA3/ B(200)
上記のコードを使用すると、コンパイラが A と B の両方に必要なパディングを判断するのに最大限の柔軟性をもたせることができます。
浮動小数点のパフォーマンスを向上するには、次の一般的な規則に従ってください:
計算中に表現可能な範囲を超過しないようにします。表現可能な範囲を超過すると、その処理によりパフォーマンスが低下する可能性があります。 DOUBLE または REAL*8 変数の高精度が必要な場合を除き、REAL 変数を単精度形式で使用してください。また、高精度の形式を持つ変数を使用すると、メモリサイズが増え、より大きな帯域幅が必要となります。
IA-32 のみ: 複数の変数間で丸めモードを何度も変更するのは避けてください。丸めモードを頻繁に変更すると、非 SSE 命令を使用して計算を行った場合にパフォーマンスが低下する可能性があります。したがって、非 SSE コードを生成する場合に FLOOR 命令および TRUNC 命令を一緒に使用することも避けてください。これは、CEIL と TRUNC の使用についても同じです。
この問題を回避するには、-x{K|W|N|B|P} オプションを使って SSE 命令により計算を実行する方法もあります。
次の方法で、両方のアーキテクチャについてデノーマル例外の影響を軽減します。
アンダーフローのある浮動小数点計算は結果がデノーマル値となり、そのためにパフォーマンスに悪影響を与えることがあります。
IA-32: ストリーミング SIMD 拡張命令 (SSE)、およびストリーミング SIMD 拡張命令 2 (SSE2) の SIMD 機能を利用します。-x{K|W|N|B|P} オプションは、SSE 命令および SSE2 命令で FTZ (ゼロ・フラッシュ) モードを有効にします。そのため、アンダーフロー結果が自動的にゼロに変換されるので、アプリケーションのパフォーマンスが改善します。さらに、-xP オプションを使用して DAZ (denormals are zeros) モードを有効にする方法もあります。これにより、デノーマルが入力時にゼロに変換され、パフォーマンスをさらに改善できます。IEEE-754 に完全準拠する必要がなく、実行速度を向上させたい場合には、これらのオプションが適しています。FTZ および DAZ の詳細に関する詳細は、「FTZ フラグと DAZ フラグの設定」および、『インテル® アーキテクチャ最適化リファレンス・マニュアル』の「浮動小数点例外」を参照してください。
Itanium アーキテクチャ: -O3 オプションで設定される -ftz オプションを使用して、FTZ (ゼロ・フラッシュ) モードを有効にします。
多くのアプリケーションでは、ベクトル化を実装することでパフォーマンスを大幅に向上することができます。ベクトル化はメインの計算ループにストリーミング SIMD SSE2 命令を使用します。インテル・コンパイラでベクトル化をオンにする (ベクトル化の自動処理) か、コンパイラ・ディレクティブを使用して実装することもできます。
詳細については、「ベクトル化の自動処理 (IA-32 のみ)」を参照してください。
インテル Fortran コンパイラおよびインテルのスレッド化ツールのセットには、マルチスレッド・アプリケーションの開発を支援する機能が用意されています。詳細については、「インテル® Fortran による共用メモリ並列プログラム」を参照してください。 マルチスレッド・アプリケーションは、マルチプロセッサのインテル SMP (対称型マルチプロセッシング) システムや、ハイパースレッディング・テクノロジを使用したインテル® プロセッサ上ではパフォーマンスが大幅に向上します。