この付録には、スレッドアナライザを使用するときのヒントが記されています。
実験結果の収集前にアプリケーションをコンパイルするためのヒント
アプリケーションバイナリを構築するときに -g コンパイラオプションを使用します。これにより、スレッドアナライザでデータの競合の行番号情報を報告できます。
アプリケーションバイナリを構築するときに、-xO3 より低い最適化レベルでコンパイルします。コンパイラの変換は、行番号情報を歪め、結果をわかりにくくさせます。
スレッドアナライザは、「A.2.3 メモリー割り当て API」 で示したメモリー割り当てルーチンで割り込み処理をします。アーカイブバージョンのメモリー割り当てライブラリにリンクすると、誤検知のデータ競合が報告される場合があります。
実験結果を収集する前に、データの競合検出用アプリケーションを計測するためのヒント
コンパイラオプション -xinstrument=datarace が不正であることを示すエラーメッセージが、コンパイラから表示された場合、スレッドアナライザをサポートしていない古いバージョンの Sun Studio コンパイラを使用しています。使用しているコンパイラのバージョンは、コマンド cc -Version と入力すると確認できます。スレッドアナライザをサポートする最も古いバージョンは、2006 年 6 月の日付のものです。
次に示すように、データの競合の検出用にバイナリが計測されていない場合、collect -r race コマンドは、警告を発行します。
% collect -r races a.out WARNING: Target `a.out' is not instrumented for datarace detection; reported datarace data may be misleading |
nm コマンドを使用して、tha ルーチンの呼び出しを検索することにより、データの競合の検出用にバイナリが計測されているかどうかを判断できます。名前が __tha_ で始まるルーチンが表示されたら、バイナリは計測されています。例出力は次のとおりです。
ソースレベルの計測
% cc -xopenmp -g -xinstrument=datarace source.c % nm a.out | grep __tha_ [71] | 135408| 0|FUNC |GLOB |0 |UNDEF |__tha_get_stack_id [53] | 135468| 0|FUNC |GLOB |0 |UNDEF |__tha_src_read_w_frame [61] | 135444| 0|FUNC |GLOB |0 |UNDEF |__tha_src_write_w_frame |
バイナリレベルの計測
% cc -xopenmp -g source.c % discover -i datarace -o a.out.i a.out % nm a.out.i | grep __tha_ [88] | 0| 0|NOTY |GLOB |0 |UNDEF |__tha_read_w_pc_frame [49] | 0| 0|NOTY |GLOB |0 |UNDEF |__tha_write_w_pc_frame |
discover を使用するには、いずれかのコンパイラ最適化フラグ (-xO1、-xO2、-xO3、-xO4、-xO5) で入力バイナリをコンパイルする必要があります。コンパイラは、Oracle Solaris Studio 12 Update 1 以降のリリースのものである必要があります。オペレーティングシステムは、Oracle Solaris 10 Update 5 または OpenSolaris バージョン snv_70 以上である必要があります。そうでない場合は、次に示すように警告が表示される場合があります。
% discover -i datarace -o a.out.i a.out discover (warning): a.out has no annotations. Results may be incomplete. See discover documentation for compiler flag/OS recommendation |
また、バイナリがコンパイラオプション -xbinopt=prepare を付けてコンパイルされた場合は、SPARC ベースのシステムで実行中の、以前の Solaris バージョンでも discover ツールを使用できることがあります。このコンパイラオプションについては、cc(1)、CC(1)、または f95(1) のマニュアルページを参照してください。
データの競合およびデッドロックを検出するために、計測したアプリケーションを実行するためのヒント。
Solaris システムにすべての必須パッチがインストールされていることを確認します。collect コマンドは、見つからない必須パッチを一覧表示します。OpenMP アプリケーションの場合、libmtsk.so の最新バージョンが必要です。
-r race または -r deadlock 引数が認識されないというエラーメッセージが collect から表示された場合、スレッドアナライザをサポートしていない古いバージョンの collect を使用しています。使用している collect のバージョンは、collect -Version コマンドを入力することによって確認できます。スレッドアナライザをサポートする最も古いバージョンは、2006 年 6 月の日付のものです。
計測は、実行時間の大幅な減速 (50 倍以上) と、メモリー消費量の増大を引き起こす可能性があります。より小さなデータセットを使用することにより、実行時間を減らそうと試みることができます。また、スレッド数を増やすことによって、実行時間を減らそうと試みることもできます。
データ競合を検出するには、アプリケーションが複数のスレッドを使用していることを確認します。OpenMP の場合、スレッド数は、環境変数 OMP_NUM_THREADS を、目的のスレッド数に設定し、環境変数 OMP_DYNAMIC を FALSE に設定することによって指定できます。
データの競合の報告のヒント
スレッドアナライザは、実行時にデータの競合を検出します。アプリケーションの実行時の動作は、使用される入力データセットとオペレーティングシステムのスケジュールによって異なります。異なるスレッド数と、異なる入力データセットで collect 下でアプリケーションを実行します。また、ルールがデータの競合を検出するチャンスを最大にするために、単一のデータセットでの実験を繰り返します。
スレッドアナライザは、単一のプロセスから生じた異なるスレッド間でのデータの競合を検出します。異なるプロセス間でのデータの競合は検出しません。
スレッドアナライザは、データの競合でアクセスされた変数の名前を報告しません。ただし、2 つのデータの競合アクセスが行われたソース行を調べ、このソース行で変数が書き込まれ、読み取られたかを判断することによって、変数の名前を判別できます。
場合によっては、スレッドアナライザは、プログラムで実際には起きなかったデータの競合を報告することがあります。これらのデータの競合は誤検知と呼ばれます。これは通常、ユーザーが実装した同期が使用される場合や、メモリーがスレッド間でリサイクルされる場合に起こります。たとえば、スピンロックを実装する手製アセンブリがコードに含まれる場合、スレッドアナライザはこれらの同期ポイントを認識しません。スレッドアナライザのユーザー API に対する呼び出しをソースコードに挿入して、ユーザー定義の同期についてスレッドアナライザに通知します。詳しくは、「2.5 誤検知」および付録 A スレッドアナライザで認識される APIを参照してください。
ソースレベルの計測を使用して報告されたデータの競合ととバイナリレベルの計測を使用して報告されたデータの競合は、同じでない場合があります。バイナリレベルの計測の場合、それらがプログラム内で静的にリンクされているか、dlopen() によって動的に開かれているかにかかわらず、共有ライブラリは開いているときに、デフォルトで計測されます。ソースレベルの計測の場合、ライブラリは、そのソースが -instrument=datarace でコンパイルされている場合にのみ計測されます。