dbx コマンドによるデバッグ

第 10 章 データの視覚化

Sun Workshop でプログラムをデバッグするときに、データをグラフィック表示させる必要がある場合は、データの視覚化を行います。

データの視覚化は、デバッグ中に使用すると、大容量で複雑なデータセットの調査と理解、結果のシミュレーション、または画面とやりとりしながらの作業を進めていくことができます。「データグラフ」ウィンドウを使用することによってプログラムデータを「見る」ことができ、データをグラフィフィカルに分析できます。グラフは、印刷することもファイルに出力することもできます。

この章は、次の各節から構成されています。

適切な配列式の指定

データを表示させるには、配列とその表示方法を指定する必要があります。Sun Workshop の「デバッグ」ウィンドウで「式」フィールドに配列名を入力して、「データグラフ」ウィンドウを呼び出します。複雑な (Fortran) 配列型を除く、すべてのスカラ配列型がサポートされています。

一次元の配列は、x 軸にインデックス、y 軸に配列値を示したグラフ (ベクトルグラフ) になります。二次元の配列のデフォルトのグラフ表示 (エリアグラフ) は、 x 軸で第 1 次元のインデックス、y 軸で 第 2 次元のインデックス、z 軸で配列値を示したグラフになります。n 次元の配列をグラフ表示できますが、これらの次元の中で変更できるのは、 2 つまでです。

データセット全体を調べる必要はありません。次の例で示すように、配列の断面を指定するだけで済みます。図 10-1図 10-2 は、この章の最後にある Fortran のサンプルプログラムの bf 配列を示しています。

図 10-1 bf 配列名のみのグラフ (左)、bf (0:3,1:20) のグラフ (右)

Graphic

次の 2 つの図は、指定された値の範囲の配列を示したものです。

図 10-2 配列 bf のグラフ: bf (3,:) (左)、bf (:,7) (右)

Graphic

配列のグラフ化

配列をグラフ化する前に、次のような事前準備が必要です。

  1. 「デバッグ」ウィンドウにプログラムをロードします。

    「デバッグ」→「新規プログラム」を選択してプログラムをロードします。プログラムがすでに現在の Workshop セッションにロードされている場合は、「デバッグ」メニューのプログラムリストから該当するプログラムを選択します。

  2. プログラム内で、少なくとも 1 つのブレークポイントを設定します。

    1 つのブレークポイントをプログラムの最後に設定することも 1 つまたは複数のブレークポイントをプログラムの任意の位置に設定することもできます。

  3. プログラムを実行します。

    ブレークポイントでプログラムが停止したら、どの配列を調べるかを決めます。

以上で、選択した配列のグラフ化の準備ができました。Workshop から配列のグラフを作成するには、次のようにいくつかの方法があります。

「デバッグ」ウィンドウからのグラフ作成。「式」フィールド内に配列を入力し、「データ」→「式をグラフ表示」を選択するか、テキストエディタで配列を選択し、「デバッグ」ウィンドウ内で「データ」→「選択項目をグラフ表示」を選択します。

「データ表示」ウィンドウからのグラフ作成。「表示」→「ポップアップメニューを表示」を選択するか、マウスの右ボタンをクリックしてポップアップメニューを開いて、「グラフ」コマンドを選択します。「データ表示」 ウィンドウで式を表示して配列を選択した場合は、「グラフ」コマンドがアクティブになっています。

「データグラフ」ウィンドウからのグラフ作成。「グラフ」→「新規」を選択し、「データグラフ : 新規」ウィンドウの「式」フィールド内に配列名を入力し、「グラフ」をクリックします。「現在表示中のグラフを置き換え」ボタンをクリックすると、現在のグラフが新しいグラフに置き換わります。それ以外の場合は、新しい「データグラフ」ウィンドウが開きます。

「dbx コマンド」ウィンドウからのグラフ作成。vitem コマンドを使用すると、次のように dbx コマンド行から直接「データグラフ」を表示させることができます (Workshop で「dbx コマンド」ウィンドウを開いておく必要があります)。


(dbx) vitem -new array-expr

array-expr には、表示させる配列式を指定します。

配列表示の自動更新

配列式の値は、プログラムの実行とともに変化します。配列式の新しい値を、プログラム内の特定の位置で表示させるのか、または一定の時間間隔で再表示させるのかを選択できます。この選択は、グラフオプション内の「更新時期」の設定で行います。

プログラムがブレークポイントで停止するごとに配列の値を更新させる場合は、「更新時期」の「プログラム停止」オプションをオンにする必要があります。このようにすると、プログラムが進行していく段階で、各停止位置ごとの配列値を見ることができます。このオプションは、各ブレークポイントでデータの変更を表示させる場合に使用します。この機能は、デフォルトではオフに設定されています。

実行時間が長いプログラムの場合は、「更新時期」の「一定間隔で」オプションを選択すると、時間の経過とともに変化する配列値の変化を見ることができます。一定間隔での更新を使用すると、タイマーが一定 (n) の間隔ごとに自動的に設定されます。この間隔はデフォルトでは、1 秒に設定されています。デフォルトの設定を変更する場合は、「グラフ」→「デフォルトオプション」を選択し、「デバッグオプション」ダイアログボックス内の更新時間間隔を変更します (これは必ず データグラファカテゴリから行う必要があります)。


注 -

タイマーに設定された一定の間隔ごとに、Workshop はグラフ表示の更新を行いますが、配列がこの特定の時間に範囲外にある場合は、更新は行われません。


また、タイマーは、データ収集、メモリーのリークチェックまたはアクセスチェック時にも使用されるため、標本コレクタまたは実行時チェック機能の実行時には、「一定間隔での更新は設定できません。

表示の変更

データがグラフィック表示されたら、「データグラフ」ウィンドウ内のコントロールを使って表示画面の調整やカスタマイズが行えます。この節では、ユーザーが試してみるることができるグラフ表示の例をいくつか示します。

どのようなタイプの配列でもそれをグラフ化するときに、「データグラフ」ウィンドウを開くと、「拡大」と「縮小」オプションが表示されています。エリアグラフの場合は、このウィンドウには「軸回転」と「遠近率」フィールドが組み込まれます。これらのオプションを使用すると、その軸を回転させたり、奥行きを増減することによってグラフの表示を変更できます。グラフを簡単に回転させるには、グラフ上にカーソルを置いてマウスの右ボタンを押し、そのままグラフをドラッグします。また、各軸の回転の角度を、「軸回転」フィールドで指定することもできます。

これ以外のオプションを表示させる場合は、「オプション表示」ボタンをクリックします。オプションがすでに表示されている場合は、「オプションを隠す」ボタンをクリックして追加オプションを非表示にします。

図 10-3 は、同じ配列を 2 種類の表示画面で示したものです。左の図では、配列は、「ワイヤーメッシュ」構造の「表面」グラフタイプで表示されています。右の図では、配列は、「範囲線」によって輪郭を描く「等高線」グラフタイプで表示されています。

図 10-3 同じ配列の2種類の表示画面

Graphic

「等高線」グラフタイプを選択すると、「範囲」オプションで、どのエリアのデータ値が変化したかがわかります。

「表面」グラフタイプの表示オプションには、「テクスチャー」、「シェーディング」、「塗りつぶし」があります。テクスチャーの選択肢には、図 10-4 で示す「ワイヤーメッシュ」または「範囲線」があります。

図 10-4 「表面」グラフの「ワイヤーメッシュ」(左) と「範囲線」(右)

Graphic

「表面」グラフタイプ用のシェーディングの選択肢には、「光源」または「範囲色」があります。

Graphic

「塗りつぶし」をオンにすると、グラフの領域に陰影 (シェーディング) をつけたり、立体的にしたりできます。

Graphic

グラフタイプで「等高線」を選択すると、データ範囲を表す線を使用したエリアグラフが表示されます。「等高線」グラフタイプには、「範囲線」、「範囲色」、またはこの両方によりグラフを表示させる追加オプションがあります。

図 10-5 「範囲線」(左)、「範囲色」(中央)、「両方」(右)を指定した場合の「等高線」グラフ

Graphic

「範囲」の「範囲分割数」フィールドの値を変更すると、表示するデータ値の範囲の数値を変更できます。

図 10-6 「範囲分割数」: 5(左)、10(中央)、15(右)

Graphic

「範囲分割数」に大きな数を選択すると、反対にカラーマップに悪影響を与える可能性があるので注意してください。

範囲の間隔の凡例を表示させたい場合は、「範囲の凡例を表示」ボタンをクリックします。

視覚化されたデータの分析

視覚化されたデータの更新方法は、更新内容によって異なります。たとえば、その必要に応じて、ブレークポイントで更新することも指定した時間間隔で更新することもできます。変更内容を表示したり、最終的な結果を分析したりすることができます。この節では、さまざまなシチュエーションのシナリオを想定しています。

Workshop には、dg_fexamp(Fortran) と dg_cexamp(C) の 2 つのサンプルプログラムが付属しています。データの視覚化を説明する以下のシナリオの中で、この 2 つのサンプルプログラムを使用します。

また、これらのプログラムは練習用にも使用できます。このサンプルプログラムは、install-dir/SUNWspro/WS5.0/examples/datagrapher にあります。ここで、デフォルトの install-dir/opt です。このプログラムを使用する場合は、このディレクトリに移動し、make と入力します。すると、実行可能プログラムが作成されます。

シナリオ 1: 同じデータを違う視点で表示させて比較する

同じデータを何回でもグラフ化できるため、グラフタイプを変えたり、データのセグメント変えたりして比較できます。

  1. C または Fortran のサンプルプログラムをロードします。

  2. プログラムの最後にブレークポイントを設定します。

  3. プログラムを起動し、ブレークポイントの位置まで実行します。

  4. 「デバッグ」ウィンドウの「式」フィールドに bf と入力します。

  5. 「データ」→「式をグラフ表示」を選択し、bf 配列の二次元の「表面」グラフを開きます。

  6. もう一度「データ」→「式をグラフ表示」を選択し、もう 1 つ同じグラフを開きます。

  7. 「オプション表示」をクリックし、グラフ種類で「等高線」を選択します。これで、異なるグラフタイプで表示された同じデータを比較できます (「表面」と「等高 線」)。

  8. 「式」フィールドに、Fortran のサンプルプログラムの場合は bf(1,:)、C のサンプルプログラムの場合は bf[1][..] と入力します。

  9. 次に、「データ」→「式をグラフ表示」を選択し、この bf 配列に入ったデータセクションのグラフを開きます。

これで、ここまでに表示させた同一データの異なるタイプの表示画面をすべて比較できます。

シナリオ 2: データのグラフを自動的に更新する

「更新時期」の「プログラム停止」オプションをオンにすると、グラフの更新を自動的に制御できます。この機能を使用すると、プログラムの実行中のデータの変化を比較できます。

  1. C または Fortran のサンプルプログラムをロードします。

  2. bf 関数の外側のループの最後にブレークポイントを設定します。

  3. プログラムを起動し、ブレークポイントの位置まで実行します。

  4. 「式」フィールドに bf と入力します。

  5. 「データ」→「式をグラフ表示」を選択します。ループの最初の反復が終わると、bf 配列内の値のグラフが表示されます。

  6. 「オプション表示」をクリックし、「更新時期」の「プログラム停止」を選択します。

  7. 「実行」→「継続」コマンドを選択し、このプログラムのほかのループの反復を複数実行させます。プログラムがブレークポイントで停止するごとに、グラフは、直前のループの反復で設定された値に更新されます。

  8. 各ブレークポイントでデータの最新のグラフを表示させたい場合は、この自動更新機能を使用すれば時間を節約できます。

シナリオ 3: プログラムの異なる箇所のデータグラフを比較する

グラフの更新は、手動でも制御できます。

  1. C または Fortran のサンプルプログラムをロードします。

  2. af 関数の外側のループの最後にブレークポイントを設定します。

  3. プログラムを起動し、ブレークポイントの位置まで実行します。

  4. 「式」フィールドに af と入力します。

  5. 「データ」→「式をグラフ表示」を選択します。ループの最初の反復が終わると、af 配列内の値のグラフが表示されます。このグラフでは、必ず自動更新機能はオフ (デフォルトの設定) にしておいてください。

  6. 「実行」→「継続」 コマンドを使用して、このプログラムのほかのループの反復を実行させます。

  7. 「データ」→「式をグラフ表示」を選択し、af 配列を表示した別のグラフを開きます。このグラフには、外側のループの 2 番目の反復に設定されたデータの値が使用されています。

  8. ここで、af 配列の 2 つのループの反復間でデータを比較できます。自動更新をオフに設定したグラフであれば、継続的に自動または手動で更新が行われているグラフに対する基準のグラフとして使用できます。

シナリオ 4: 同じプログラムを別々に実行した結果のデータグラフを比較する

同じプログラムを複数回実行させる場合、次にそのプログラムを実行させるまで前のデータグラフが画面に残っています。前にプログラムを実行したときのデータから作成したグラフは、手動で更新するか、または自動更新機能がオンになっていない限り上書きされません。

  1. C または Fortran のサンプルプログラムをロードします。

  2. プログラムの最後にブレークポイントを設定します。

  3. プログラムを起動し、ブレークポイントの位置まで実行します。

  4. 「式」フィールドに vec と入力し、「データ」→「式をグラフ表示」を選択します。

  5. vec 配列のグラフが表示されます (正弦波曲線で)。

  6. ここで、プログラムを編集できます (たとえば、sin を cos に置き換えるなど)。修正継続機能を使用し、プログラムの再コンパイルを行ってから作業を続行します (エディタの「修正」ツールバーボタンをクリックします)。

  7. プログラムを再起動します。

  8. 自動更新機能がオフになっているため、プログラムがブレークポイントに到達しても、前に作成されたグラフは更新されません。

  9. 「データ」→「式をグラフ表示」を選択し (vec が「式」フィールドに入力されたままの状態です)、現在の vec 値のグラフを、前の実行時に作成されたグラフと並べて表示します。

  10. これで、2 回の実行により作成されたそれぞれのグラフを比較できます。「グラフ更新」ボタンを使用して手動で更新した場合か、自動更新機能がオンになっている場合にだけ前の実行時のグラフは変更されます。

Fortran のサンプルプログラム


real vec(100)
real af(50,50)
real bf(-3:3,-10:20)
real cf(50, 100, 200)
int x,y,z

ct = 0

do x = 1,100
            ct = ct + 0.1
            vec(x) = sin(ct)
enddo

do x = 1,50
           do y = 1,50
              af(x,y) = (sin(x)+sin(y))*(20-abs(x+y))
           enddo
 enddo

do x = -3,3
          do y = -10,20
            bf(x,y) = y*(y-1)*(y-1.1)-10*x*x*(x*x-1)
          enddo
enddo

do x = 1,50
          do y = 1,100
            do z = 1,200
              cf(x,y,z) = 3*x*y*z - x*x*x - y*y*y - z*z*z
            enddo
          enddo
enddo

end

C のサンプルプログラム


#include <math.h>
main()
{
    int x,y,z;
    float ct=0;
    float vec[100];
    float af[50][50];
    float bf[10][20];
    float cf[50][100][200];

    for (x=0; x<100; x++)
    {
          ct = ct + 0.1;
          vec[x] = sin(ct);
    }
    for (x=0; x<50; x++)
    {
          for (y=0; y<50; y++)
          {
          af[x][y] = (sin(x)+sin(y))*(20-abs(x+y));
          }
    }
    for (x=0; x<10; x++)
    {
          for (y=0; y<20; y++)
          {
            bf[x][y] = y*(y-1)*(y-1.1)-10*x*x*(x*x-1);
          }
    }
    for (x=0; x<50; x++)
    {
          for (y=0; y<100; y++)
          {
          for (z=0; z<200; z++)
          {
                    cf[x][y][z] = 3*x*y*z - x*x*x - y*y*y - z*z*z ;
          }
          }
    }
}