次の表にリストしたコンパイラオプションによって、デフォルトのコンパイルで作成されるプログラムのパフォーマンスを上げるための方法のレパートリーは広がります。このリストには、コンパイラの中でもよりパフォーマンスに影響を与えるオプションだけを紹介しました。完全なリストについては、『Fortran ユーザーズガイド』を参照してください。
表 9–1 パフォーマンスに影響を与えるオプション
処理 |
オプション |
---|---|
さまざまな最適化オプションをいっしょに使用する |
-fast |
コンパイラの最適化レベルを n に設定する |
-On (-O = -O3) |
ターゲットハードウェアを指定する |
-xtarget=sys |
特定の命令セットアーキテクチャーを指定する |
-xarch=isa |
パフォーマンスプロファイルデータを使用して最適化する (-O5 で) |
-xprofile=use |
ループを n まで展開する |
-unroll=n |
浮動小数点の簡約化と最適化を許可する |
-fsimple=1|2 |
依存関係の解析を行い、ループを最適化する |
-depend |
内部手続きの最適化を実行する |
-xipo |
このようなオプションはコンパイル時間を増やすものもあります。なぜなら、プログラムをより深く解析するからです。オプションの中には、呼び出すルーチンと呼び出されるルーチンを同じファイルに集めておくと (それぞれを別々なファイルに入れておくよりも) うまく動作するものもあります。これによって、解析が大域的に行われるからです。
このオプション 1 つで、いくつものパフォーマンスオプションを選択したことになります。
このオプションは、リリースごと、またはコンパイラごとに変更されることのあるほかのオプションを選択する機能として定義されています。-fast により選択されるいくつかのオプションはすべてのプラットフォームで使用できない可能性があります。-fast の展開を表示するには、-dryrun フラグを使用してコンパイルしてください。
-fast により選択されるいくつかのオプションはすべてのプラットフォームで使用できない可能性があります。 しかし、オプションによっては、アプリケーションで使用できない場合があります。-fast を使用して、最大のパフォーマンスを得るためにアプリケーションをコンパイルしてください。しかし、さらに調整が必要な場合があります。-fast を指定してコンパイルしたプログラムが正しく動作しない場合、-fast を形成している個々のオプションを調査して、プログラムを正しく動作させるオプションだけを呼び出してください。
また、-fast でコンパイルされたプログラムは、使用するデータセットにより、高いパフォーマンスと正確な結果を実現できないことがあります。浮動小数点演算の特定プロパティーに依存しているプログラムは、-fast を使用してコンパイルしないでください。
-fast で選択されたオプションの一部は暗黙的にリンクするため、コンパイルとリンクを別々に行う場合は、リンク時も必ず -fast を使用してください。
-fast では次のオプションが選択されます。
-dalign
-depend
-fns
-fsimple=2
-ftrap=common
-fround=nearest (Solaris のみ)
-libmil
-xtarget=native
-O5
-xlibmopt (Solaris のみ)
-pad=local (SPARC のみ)
-xvector=lib (SPARC のみ)
-nofstore (x86 のみ)
-xregs=frameptr (x86 のみ)
-fast は、コンパイラの最適化能力のほとんどを簡単に引き出すための方法です。複合オプションは個別にも指定できます。また、それぞれに注意すべき副作用があります (『Fortran ユーザーズガイド』を参照)。-fast の実際の展開内容は、コンパイラのリリースが変わるたびに変更される可能性があることに注意してください。-dryrun を付けてコンパイルすると、すべてのコマンド行フラグの展開内容を見ることができます。
-fast のあとに別のオプションを追加して、さらに最適化を指定できます。たとえば、次のようにします。
f95 -fast -m64 ...
64 ビット対応のプラットフォーム向けにコンパイルします。
-fast には、-dalign、-fns、-fsimple=2 が含まれます。このため、-fast を指定してプログラムをコンパイルすると、結果として、非標準の浮動小数点演算、非標準のデータ配列、式評価の非標準の順序になる可能性があります。これらの選択オプションは、ほとんどのプログラムに適していない可能性があります。
-O オプションを明示的に、あるいは、-fast などのマクロオプションで暗黙的に指定しないかぎり、コンパイラは最適化を行いません。ほとんどすべての場合、コンパイル時に最適化レベルを指定すると、プログラムの実行パフォーマンスは上がります。一方、最適化レベルを上げるほど、コンパイル時間が増え、コードのサイズも大きくなる可能性があります。
ほとんどの場合、パフォーマンス、コードのサイズ、コンパイル時間をもっともバランスよくコンパイルするのはレベル -O3 です。 -O4 は、呼び出し側と同じソースファイルに入っているルーチンの呼び出しの自動インライン化を追加します。副プログラム呼び出しのインライン化の詳細については、『Fortran ユーザーズガイド』を参照してください。
レベル -O5 は、低いレベルには適用できない、さらに積極的な最適化テクニックを追加します。一般的に、-O3 より上のレベルは、プログラム中でもっとも計算が多い、つまりパフォーマンスが上がる見込みが大きい部分のルーチンだけに指定するものです。ちなみに、異なる最適化レベルでコンパイルしたプログラムをいっしょにリンクしても何の問題もありません。
C$ PRAGMA SUN OPT=n 指令を使用して、ソースファイルのルーチンごとに異なる最適化レベルを設定します。この指令はコンパイラのコマンド行の -On フラグに優先しますが、-xmaxopt=n フラグで最大最適化レベルを設定して使用しなければいけません。 詳細は、f95(1) のマニュアルページを参照してください。
-xprofile=use と組み合わせた場合、コンパイラはレベル -O3 以上の最適化をより効率的に適用します。このオプションを使用すると、オプティマイザは、-xprofile=collect でコンパイルしたプログラムが典型的な入力データを使用して生成した実行時実行プロファイルから指示を受けます。フィードバックプロファイルは、どこで最適化が最大の効果を発揮するかをコンパイラに示します。これは特に -O5 で重要になります。次に示す例は、より高い最適化レベルでプロファイルを収集する典型的な例です。
demo% f95 -o prg -fast -xprofile=collect prg.f ... demo% prg demo% f95 -o prgx -fast -O5 -xprofile=use:prg.profile prg.f ... demo% prgx |
前述の例の最初のコンパイルで、実行時に文カバレージ統計を生成する実行可能ファイルが生成されます。2 回目のコンパイルで、このパフォーマンスデータを使用して、プログラムを最適化しています。
-xprofile オプションに関する詳細は、『Fortran ユーザーズガイド』を参照してください。
-dalign を使用すると、コンパイラはダブルワードのロード命令またはストア命令を (可能であれば) 生成できます。 データの移動量が多いプログラムは、このオプションを付けてコンパイルすれば、その恩恵を十分に受けることができます。-dalign は、-fast によって選択されるオプションの 1 つです。ダブルワード命令の速度は、同等のシングルワード命令と比べると、ほとんど倍になります。
しかし、-dalign を使用するときは (したがって、-fast を使用するときも) 十分注意しなければいけません。なぜなら、COMMON ブロック中のデータの特定の境界合わせを予想してコーディングされたプログラムのうち、問題を起こすものがあるからです。-dalign を使用すると、コンパイラはパディングを追加して、倍精度と 4 倍精度のデータをすべて (REAL も COMPLEX も) ダブルワード境界にそろえようとします。その結果、次のようなことが起こります。
パディングを追加したために、COMMON ブロックが予想よりも大きくなることがあります。
COMMON を共有するプログラム単位のいずれか 1 つでも -dalign を付けてコンパイルした場合、すべての単位を -dalign を付けてコンパイルしなければいけません。
たとえば、複数のデータ型が混在する COMMON ブロック全体を 1 つの配列として別名付けを行うことによって、データを書き込むプログラムは -dalign を付けるとうまく動作しません。なぜなら、倍精度変数や 4 倍精度変数のパディングのために、プログラムが予想するよりもブロックが大きくなるからです。
最適化レベル -O3 以上に -depend を追加すると、DO ループとループの入れ子に関するコンパイラの最適化能力が拡張されます。このオプションを使用すると、オプティマイザは反復間のデータの依存関係を解析し、そのループ構造を変形できるかどうか決定します。データの依存関係のないループだけがその構造を変形できます。しかし、この解析を追加すると、コンパイル時間が増えます。
指示しないかぎり、コンパイラは浮動小数点計算を簡易化しようとしません (デフォルトは -fsimple=0)。-fsimple=2 を追加すると、オプティマイザはさらに簡易化を行うことができます。 しかし、簡易化を行うと、丸めの影響によって、結果がわずかに違うという問題が発生する可能性があります。-fsimple レベル 1 か 2 を使用する場合は、すべてのプログラム単位を同じようにコンパイルし、数値精度の整合性が失われないようにする必要があります。このオプションについての重要な情報は、『Fortran ユーザーズガイド』を参照してください。
長い繰り返しを持つ短いループを展開すると、いくつかのルーチンはその恩恵を受けることがあります。しかし、展開はプログラムのサイズを増やすことにもなり、ほかのループのパフォーマンスを下げることにもなります。 n=1 を使用すると (デフォルト)、オプティマイザは自動的にループを展開しません。n が 1 より大きいときは、オプティマイザは、深さが n までループを展開しようとします。
コンパイラのコードジェネレータはループの展開をさまざまな要因に応じて決定します。コンパイラは、オプションが n>1 で指定されている場合でもループを展開しないことがあります。
繰り返しが可変の DO ループを展開する場合、展開したループとオリジナルのループの両方がコンパイルされます。繰り返し数を実行時にテストして、展開したループを実行するのが適切かどうかを決定します。ループを展開すると、特に文が 1 つか 2 つしかないループの場合は、反復ごとに行われる計算量が増えるので、オプティマイザがレジスタをスケジュールし演算を単純化する機会が増えます。繰り返しの数、ループの複雑さ、展開の深さの選択のかね合いは簡単に決定できず、ある程度の経験が必要となるでしょう。
次に示す例は、-unroll=4 を指定して、簡単なループを深さが 4 まで展開する様子を示しています (このオプションを使用しても、ソースコードは変更されません)。
元のループ :
DO I=1,20000 X(I) = X(I) + Y(I)*A(I) END DO |
深さ 4 まで展開すると次のコーディングと同じようになります:
DO I=1, 19997,4 TEMP1 = X(I) + Y(I)*A(I) TEMP2 = X(I+1) + Y(I+1)*A(I+1) TEMP3 = X(I+2) + Y(I+2)*A(I+2) X(I+3) = X(I+3) + Y(I+3)*A(I+3) X(I) = TEMP1 X(I+1) = TEMP2 X(I+2) = TEMP3 END DO |
この例は、固定した繰り返しの簡単なループを示しています。可変の繰り返し数を持つループに対しては、構造の変更はもっと複雑になります。
コンパイラにターゲットのコンピュータハードウェアの正確な情報を伝えると、パフォーマンスが上がるプログラムもあります。プログラムのパフォーマンスを重視する場合は、ハードウェアを適切に指定することが極めて重要です。特に、プログラムをより新しい SPARC システム上で実行する場合には重要になります。しかし、ほとんどのプログラムと古い SPARC プロセッサの場合、パフォーマンスはそれほど上がらず、汎用指定だけで十分です。
『Fortran ユーザーズガイド』には、-xtarget= が認識するすべてのシステム名がリストされています。特定のシステム名に対して (たとえば、UltraSPARC-II なら ultra2)、-xtarget は、システムに適切に一致するように、-xarch、-xcache、-xchip の組み合わせに展開されます。オプティマイザはこれらの指定を使用して、従うべき方法と生成する命令を決定します。
-xtarget=native は特別な設定で、これを指定すると、オプティマイザはホストシステム (コンパイルを行うシステム) をターゲットとしてコードをコンパイルします。コンパイルと実行を同じシステム上で行うときは、このオプションが断然便利です。実行システムが不明であるときは、汎用のアーキテクチャー用にコンパイルするのが望ましい方法です。そのため、最適のパフォーマンスを得ることはできませんが、-xtarget=generic がデフォルトになります。
-xtarget フラグと -xchip フラグは、どちらも ultra3 と ultra3 バリアントを受け入れ、UltraSPARC-III プロセッサおよび UltraSPARC-IV プロセッサ用に最適化されたコードを生成します。最新の UltraSPARC プラットフォーム上でアプリケーションのコンパイルと実行を行うときは、-fast フラグを指定すると、そのプラットフォームに適したコンパイラ最適化オプションを自動的に選択できます。
クロスコンパイル (最新の UltraSPARC プラットフォーム以外のプラットフォームでコンパイルするが、UltraSPARC-III プロセッサで実行するためのバイナリを生成する) には、次のフラグを使用してください。
-fast -xtarget=ultra3
64 ビットコード生成用にコンパイルするには -m64 を使用してください。
最新の UltraSPARC プロセッサ用の -xtarget フラグのリストについては、『Fortran ユーザーズガイド』を参照してください。
-xprofile=collect: および -xprofile=use: を使用したパフォーマンスプロファイルは、特に UltraSPARC-III プラットフォームおよび UltraSPARC-IV プラットフォームで有効です。これは、コンパイラがもっとも頻繁に実行されるプログラムのセクションを特定し、局所的な最適化を実行して、最高のパフォーマンスを引き出すことができるからです。
Sun Studio Fortran コンパイラは、Solaris および Linux x86 プラットフォーム向けに 32 ビットおよび 64 ビット両方のコードのコンパイルをサポートしています。
-xtarget=pentium3 フラグは、次のように展開されます。-xarch=sse -xchip=pentium3 -xcache=16/32/4:256/32/4
Pentium 4 システムの場合、-xtarget=pentium4 は次のように展開されます。-xarch=sse2 -xchip=pentium4 -xcache=8/64/4:256/128/8
新しい -m64 オプションは、64 ビット x64 命令セット用のコンパイルを指定します。
新しい -xtarget オプションの -xtarget=opteron は、32 ビット AMD コンパイル用の -xarch、-xchip、-xcache の設定を指示します。
64 ビットコードを生成するには、コマンド行で -fast および -xtarget のあとに -m64 を指定する必要があります。-xtarget オプションは、自動的には 64 ビットコードを生成しません。-xtarget 値の定義もしているマクロのため、-fast オプションもまた 32 ビットコードになります。-xtarget=native64 および -xtarget=generic64 を除く、現在の -xtarget 値はすべて 32 ビットコードになるため、64 ビットコードを生成するには、次に示すように、コマンド行で -fast または -xtarget のあとに -xarch=m64 を指定する必要があります。
% f95 -fast -m64 または % f95 -xtarget=opteron -m64
-xarch=amd64 が指定されると、コンパイラが __amd64 および __x86_64 を事前定義するようになりました。
32 ビットおよび 64 ビット x86 プラットフォームでのコンパイルとパフォーマンスについての詳細は、『Fortran ユーザーズガイド』を参照してください。
この新しい f95 コンパイラフラグは、Forte Developer 6 update 2 リリースで導入されたもので、内部手続き解析パスを呼び出して、プログラム全体の最適化を実行します。-xcrossfile と異なり、-xipo はリンクステップですべてのオブジェクトファイルを最適化し、コンパイルコマンドのソースファイルだけに限定されません。
-xipo は大規模な複数ファイルにわたるアプリケーションをコンパイルおよびリンクする際に特に有効です。-xipo でコンパイルされたオブジェクトファイルは、その中に保存された解析情報を持っています。これにより、ソースおよびコンパイル済みプログラムファイルの内部手続き解析ができるようになります。
内部手続き解析を効果的に使用する方法について詳細は、『Fortran ユーザーズガイド』を参照してください。
ソースコード内の重要なポイントに ASSUME 指令を追加すると、検出しにくいプログラムの重要情報が明らかになり、コンパイラへの最適化のための支持として役立ちます。たとえば、DO ループのトリップカウントが常にある値より大きいことや、IF 分岐が行われない可能性が高いことを、コンパイラに知らせることができます。コンパイラはこの情報を利用して、これらの表明に基づくより最適化されたコードを生成できます。
そのうえ、プログラマは、表明が誤りであったことが実行時にわかった場合に警告メッセージが発行されるようにすることによって、ASSUME プラグマを使用してプログラムの実行を検証できます。
詳細は、『Fortran ユーザーズガイド』の第 2 章の ASSUME プラグマの説明と、第 3 章の -xassume_control コンパイラコマンド行オプションの説明を参照してください。