ここでは、次のコーディング手法における一般的なガイドラインについて説明します。
MMX® テクノロジー、ストリーミング SIMD 拡張命令 (SSE)、ストリーミング SIMD 拡張命令 2 (SSE2)、およびストリーミング SIMD 拡張命令 3 (SSE3)、ストリーミング SIMD 拡張命令 4 (SSE4) をサポートする IA-32 およびインテル® 64 アーキテクチャー
IA-64 アーキテクチャー
このセクションでは、IA-32、インテル® 64 および IA-64 アーキテクチャーをベースとしたプロセッサーのパフォーマンスを向上させるアーキテクチャー機能と関連のあるコーディングの手法、ツール、規則、および推奨事項について説明します。
ガイドラインで特定のアーキテクチャーのみに適用される部分には、そのアーキテクチャーが明記されています。デフォルトは、IA-32 アーキテクチャーです。
コンパイラーで生成されたコードのパフォーマンスは、使用するコンパイラーによって異なります。インテル® Fortran コンパイラーは、インテル® アーキテクチャー用に最適化されたコードを生成します。コンパイラーのさまざまな最適化オプションを使用して、パフォーマンスを大幅に向上させることができます。ここで説明するガイドラインに従うことで、コンパイラーによる Fortran プログラムの最適化の効率性をさらに高めることができます。
Fortran アプリケーションで最大限のプロセッサー・パフォーマンスを得るには、次の手順を実行します。
メモリーアクセスのストールを回避すること
浮動小数点のパフォーマンスを高めること
SIMD 整数処理のパフォーマンスを高めること
ベクトル化の使用
以下に、インテル® アーキテクチャー・ベースのプロセッサーのパフォーマンスを最適化する機能に関連する、コーディング手法、規則、および推奨事項を示します。
インテル® コンパイラーは Fortran の配列を列優先順に編成します。例えば、2 次元配列の場合、メモリー内では A(22, 34) と A(23, 34) の各要素が連続して格納されます。最高レベルのパフォーマンスを得るには、内側のループが配列に連続アクセスできるように配列のコーディングを行ってください。
次の例について考えてみます。例 1 のコードは例 2 より優れたパフォーマンスが得られます。
例 1 |
---|
subroutine contiguous(a, b, N) integer :: i, j, N, a(N,N), b(N,N) do j = 1, N do i = 1, N b(i, j) = a(i, j) + 1 end do end do end subroutine contiguous |
このコードでは、内側のループ I で配列 A と配列 B に連続してアクセスするので、パフォーマンスが向上します。しかし、次の例では、内側のループ J で配列 A と配列 B へのアクセス方法が非連続的なので、パフォーマンスが低下します。
例 2 |
---|
subroutine non_contiguous(a, b, N) integer :: i, j, N, a(N,N), b(N,N) do i = 1, N do j = 1, N b(i, j) = a(i, j) + 1 end do end do end subroutine non_contiguous |
内側のループがメモリーに連続してアクセスできるように、コンパイラーによってコードを変換することも可能です。このコード変換を行うには、-O3 (Linux* OS) または /O3 (Windows* OS) (IA-32、インテル® 64、IA-64 アーキテクチャー)、-O3 (Linux) または /O3 (Windows) と -ax (Linux) または /Qax (Windows) (IA-32 アーキテクチャーのみ) などの高度な最適化オプションを使用する必要があります。
優れたパフォーマンスを得るにはアライメントが重要な役目を果たします。アライメントされたメモリーのアクセスは、アライメントされていないメモリーのアクセスより高速に処理されます。複数のファイルについてプロシージャー間の最適化 (-ipo (Linux) または /Qipo (Windows) オプション) を使用すると、コンパイラーはコードを解析して、アライメントされた境界から配列を開始できるように配列のパディングを行うべきかどうかを判断します。1 つの共通ブロックで複数の配列を指定すると、コンパイラーに余分な負担がかかることがあります。
例えば、次のような COMMON 文を考えてみます。
例 3 |
---|
COMMON /AREA1/ A(200), X, B(200) |
ここでは、コンパイラーが A(1) をアライメントするために、16 バイトにアライメントされたアドレスにパディングを追加した場合、B(1) という要素は 16 バイトにアライメントされたアドレスに格納されません。このような場合には、AREA1 を次のように分割します。
例 4 |
---|
COMMON /AREA1/ A(200) COMMON /AREA2/ X COMMON /AREA3/ B(200) |
上記のコードを使用すると、コンパイラーが A と B の両方に必要なパディングを判断するのに最大限の柔軟性をもたせることができます。