プログラムのパフォーマンス解析

コンパイラの最適化とループへの影響

コンパイラヒントの説明からもわかるとおり、最適化コードとソースコードを対応させるのは難しい場合があります。コンパイラが出力する情報が、可能な限りソースコードに近い形式で表示されるほうが望ましいのは明らかです。残念ながら、コンパイラオプティマイザは、プログラムを内部表現によって「読み取る」ため、もとのソースコードに対応させようとしても、それほど効果はありません。

次に、混乱の原因となりやすい最適化の手法を紹介します。

インライン化

インライン化とは、 最適化レベル -O4 に限り、1 つのファイルに含まれる関数だけに 適用される最適化の 1 つです。すなわち、あるファイルに 17 個の Fortran 関数が含まれている場合、16 個の関数を残りの 1 つの関数に展開でき、-O4 レベルでコンパイルされていれば、その 16 個の関数のソースコードを 1 つの関数の本体にコピーします。これ以上の最適化を適用すると、ソースコードのどの行番号がどの最適化の対象となっているかが特定できなくなります。

コンパイラヒントの説明が不明確と思われる場合は、-O3 -parallel -Zlp を付けてコンパイルすると、コンパイラが関数をインライン化する前の段階で、ループに関するコンパイラからの指摘をより詳しく確認できます。

特に実態のないループ (すなわちコンパイラが、実在することを前提とするループで、実際のソースコード中には存在しないもの) は、インライン化の対象となっている可能性があります。

ループの変形 : 展開、詰め込み、分割、および入れ替え

コンパイラは、ループ本体を大きく書き換えるようなループの最適化を多数実行します。 具体的には、ループの最適化、 展開、詰め込み、 分割、 入れ替えなどの操作があります。

ループツールとループレポートは、可能な限り、意味のあるヒントを提供しようとしますが、最適化済みコードとソースコードを対応させる上での根本的な問題があるため、ヒントの内容が誤解を招くこともあります。

逐次ループの内部に入れ子にした並列ループ

逐次ループの中に並列ループが入れ子にされている場合、各ループを繰り返すごとに時計時間を使用するという条件があるため、ループツールおよびループレポートが報告する実行時間の情報が誤解を招く場合があります。内部ループが並列化されていると、ループの一部を並列的に繰り返す場合であっても、反復ごとの時計時間が確保されます。

これに対して、外部ループには、入れ子にした並列ループ全体の実行時間しか割り当てられません。すなわち、内部ループを並列的にインスタンス化した場合の最も長い時間に相当します。このように計測方法が二重になる結果、内部ループに比べ、外部ループの消費時間が短くなるという、「外部ループの変則性」という問題を生じることになります。