JavaScript is required to for searching.
ナビゲーションリンクをスキップ
印刷ビューの終了
Oracle Solaris Studio 12.3: パフォーマンスアナライザ     Oracle Solaris Studio 12.3 Information Library (日本語)
search filter icon
search icon

ドキュメントの情報

はじめに

1.  パフォーマンスアナライザの概要

2.  パフォーマンスデータ

3.  パフォーマンスデータの収集

4.  パフォーマンスアナライザツール

5.   er_print コマンド行パフォーマンス解析ツール

6.  パフォーマンスアナライザとそのデータについて

7.  注釈付きソースと逆アセンブリデータについて

ツールがソースコードを見つけるしくみ

注釈付きソースコード

パフォーマンスアナライザの「ソース」タブのレイアウト

元のソース行の識別

「ソース」タブのインデックス行

コンパイラのコメント

共通部分式の除去

ループの最適化

関数のインライン化

並列化

注釈付きソースの特別な行

ソース行メトリック

ソース行メトリックの解釈

メトリックの形式

注釈付き逆アセンブリコード

注釈付き逆アセンブリの解釈

命令発行時のグループ化

命令発行遅延

ハードウェアカウンタオーバーフローの関連付け

「ソース」タブ、「逆アセンブリ」タブ、「PC」タブの特別な行

アウトライン関数

コンパイラ生成の本体関数

動的にコンパイルされる関数

Java ネイティブ関数

クローン生成関数

静的関数

包括的メトリック

分岐先

ストア命令とロード命令の注釈

実験なしのソース/逆アセンブリの表示

-func

-{source,src} item tag

-{disasm,dis} item tag

-{cc,scc,dcc} com-spec

-outfile filename

-V

8.  実験の操作

9.  カーネルプロファイリング

索引

注釈付きソースコード

実験の注釈付きソースコードは、パフォーマンスアナライザで「アナライザ」ウィンドウの左の区画にある「ソース」タブを選択することで表示できます。または、実験を実行しなくても、er_src ユーティリティーを使用して注釈付きソースコードを表示できます。ここでは、パフォーマンスアナライザでソースコードを表示する方法について説明します。er_src ユーティリティーを使用した注釈付きソースコードの表示の詳細は、「実験なしのソース/逆アセンブリの表示」を参照してください。

アナライザの注釈付きソースには、次の情報が含まれています。

パフォーマンスアナライザの「ソース」タブのレイアウト

「ソース」タブは、いくつかの列に分かれています。ウィンドウの左側には個々のメトリックを表示する固定幅の列が表示されます。右側の残りの列には、注釈付きソースが表示されます。

元のソース行の識別

注釈付きソースで黒字で表示されるすべての行は、元のソースファイルから取得されたものです。注釈付きソース列の各行の先頭の番号は、元のソースファイルの行番号に対応します。別の色で文字が表示されている行は、インデックス行かコンパイラのコメント行です。

「ソース」タブのインデックス行

ソースファイルとは、オブジェクトファイルを生成するためにコンパイルされるか、またはバイトコードに解釈されるファイルのことです。オブジェクトファイルには通常、ソースコード内の関数、サブルーチン、またはメソッドに対応する実行可能コードの領域が 1 つ以上含まれています。アナライザはオブジェクトファイルを解析して、それぞれの実行可能領域を関数として識別します。そして、オブジェクトコード内で見つけた関数を、オブジェクトコードに関連付けられたソースファイル内の関数、ルーチン、サブルーチン、またはメソッドにマップしようとします。アナライザは解析が成功すると、注釈付きソースファイル内の、オブジェクトコードで検出された関数の最初の命令に対応する場所に、インデックス行を追加します。

注釈付きソースは、「関数」タブのリストにインライン関数が表示されていない場合でも、インライン関数を含むすべての関数のインデックス行を表示します。「ソース」タブには、インデックス行が赤いイタリック体で、テキストが山括弧内に示されます。もっとも単純な種類のインデックス行は、関数のデフォルトコンテキストに対応しています。関数のデフォルトソースコンテキストは、その関数の最初の命令が帰するソースファイルとして定義されます。次の例は、C 関数 icputime のインデックス行を示しています。

                    578. int
                    579. icputime(int k)
0.       0.         580. {
                         <Function: icputime>

この例で分かるように、インデックス行は最初の命令に続く行に表示されます。C ソースの場合は、最初の命令は、関数本体の先頭が開く括弧に対応します。Fortran ソースの場合は、各サブルーチンのインデックス行が、subroutine キーワードを含む行に続きます。また、次の例に示すように、main 関数のインデックス行が、アプリケーションの起動時に実行される最初の Fortran ソース命令に続きます。

                                   1. ! Copyright (c) 2006, 2010, Oracle and/or its affiliates. All Rights Reserved.
                                   2. ! @(#)omptest.f 1.11 10/03/24 SMI
                                   3. ! Synthetic f90 program, used for testing openmp directives and the
                                   4. !       analyzer
                                   5. 
0.       0.       0.       0.      6.        program omptest
                                      <Function: MAIN>  
                                   7.
                                   8. !$PRAGMA C (gethrtime, gethrvtime)

場合によっては、アナライザは、オブジェクトコード内に見つけた関数を、そのオブジェクトコードに関連付けられたソースファイル内のプログラミング命令を使ってマップできないことがあります。たとえば、ヘッダーファイルのように、コードが #include されている場合や、ほかのファイルからインライン化されている場合があります。

また、特別なインデックス行やコンパイラのコメントではない特殊な行は、赤で示されます。たとえば、コンパイラの最適化の結果、ソースファイルに記述されているコードに対応しないオブジェクトコード内の関数について、特別なインデックス行が作成される場合があります。詳細は、「「ソース」タブ、「逆アセンブリ」タブ、「PC」タブの特別な行」を参照してください。

コンパイラのコメント

コンパイラのコメントは、コンパイラによって最適化されたコードがどのように生成されたかを示します。インデックス行や元のソース行と区別できるように、コンパイラのコメント行は青く表示されます。コンパイラのさまざまな段階で、実行可能ファイルにコメントが挿入されることがあります。各コメントは、ソースの特定の行に関連付けられます。注釈付きソースの書き込み時には、ソース行に対してコンパイラが生成するコメントが、ソース行の直前に挿入されます。

コンパイラのコメントは、最適化するためにソースコードに対して行われた変換の大部分に関する情報を提供します。こうした変換には、ループの最適化、並列化、インライン化、パイプライン化などがあります。次に、コンパイラのコメントの例を示します。

0.       0.       0.       0.        28.       SUBROUTINE dgemv_g2 (transa, m, n, alpha, b, ldb,   &
                                     29.      &                   c, incc, beta, a, inca)
                                     30.       CHARACTER (KIND=1) :: transa
                                     31.       INTEGER   (KIND=4) :: m, n, incc, inca, ldb
                                     32.       REAL      (KIND=8) :: alpha, beta
                                     33.       REAL      (KIND=8) :: a(1:m), b(1:ldb,1:n), c(1:n)
                                     34.       INTEGER            :: i, j
                                     35.       REAL      (KIND=8) :: tmr, wtime, tmrend
                                     36.       COMMON/timer/ tmr
                                     37. 
                             Function wtime_ not inlined because the compiler has not seen 
                             the body of the routine
0.       0.       0.       0.        38.       tmrend = tmr + wtime()


                             Function wtime_ not inlined because the compiler has not seen 
                             the body of the routine
                             Discovered loop below has tag L16
0.       0.       0.       0.        39.       DO WHILE(wtime() < tmrend)
                              
                             Array statement below generated loop L4
0.       0.       0.       0.        40.       a(1:m) = 0.0
                                     41. 
                                    
                             Source loop below has tag L6
0.       0.       0.       0.        42.       DO j = 1, n       ! <=-----\ swapped loop indices
       
                             Source loop below has tag L5
                             L5 cloned for unrolling-epilog.  Clone is L19
                             All 8 copies of L19 are fused together as part of unroll and jam
                             L19 scheduled with steady-state cycle count = 9
                             L19 unrolled 4 times
                             L19 has 9 loads, 1 stores, 8 prefetches, 8 FPadds, 
                             8 FPmuls, and 0 FPdivs per iteration
                             L19 has 0 int-loads, 0 int-stores, 11 alu-ops, 0 muls, 
                             0 int-divs and 0 shifts per iteration
                             L5 scheduled with steady-state cycle count = 2
                             L5 unrolled 4 times
                             L5 has 2 loads, 1 stores, 1 prefetches, 1 FPadds, 1 FPmuls,
                             and 0 FPdivs per iteration
                             L5 has 0 int-loads, 0 int-stores, 4 alu-ops, 0 muls, 
                             0 int-divs and 0 shifts per iteration
0.210    0.210    0.210    0.        43.          DO i = 1, m    
4.003    4.003    4.003    0.050     44.             a(i) = a(i) + b(i,j) * c(j)
0.240    0.240    0.240    0.        45.          END DO  
0.       0.       0.       0.        46.       END DO  
                                     47.       END DO
                                     48. 
0.       0.       0.       0.        49.       RETURN
0.       0.       0.       0.        50.       END

「ソース」タブに表示されるコンパイラコメントの種類は、「データ表示方法の設定」ダイアログボックスの「ソース/逆アセンブリ」タブを使って設定できます。詳細は、「データ表示オプションの設定」を参照してください。

共通部分式の除去

非常に一般的な最適化の例として、1 つの式が複数の場所に存在するときに、この式のコードを 1 つの場所にまとめることによってパフォーマンスを向上させることができます。たとえば、コードブロックの ifelse の分岐の両方で同じ演算が記述されている場合、コンパイラはその演算を if 文の直前に移動することができます。実際にそのようにした場合、コンパイラは以前出現した一方の式に基づいて、命令に行番号を割り当てます。割り当てられた行番号が if 構造の分岐の 1 つに対応していて、実際にはもう一方の分岐が常に実行される場合、注釈付きソースでは、実行されない分岐内の行のメトリックが表示されます。

ループの最適化

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

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

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

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

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

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

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

    Loop below fissioned into 2 loops
    Loop below fused with loop on line 116
    [116]    for (i=0;i<nvtxs;i++) {
関数のインライン化

インライン関数を使用して、コンパイラは、実際の関数呼び出しを行う代わりに、関数が呼び出されている場所に関数の命令を直接挿入します。つまり、C/C++ マクロと同様に、それぞれの呼び出し場所でインライン関数の命令の複製が作成されます。コンパイラは、高レベルの最適化 (4 および 5) で明示的または自動的なインライン化を実行します。インライン化によって関数呼び出しの負荷が減り、レジスタの使用や命令のスケジュールを最適化するための命令がさらに提供されますが、その代わりに、コードのメモリー使用量が多くなります。次に、コンパイラコメントのインライン化の例を示します。

                Function initgraph inlined from source file ptralias.c 
                    into the code for the following line
0.       0.         44.       initgraph(rows);

注 - コンパイラのコメントは、アナライザの「ソース」タブ内で 2 行にまたがって折り返されることはありません。


並列化

Sun、Cray、または OpenMP の並列化指令が含まれているコードの場合、複数プロセッサ上での並列実行用にコンパイルできます。コンパイラのコメントは、並列化が実行されている場所と実行されていない場所、およびその理由を示します。次に、並列化コンピュータのコメントの例を示します。

0.       6.324       9. c$omp  parallel do shared(a,b,c,n) private(i,j,k)
                   Loop below parallelized by explicit user directive
                   Loop below interchanged with loop on line 12
0.010    0.010     [10]            do i = 2, n-1

                   Loop below not parallelized because it was nested in a parallel loop
                   Loop below interchanged with loop on line 12
0.170    0.170      11.               do j = 2, i

並列実行とコンパイラ生成の本体関数の詳細は、「OpenMP実行の概要 」を参照してください。

注釈付きソースの特別な行

「ソース」タブには、特殊な場合のためのほかの注釈を表示できます。これらの注釈は、コンパイラのコメントの形で、またはインデックス行と同じ色で特別な行に表示できます。詳細は、「「ソース」タブ、「逆アセンブリ」タブ、「PC」タブの特別な行」を参照してください。

ソース行メトリック

実行可能コードの各行のソースコードメトリックは、固定幅の列に表示されます。メトリックは、関数リストのものと同じです。実験のデフォルト値は、.er.rc ファイルを使って変更できます。詳細は、「デフォルト値を設定するコマンド」を参照してください。また、表示されるメトリックとしきい値の強調表示も、「データ表示方法の設定」ダイアログボックスを使ってアナライザで変更できます。詳細は、「データ表示オプションの設定」を参照してください。

注釈付きソースコードは、ソース行レベルでのアプリケーションのメトリックスを示します。注釈付きソースは、アプリケーションの呼び出しスタックに記録された PC (プログラムカウント) を読み取り、各 PC をソース行にマッピングすることによって作成されます。注釈付きソースファイルを作成するために、アナライザは、最初に特定のオブジェクトモジュール (.o ファイル) またはロードオブジェクト内に生成されたすべての関数を特定し、各関数のすべての PC のデータをスキャンします。注釈付きソースを作成するには、アナライザが、すべてのオブジェクトモジュールまたはロードオブジェクトを検出して読み取り、PC からソース行へのマッピングを特定できる必要があります。また、表示するソースファイルを読み取って、注釈付きのコピーを作成できる必要もあります。実験のソースコードを検索するために使用されるプロセスについては、「ツールがソースコードを見つけるしくみ」を参照してください。

コンパイル処理では、要求される最適化レベルに応じて多くの段階があり、変換によって命令とソース行のマッピングに混乱が生じることがあります。最適化によっては、ソース行の情報が完全に失われたり、混乱が生じたりすることがあります。コンパイラは、さまざまな発見手法によって命令のソース行を追跡しますが、こうした手法は絶対ではありません。

ソース行メトリックの解釈

命令のメトリックについては、実行対象の命令を待っている間に発生したメトリックとして解釈する必要があります。イベントが記録されるときに実行中である命令がリーフ PC と同じソース行に存在している場合、メトリックはこのソース行を実行した結果であると解釈できます。ただし、実行中の命令とリーフ PC が存在しているソース行がそれぞれ異なる場合、リーフ PC が存在しているソース行のメトリックの少なくとも一部は、実行中命令のソース行が実行待ちしていた間に集計されたメトリックであると解釈する必要があります。この一例としては、1 つのソース行で計算された値が次のソース行で使用される場合が挙げられます。

メトリックスの解釈方法がもっとも問題となるのは、キャッシュミスやリソース待ち行列ストールなど、実行が大幅に遅延している場合や、命令が直前の命令の結果を待っている場合です。このような場合、ソース行のメトリックスが異常に高く見えることがあります。コード内のほかのソース行を調べて、こういった高メトリック値の原因である行を突きとめてください。

メトリックの形式

表 7-1 に、注釈付きソースコードの行に表示可能な 4 種類のメトリックスを示します。

表 7-1 注釈付きソースコードのメトリック

メトリック
意味
(空白)
プログラムに、このコード行に対応する PC が存在しません。コメント行は常にこの空白になります。また、次の場合の見かけ上のコード行も空白になります。
  • 最適化中に、見かけ上のコード部分のすべての命令が削除されている。

  • コードが別の場所で繰り返されていて、コンパイラによって共通する部分式が認識され、その行のすべての命令に繰り返し部分の行番号が付けられている。

  • コンパイラによって、その行の命令に不正な行番号が付けられている。

0.
プログラム内のいくつかの PC がこの行から派生したものとしてタグ付けされていますが、それらの PC を参照しているデータがありません。統計的にサンプリングされたかトレースされた呼び出しスタックに、そのような PC は存在しません。0. メトリックは、その行が実行されなかったことを意味するのではなく、プロファイリングデータパケットや記録されたトレースデータパケットに統計として表示されなかったことだけを意味します。
0.000
この行の少なくとも 1 つの PC がデータに表れていますが、メトリック値の計算でゼロに丸められました。
1.234
この行に属するすべての PC のメトリックの合計が、表示されているゼロ以外の数値になりました。