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

ループレポートの起動

ループレポートの起動時に、プログラム名を入力します。loopreport の後ろに検証したいプログラム名 (実行可能ファイル) を入力してください。


% loopreport program

プログラム名を指定せずにループレポートを起動することも可能です。ただし、プログラム名を指定せずにループレポートを起動する場合、ループレポートは現在の作業ディレクトリを検索して、a.out という名前のファイルを探します。


% loopreport > a.out.loopreport

出力をファイルにリダイレクトしたり、パイプによってほかのプログラムへと受け渡すことも可能です。


% loopreport program > program.loopreport
% loopreport program | more

タイミングファイル

ループレポートはプログラムに関連したタイミングファイルを一緒に読み込みます。タイミングファイルは、-zlp オプションを使用する場合に作成され、ループに関する情報を含みます。通常、タイミングファイルには program.looptimes という形式の名前が付けられ、プログラムと同じディレクトリに収められます。

しかし、 タイミングファイルの位置を指定する方法も 4 種類ほど用意されています。ループレポートは、以下に示すルールに従ってタイミングファイルを選択します。

図 3-4 ループレポートの例

Graphic

ループレポートのフィールド

以下の説明は、ループツールの「レポートの作成」出力およびループレポートの出力にもそのままあてはまります。

ループレポートには、以下の情報が含まれています。

コンパイル時にコンパイラによって割り当てられる任意の番号。これはループとの対話には便利な内部的なループ ID で、プログラムとの実質的な関連はありません。

ソースファイルにおけるループの先頭ステートメントの行番号。

Yes ならば、ループが並列化の対象としてマークされていることを示し、No ならば、そうでないことを示します。

「コンパイラヒントの説明」リストのヒントテキストに対応した番号。

その上位からループへと入り込む回数。エントリは、ループが実行される総数であるループ反復回数とは異なります。たとえば、以下のコードは Fortran で書かれた 2 つのループです。


do 10 i=1,17
    do 10 j=1,50
    ...some code...
    10 continue

最初のループには 1 度だけ入り、ループは 17 回反復されます。2 番目のループには 17 回入り込み、ループは 17*50 = 850 回反復されます。

ループの入れ子のレベル。ループがトップレベルのループならば、入れ子のレベルは 0 です。ループがほかのループの子ループならば、レベルは 1 となります。

たとえば、以下に示す C のコードでは、i ループはレベル 0、j ループはレベル 1、k ループはレベル 2 となります。


for (i=0; i<17; i++)
    for (j=0; j<42; j++)
    for (k=0; k<1000; k++)
        do something;

プログラム全体に対して、このループを実行するために費やされる経過時計時間の総計。外側のループの経過時計時間には、内側のループの経過時計時間が含まれます。以下に例を示します。


for (i=1; i<10; i++)
    for (j=1; j<10; j++)
       do something; 

たとえば、上記の例で、外側のループ ( iループ) に割り当てられる時間が 10 秒だとしたら、内側のループ (j ループ) に割り当てられる時間は 9.9 秒となります。

ループの実行に費やされる時計時間として計測されたプログラム実行時間全体におけるパーセンテージ。時計時間においては、外側のループにはそこに含まれるループに費やされる時間も含まれます。

ループにおいてデータ依存を生じる変数の名前。このフィールドは、コンパイラヒントに、ループがデータ依存の弊害を受けていると示される場合のみ表示されます。あるループ内の繰り返しの中で計算される値がほかのループでも使用されるなどの理由で、ループの並列化が安全に行われない場合などに、データ依存の問題は発生します。データ依存の例を以下に示します。


do i = 1, N
    a(i) = b(i) + c(i)
    b(i) = 2 * a(i + 1)
end do

上記のループ例が並列処理で実行される場合、a(2) の値を基に b(1) の値を再計算する反復 1 は、a(2) の再計算を終えたばかりの反復 2 の後に実行される可能性が出てきます。つまり、ループが並列処理されなかった場合とは異なり、b(1) の値は、オリジナルの値ではなく、新しい a(2) の値によって決まってしまいます。