Oracle Solaris Studio 12.2: パフォーマンスアナライザ

ループの最適化

コンパイラは、数種類のループの最適化を行うことができます。一般的なものを次に示します。

ループの展開では、ループ本体内でループを数回反復し、それに応じてループインデックスを調整します。ループの本体が大きくなるほど、コンパイラはより効率的に命令をスケジュールできます。また、ループインデックスの増分や条件検査操作によるオーバーヘッドが減少します。残りのループは、ループのピーリングを使って処理されます。

ループのピーリングでは、ループから多数のループの反復を取り除き、これらをループの前か後ろに適宜移動します。

ループの入れ換えは、メモリーのストライドを最小限に抑えてキャッシュ行のヒット率を最大限に上げるために、入れ子のループの順序を変更します。

ループの融合は、隣り合ったループや近接したループを 1 つのループにまとめます。ループの融合からは、ループの展開と同じような利点がもたらされます。さらに、最適化済みの 2 つのループで共通のデータにアクセスする場合は、ループの融合によってループのキャッシュの局所性が改善されて、コンパイラは命令レベルの並列化機能をさらに活用することが可能になります。

ループの分散はループの融合の反対で、ループは複数のループに分割されます。この最適化は、ループ内の計算回数が過度に多くなり、パフォーマンス低下の原因となるレジスタのスピルが発生する場合に適しています。また、ループの分裂は、ループに条件文が含まれている場合にも有効です。場合によっては、条件文を含むものと含まないものの 2 つにループを分割できます。これによって、条件文を含まないループにおけるソフトウェアのパイプライン化の機会が増えます。

場合によって、入れ子のループでは、コンパイラはループの分裂を適用してループを分割し、次にループの融合を実行して異なる方法でループをまとめ直すことでパフォーマンスを改善します。この場合は、次のようなコンパイラのコメントが表示されます。


    Loop below fissioned into 2 loops
    Loop below fused with loop on line 116
    [116]    for (i=0;i<nvtxs;i++) {