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

コンパイラのコメント

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

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


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 ソフトウェア実行の概要」を参照してください。