高レベルな最適化 (HLO) レポート

高レベルな最適化 (HLO) は、各最適化の有用性および適用可能性に基づいて特定の最適化を行います。HLO レポートは、関連するすべての領域に加えて、構造体分割およびループ運搬のスカラー置換についての情報を提供します。また、次の理由から行われなかったループ交換についての情報も提供します。

例えば、レポートは、コンパイラーが最適化の候補となるはずのループの入れ子になぜループ交換を適用しなかったかを知る手がかりを提供します。レポートされた問題 (ボトルネック) がソースコードを変更することで排除できる場合は、レポートは可能性のあるループ交換を示唆します。

オペレーティング・システムに応じて、次のオプションを指定し、HLO を有効にしてレポートを作成します。

HLO の詳細については、「高レベルな最適化の概要」を参照してください。

次のコマンド例は、HLO レポートの作成に必要な一般的なコマンドです。

プラットフォーム

コマンド例

Linux および Mac OS X

icpc -c -xP -O3 -opt-report 3 -opt-report-phasehlo sample.cpp

Windows

icl /c /QxW /O3 /Qopt-report:3 /Qopt-report-phase:hlo sample.cpp

-opt-report-file (Linux および Mac OS X) または /Qopt-report-file (Windows) を使用して、レポート結果をキャプチャーする出力ファイルを指定します。結果をキャプチャーするファイルを指定することで、結果の解析に費やす時間を短縮でき、後に行うテスティングの基本ラインをつかむことができます。

レポート結果

レポートは、特定の形式で情報を提供します。Windows のレポート形式は、Linux や Mac OS X のレポート形式とは異なります。レポート出力には共通の要素が含まれますが、レポートが提供するアドバイスを理解する一番良い方法は、コード例とそのレポート出力を実際に確認することです。

例 1: この例では、関数呼び出しがループの内部にある場合を示しています。

例 1

void bar (int *A, int **B);

int foo (int *A, int **B, int N)

{

   int i, j;

   for (j=0; j<N; j++) {

      for (i=0; i<N; i++) {

         B[i][j] += A[j];

         bar(A,B);

      }

   }

   return 1;

}

オペレーティング・システムを問わず、レポートでは、特定の関数の最適化結果が 1 行で示され、その後にレポートされた処理が示されます。行の形式と説明は下にリストされます。

次の表は、一般的なレポート要素と結果の解釈に役立つ説明をまとめたものです。

レポート要素

説明

レポートされる関数についての情報です。次の形式で示されます。

<source name>;<start line>;<end line>;<optimization>; <function name>;<element type>

例えば、レポートには次の情報が含まれます。

Linux および Mac OS X:

<sample1.c;-1:-1;hlo;foo;0>

Windows:

<sample1.c;-1:-1;hlo;_foo;0>

ここでは、次の情報が含まれます。

  • <source name>: 検証されるソースファイルの名前です。

  • <start line>: 検証される関数の開始行番号です。値が 1 の場合、関数全体がレポートされます。

  • <end line>: 検証される関数の終了行番号を示します。

  • <optimization>: 最適化フェーズを示します。このレポートの場合は、hlo 最適化フェーズです。

  • <function name>: 検証される関数名です。

  • <element type>: レポート要素の型を示します。0 は要素がコメントであることを示します。

いくつかのレポート要素はグループ化されます。

QLOOPS 2/2      ENODE LOOPS 2 unknown 0 multi_exit_do 0 do 2 linear_do 2

LINEAR HLO EXPRESSIONS:  17 / 18

Windows のみ: レポートのこのセクションには、次の情報がリストされます。

  • QLOOPS: 発見されたループの中から適格なループの数を示します。

  • ENODE LOOPS: HLO によって生成された望ましいループ形式 (標準的な) の数を示します。これは、HLO によって生成されたループの数です。

  • unknown: カウントできなかったループの数を示します。

  • multi_exit_do: 複数の出口を含むカウント可能なループを示します。

  • do: カウント可能なトリップカウントを持つループの合計数を示します。

  • linear_do: 線形形式で表現できる限界を持つループ数を示します。

  • LINEAR HLO EXPRESSIONS: 線形形式で表現できる式 (2 番目の数字) のすべての中間形式 (ENODE) にある式の数 (最初の数字) を示します。

上記のコード例では次のような結果が出力されます。

プラットフォーム

例 1 のレポート出力

Linux および Mac OS X

<sample1.c;-1:-1;hlo;foo;0>

High Level Optimizer Report (foo)

 

Block, Unroll, Jam Report:

(loop line numbers, unroll factors and type of transformation)

 

<sample1.c;7:7;hlo_unroll;foo;0>

Loop at line 7 unrolled with remainder by 2  

Windows

<sample1.c;-1:-1;hlo;_foo;0>

High Level Optimizer Report (_foo)

QLOOPS 2/2      ENODE LOOPS 2 unknown 0 multi_exit_do 0 do 2 linear_do 2

LINEAR HLO EXPRESSIONS:  17 / 18

------------------------------------------------------------------------------

 

<sample1.c;6:6;hlo_linear_trans;_foo;0>

Loop Interchange not done due to: User Function Inside Loop Nest

Advice: Loop Interchange, if possible, might help Loopnest at lines: 6 7

      : Suggested Permutation: (1 2 ) --> ( 2 1 )

例 2: ループの入れ子によりループ交換が妨げられた例を示しています。

例 2

int foo (int *A, int **B, int N)

{

   int i, j;

   for (j=0; j<N; j++) {

      A[j] = i + B[i][1];

      for (i=0; i<N; i++) {

         B[i][j] += A[j];

      }

   }

   return 1;

}

上記のコード例では次のような結果が出力されます。

プラットフォーム

例 2 のレポート出力

Linux および Mac OS X

<sample2.c;-1:-1;hlo;foo;0>

High Level Optimizer Report (foo)

 

<sample2.c;7:7;hlo_scalar_replacement;in foo;0>

#of Array Refs Scalar Replaced in foo at line 7=2

#of Array Refs Scalar Replaced in foo at line 7=1

 

Block, Unroll, Jam Report:

(loop line numbers, unroll factors and type of transformation)

 

<sample2.c;7:7;hlo_unroll;foo;0>

Loop at line 7 unrolled with remainder by 2  

Windows

<sample2.c;-1:-1;hlo;_foo;0>

High Level Optimizer Report (_foo)

QLOOPS 2/2      ENODE LOOPS 2 unknown 0 multi_exit_do 0 do 2 linear_do 2

LINEAR HLO EXPRESSIONS:  22 / 27

------------------------------------------------------------------------------

 

<sample2.c;7:7;hlo_scalar_replacement;in _foo;0>

#of Array Refs Scalar Replaced in _foo at line 7=1

 

<sample2.c;5:5;hlo_linear_trans;_foo;0>

Loop Interchange not done due to: Imperfect Loop Nest (Either at Source or due
to other Compiler Transformations)

Advice: Loop Interchange, if possible, might help Loopnest at lines: 5 7

      : Suggested Permutation: (1 2 ) --> ( 2 1 )

例 3: この例では、データの依存関係によりループ交換が禁止されている状態を示しています。

例 3

int foo (int **A, int **B, int **C, int N)

{

   int i, j;

   for (j=0; j<N; j++) {

      for (i=0; i<N; i++) {

         A[i][j] = C[i][j] * 2;

         B[i][j] += A[i][j] * C[i][j];

      }

   }

   return 1;

}

上記のコード例では次のような結果が出力されます。

プラットフォーム

例 3 のレポート出力

Linux および Mac OS X

<sample3.c;-1:-1;hlo;foo;0>

High Level Optimizer Report (foo)

 

Block, Unroll, Jam Report:

(loop line numbers, unroll factors and type of transformation)

 

<sample3.c;6:6;hlo_unroll;foo;0>

Loop at line 6 unrolled with remainder by 2  

Windows

<sample3.c;-1:-1;hlo;_foo;0>

High Level Optimizer Report (_foo)

QLOOPS 2/2      ENODE LOOPS 2 unknown 0 multi_exit_do 0 do 2 linear_do 2

LINEAR HLO EXPRESSIONS:  36 / 36

------------------------------------------------------------------------------

 

<sample3.c;5:5;hlo_linear_trans;_foo;0>

Loop Interchange not done due to: Data Dependencies

  Dependencies found between following statements:

    [From_Line# -> (Dependency Type) To_Line#]

    [7 ->(Anti) 8] [7 ->(Flow) 8] [7 ->(Output) 8]

    [7 ->(Flow) 7] [7 ->(Anti) 7] [7 ->(Output) 7]

Advice: Loop Interchange, if possible, might help Loopnest at lines: 5 6

      : Suggested Permutation: (1 2 ) --> ( 2 1 )

例 4: この例は、ループの順序は適切だと判断されたけれども、ループ交換による効果がわずかしか見込めない場合を示しています。このコードをコンパイルするには、レポート生成時に -restrict (Linux および Mac OS X) または /Qrestrict (Windows) オプションをほかのオプションに追加します。

例 4

int foo (int ** restrict A, int ** restrict B, int N)

{

   int i, j, value;

   

   for (j=0; j<N; j++) {

      for (i=0; i<N; i++) {

         A[j][i] += B[i][j];       

      }

   }

   value = A[1][1];

   return value;

}

上記のコード例では次のような結果が出力されます。

プラットフォーム

例 4 のレポート出力

Linux および Mac OS X

<sample4.c;-1:-1;hlo;foo;0>

High Level Optimizer Report (foo)

 

Block, Unroll, Jam Report:

(loop line numbers, unroll factors and type of transformation)

 

<sample4.c;6:6;hlo_unroll;foo;0>

Loop at line 6 unrolled with remainder by 2

Windows

<sample4.c;-1:-1;hlo;_foo;0>

High Level Optimizer Report (_foo)

QLOOPS 2/2      ENODE LOOPS 2 unknown 0 multi_exit_do 0 do 2 linear_do 2

LINEAR HLO EXPRESSIONS:  18 / 18

例 5: この例では、ループの入れ子が不完全でループの順序は良いが、ループ交換による効果がわずかしかない場合を示しています。このコードをコンパイルするには、レポート生成時に -restrict (Linux および Mac OS X) または /Qrestrict (Windows) オプションをほかのオプションに追加します。

int foo (int ** restrict A, int ** restrict B, int ** restrict C, int N)

{

   int i, j, sum;

   

   for (j=0; j<N; j++) {

      sum += A[1][1];

      for (i=0; i<N; i++) {

         sum = B[j][i] + C[i][j];

      }

   }

   return sum;

}

上記のコード例では次のような結果が出力されます。

プラットフォーム

例 5 のレポート出力

Linux および Mac OS X

<sample5.c;-1:-1;hlo;foo;0>

High Level Optimizer Report (foo)

Windows

<sample5.c;-1:-1;hlo;_foo;0>

High Level Optimizer Report (_foo)

QLOOPS 2/2      ENODE LOOPS 2 unknown 0 multi_exit_do 0 do 2 linear_do 2

LINEAR HLO EXPRESSIONS:  16 / 19

------------------------------------------------------------------------------

 

<sample5.c;5:5;hlo_linear_trans;_foo;0>

Loop Interchange not done due to: Imperfect Loop Nest (Either at Source or due t

o other Compiler Transformations)

Advice: Loop Interchange, if possible, might help Loopnest at lines: 5 7

      : Suggested Permutation: (1 2 ) --> ( 2 1 )

例 6: この例は、完全なループの入れ子と不完全なループの入れ子があり、正しくネストされたループにはデータの依存関係が含まれる場合を示しています。

int foo (int ***A, int ***B, int **C, int N)

{

   int q, i, j, k;

   q = 0;

   while ( A[q][0][0] != 0) {

   for (j=0; j<N; j++) {

      A[j][0][0] = j + B[j][0][0];

      for (i=0; i<N; i++) {

         for (k=0; k<N; k++) {

            B[k][i][j] += A[j][0][0] + C[i][j];

         }

      }

   }

   A[q][0][0] = B[0][q][0] + 5;

   }

   return 1;

}

上記のコード例では次のような結果が出力されます。

プラットフォーム

レポート出力例

Linux および Mac OS X

<sample6.c;-1:-1;hlo;foo;0>

High Level Optimizer Report (foo)

 

Block, Unroll, Jam Report:

(loop line numbers, unroll factors and type of transformation)

 

<sample6.c;9:9;hlo_unroll;foo;0>

Loop at line 9 unrolled with remainder by 2  

[root@infodev-test hlo_samples_cpp]#

Windows

<sample6.c;-1:-1;hlo;_foo;0>

High Level Optimizer Report (_foo)

QLOOPS 2/4      ENODE LOOPS 2 unknown 0 multi_exit_do 0 do 2 linear_do 2

LINEAR HLO EXPRESSIONS:  34 / 34

------------------------------------------------------------------------------

 

<sample6.c;8:8;hlo_linear_trans;_foo;0>

Loop Interchange not done due to: Data Dependencies

  Dependencies found between following statements:

    [From_Line# -> (Dependency Type) To_Line#]

    [10 ->(Flow) 10] [10 ->(Anti) 10] [10 ->(Output) 10]

Advice: Loop Interchange, if possible, might help Loopnest at lines: 8 9

      : Suggested Permutation: (1 2 ) --> ( 2 1 )

レポート結果に基づくコードの変更

HLO レポートにより、コンパイラーが行ったループ変換について知ることができ、またいくつかのアドバイスを得られますが、ループの変換が省略されたことにより、コンパイラーが試みた変換があることも示唆している可能性があります。次のリストは、適用できる可能性のあるいくつかの変換を示しています。(手動キャッシュブロックのような手動の最適化テクニックは避けるか、または最後の手段としてください。)