Sun Studio 12: dbx コマンドによるデバッグ

第 13 章 OpenMP プログラムのデバッグ

OpenMPTM アプリケーションプログラミングインタフェース (API) は、共用メモリーマルチプロセッサアーキテクチャー用に複数のコンピュータベンダーと共同で開発された並列プログラミングモデルです。Fortran、C++ および C の OpenMP プログラムを dbx を使用してデバッグするためのサポートは、dbx の汎用マルチスレッドデバッグ機能に基づいています。スレッドおよび LWP 上で動作するすべての dbx コマンドは OpenMP デバッグに使用できます。dbx は、OpenMP デバッグでの非同期スレッド制御はサポートしていません。

この章の内容は次のとおりです。

Sun Studio Fortran 95 および C コンパイラによって実装される指示、実行時ライブラリルーチン、および OpenMP Version 2.0 アプリケーションプログラムインタフェースの環境変数については、『OpenMP API ユーザーズガイド』を参照してく ださい。


注 –

OpenMP デバッグが行えるのは Solaris OS の動作しているプラットフォームのみです。Linux プラットフォームで行うことはできません。


コンパイラによる OpenMP コードの変換

OpenMP デバッグの詳細については、OpenMP コードがコンパイラによってどのように変換されるかを理解することが役立ちます。次に Fortran の例を示します。


1    プログラムの例
2        integer i, n
3        parameter (n = 1000000)
4        real sum, a(n)
5    
6        do i = 1, n
7        a(i) = i*i
8        end do
9    
10        sum = 0
11    
12    !$OMP PARALLEL DO DEFAULT(PRIVATE), SHARED(a, sum)
13    
14        do i = 1, n
15        sum = sum + a(i)
16        end do
17    
18    !$OMP END PARALLEL DO
19    
20        print*, sum
21        プログラムの例、終わり

行 12 〜 18 のコードは並列領域です。f95 コンパイラは、コードのこのセクションを、 OpenMP 実行時ライブラリから呼び出されるアウトラインサブルーチンに変換します。このアウトラインサブルーチンには、内部で生成された名前が付きます。この場合は _$d1A12.MAIN_ です。次に f95 コンパイラは、 OpenMP 実行時ライブラリへの呼び出しによって並列領域用にコードを置換して、アウトラインサブルーチンを引数の 1 つとして渡します。OpenMP 実行時ライブラリはすべてのスレッド関連実行を処理し、アウトラインサブルーチンを並列で実行するスレーブスレッドをディスパッチします。C コンパイラも同様に動作します。

OpenMP プログラムをデバッグするときには、アウトラインサブルーチンは dbx によって別の関数として扱われますが、内部生成された名前を使用して関数内のブレークポイントを明示的に設定することはできません。

OpenMP コードで利用可能な dbx の機能

マルチスレッドプログラムのデバッグ用の機能に加えて、OpenMP プログラム内で dbx を使用して次のことが実行できます。

OpenMP コードにおけるスタックトレースの使用

並列領域で実行が停止されると、 where コマンドによってアウトラインサブルーチンを含むスタックトレースと複数の実行時ライブラリ呼び出しが表示されます。 「コンパイラによる OpenMP コードの変換」の Fortran の例を使用して実行を行 15 で停止すると、where コマンドによって次のスタックトレースが生成されます。


[t@4 l@4]: where
現スレッド: t@4
=>[1] _$d1A12.MAIN_(), 行番号 15  "example.f90"
[2] __mt_run_my_job_(0x45720, 0xff82ee48, 0x0, 0xff82ee58, 0x0, 0x0), at 0x16860
[3] __mt_SlaveFunction_(0x45720, 0x0, 0xff82ee48, 0x0, 0x455e0, 0x1), at 0x1aaf0

スタックの上位フレームはアウトライン関数のフレームです。コードがアウトラインされていても、ソース行番号は 15 にマップされたままです。ほかの 2 つのフレームは実行時ライブラリルーチン用です。

並列領域で実行が停止されると、前述の例のようにスレーブスレッドの where コマンドはスタックトレースを親スレッドに戻しません。ただし、マスタースレッドの where コマンドは完全トレースバックを行います。


[t@4 l@4]: thread t@1
t@1 (l@1) で停止しました _$d1A12.MAIN_ 行番号 15 ファイル "example.f90"
15           sum = sum + a(i)
[t@1 l@1]: where
現スレッド: t@1
=>[1] _$d1A12.MAIN_(), 行番号 15  "example.f90"
[2] __mt_run_my_job_(0x41568, 0xff82ee48, 0x0, 0xff82ee58, 0x0, 0x0), at 0x16860
[3] __mt_MasterFunction_(0x1, 0x0, 0x6, 0x0, 0x0, 0x40d78), at 0x16150
[4] MAIN(), 行番号 12 "example.f90"

いくつかのスレッドが大きくない場合、threads コマンド (threads コマンド」参照) を使用してすべてのスレッドをリスト表示し、スレーブスレッド内で実行がどのようにブレークポイントに到達したかを判別し、各スレッドに切り替えてマスタースレッドを判別することができます。

OpenMP コードにおける dump コマンドの使用

並列領域で実行が停止すると、dump コマンドによって private 変数の複数のコピーが出力されます。次の例では、dump c コマンドが変数 i の 2 つのコピーを出力します。


[t@1 l@1]: dump
i = 1
sum = 0.0
a = ARRAY
i = 1000001

変数 i の 2 つのコピーが出力されるのは、アウトラインルーチンがホストルーチンのネストされた関数として実装され、private 変数がアウトラインルーチンの局所変数として実装されます。dump コマンドがスコープ内のすべての変数を出力する ため、ホストルーチン内の i およびアウトラインルーチン内の i の両方が表示されます。

OpenMP コードの実行シーケンス

OpenMP プログラム内の並列領域の内部にシングルステップするときの実行シーケンスは、ソースコードシーケンスとは同じではありません。シーケンスが異なるのは、並列領域内のコードが通常はコンパイラによって変換され再配置されるためです。OpenMP コード内でのシングルステップは、オプティマイザがコードを移動する最適化コード内でのシングルステップと似ています。