Compaq C コンパイラは,OpenMP C APIに準拠した共用メモリ並列処理アプリケーションの開発をサポートします。 この API は,コンパイラ指示文,ライブラリ関数,環境変数の集合を定義し,コンパイラ,リンカ,実行時環境に指示を与えて,アプリケーションの複数の部分を並行して実行できるようにします。
OpenMP 指示文を使用すると,複数のプロセッサで並行して実行できるコードを,通常の直列的な ANSI C のソース・コードの構造を変更することなく作成できます。 これらの指示文を正しく使用すれば,マルチプロセッサ・マシンの別々のプロセッサでそのコードが同時に実行できるため,ユーザ・コードの経過時間に関する性能を大幅に向上できます。 同じソース・コードをコンパイルするときに,並列処理の指示文を無視するようにすれば,OpenMP でのコンパイルと同じ機能を実行する直列的な C 言語プログラムになります。
『OpenMP C and C++ Application Programming Interface』仕様書は,インターネット上の
http://www.openmp.org/specs/
で参照できます。
この章では,次の項目について説明します。
コンパイル・オプション (13.1 節)
環境変数 (13.2 節)
実行時性能のチューニング (13.3 節)
プログラミング上の一般的な問題 (13.4 節)
インプリメンテーション固有の動作 (13.5 節)
デバッグ (13.6 節)
次の
cc
コマンド行オプションは,並列処理をサポートします。
-mpコンパイラが OpenMP の手動分解プラグマと従来の手動分解指示文の両方を認識するようにします。
libots3
がリンクに含まれるようにします。
従来の手動分解指示文の詳細については,付録 D
を参照してください。
-ompコンパイラが OpenMP の手動分解プラグマだけを認識し,従来の手動分解指示文を無視するようにします。
従来の手動分解指示文の処理を除いて,-mp
と
-omp
スイッチは同じです。
つまり,-mp
は従来の指示文を認識し,-omp
は認識しません。
-granularity size異なるスレッドから安全にアクセスできるメモリ内の共用データのサイズを制御します。
size
の有効な値は,byte,longword,および
quadword
です。
byte1 バイト以上のすべてのデータに,メモリ内のデータを共用する別々のスレッドからアクセスできるようにします。 このオプションを使用すると,実行時の性能が低下します。
longword自然に位置合わせされている 4 バイト以上のデータに,メモリ内のデータへのアクセスを共用する別々のスレッドから安全にアクセスできるようにします。 3 バイト以下のデータ項目および位置合わせされていないデータにアクセスすると,複数のスレッドから書き込まれたデータ項目の更新に一貫性が保たれない場合があります。
quadword自然に位置合わせされている 8 バイトのデータに,メモリ内のデータを共用する別々のスレッドから安全にアクセスできるようにします。 7 バイト以下のデータ項目および位置合わせされていないデータにアクセスすると,複数のスレッドから書き込まれたデータ項目の更新に一貫性が保たれない場合があります。 これは,省略時の値です。
-check_omp特定の OpenMP 構造の実行時検査が行われるようにします。 これには,無効なネストおよびその他の無効な OpenMP の事例の実行時検出が含まれます。 実行時に無効なネストが検出された場合にこのスイッチが設定されていると,実行可能プログラムは Trace/BPT トラップで異常終了します。 このスイッチが設定されていないときに無効なネストが検出されると,その場合の動作は予測できません。 たとえば,実行可能プログラムが停止することがあります。
コンパイラでは,次の無効なネスト状態を検出します。
ワーク・シェアリング構造,critical
セクション,または
master
内に,for,single,または
sections
指示文を入れる。
ワーク・シェアリング構造,critical
セクション,または
master
内で,barrier
指示文を実行する。
ワーク・シェアリング構造内で,master
指示文を実行する。
critical
セクション内で,ordered
指示文を実行する。
ordered for
内でないのに,ordered
指示文を実行する。
省略時の設定では,実行時検査は行われません。
コンパイラおよび実行時システムは,OpenMP 仕様に概要が示されている環境変数に加えて,次の環境変数を認識します。
MP_THREAD_COUNT実行時システムが作成するスレッドの数を指定します。
省略時の設定は,プロセスで使用できるプロセッサの数です。
OMP_NUM_THREADS
環境変数は,この変数に優先します。
MP_STACK_SIZE各スレッドについて,実行時システムが割り当てるスタック空間のバイト数を指定します。 0 を指定した場合,実行時システムでは非常に小さい,省略時の設定を使用します。 したがって,プログラムで大きな配列を PRIVATE として宣言したときは,これらを割り当てられるだけの値を指定してください。 この環境変数を使用しない場合,実行時システムは 5 MB を割り当てます。
MP_SPIN_COUNT条件が真になるのを待つ間に,実行時システムが何回スピンするかを指定します。 省略時の設定は 16,000,000 で,これは CPU 時間の約 1 秒に相当します。
MP_YIELD_COUNTスレッド条件変数を待ってスリープに入るまでに,実行時システムが
sched_yield
の呼び出しと条件の検査を何回交互に実行できるかを指定します。
省略時の設定は 10 です。
OpenMP 仕様では,parallel for 構造で,使用できるスレッドに処理を分散する各種の方法を用意しています。
以降の各項では,これらの方法について説明します。
13.3.1 スケジュール・タイプとチャンクサイズの設定
スケジュール・タイプとチャンクサイズの設定の選択は,並列化されたアプリケーションの最終的な性能に良くも悪くも影響することがあります。 スケジュール・タイプとチャンクサイズに不適切な設定を選択すると,並列化されたアプリケーションの性能が,直列化の場合と同じか,またはそれ以下に低下する可能性があります。
一般的な指針を次に示します。
一般的に,チャンクサイズは値が小さい方が処理速度が速くなります。 チャンクサイズの値は,反復数を使用可能なスレッド数で割ることにより得られる値と同じか,またはそれ以下にしてください。
スケジュール・タイプ
dynamic
および
guided
は,並列化されたアプリケーション以外の,各種負荷を抱えるターゲット・マシンに適した動作をします。
これらのタイプでは,スレッドが使用可能になるごとにスレッドに反復を割り当てます。
他のアプリケーションが 1 つまたは複数のプロセッサを使用している場合は,使用可能なスレッドが次の反復を処理します。
スケジュール・タイプ
runtime
は,スケジュール・タイプの実行時のチューニングを容易にしますが,実行時オーバヘッドの点では若干の性能の低下が生じます。
スケジュール・タイプとチャンクサイズが適切に設定されているかどうかを判断するには,スケジュール・タイプを
runtime
に設定したうえで,OMP_SCHEDULE
環境変数を使用してスケジュール・タイプとチャンクサイズの各種組み合わせを試してみる方法が効果的です。
試行の後,最も良い性能が得られたスケジュール・タイプとチャンクサイズを明示的に設定します。
スケジュール・タイプとチャンクサイズの設定は,アプリケーションの性能に影響する数多くの要因のうちの 2 つに過ぎません。 性能に影響を及ぼす可能性のあるその他の要因には,次のものがあります。
システム・リソースの使用可能度: ターゲット・マシンで他のアプリケーションを処理している CPU は,並列化されたアプリケーションでは使用できません。
並列化されたコードの構造: 並列領域のスレッドが,不均衡な量の処理を実行している場合。
暗黙のまたは明示的なバリアの使用: このような明示的または暗黙のポイントですべてのスレッドの同期を強制する並列領域があると,1 つまたは複数のスレッドを待つ間,アプリケーションが一時停止する場合があります。
critical
セクションの使用と
atomic
文の使用:
critical
セクションを使用すると,atomic
よりもオーバヘッドが大きくなります。
スケジュール・タイプとチャンクサイズの設定の詳細については,『OpenMP C and C++ Application Programming Interface』仕様書を参照してください。
あるスレッドが,他のスレッドによって発生するイベントを待つ必要がある場合は,次の 3 段階のプロセスが開始されます。
そのスレッドは,特定の反復数だけスピンしながら,イベントの発生を待ちます。
プロセッサを何回も他のスレッドに譲りながら,イベントが発生していないかどうかを検査します。
起こすように要求を送ってからスリープに入ります。
他のスレッドによりイベントが発生すると,スリープしているスレッドが起こされます。
環境変数
MP_SPIN_COUNT
と
MP_YIELD_COUNT,または
mpc_destroy
ルーチンを使用してスレッド環境をチューニングすると,性能が向上することがあります。
MP_SPIN_COUNT
--
アプリケーションがスタンドアロンで実行される場合は,省略時の設定で良い性能が得られます。
しかし,アプリケーションが他のアプリケーションとプロセッサを共用しなければならない場合は,MP_SPIN_COUNT
の値を減らした方がよいでしょう。
このことによりスレッドがスピンに浪費する時間が削減されて,プロセッサを明け渡す時間が早くなります。
ただし,スレッドをスリープさせた後に再び起こすための時間がかかります。
このような共用環境では,MP_SPIN_COUNT
は 1000 程度に設定するとよいでしょう。
mpc_destroy
-- 実行時に余分なスレッドが存在すると問題が起こる可能性がある処理 (fork
など) を実行する場合は,mpc_destroy
ルーチンが役に立ちます。
mpc_destroy
ルーチンは,並列領域を実行するために作成されたワーカ・スレッドを破壊します。
通常,mpc_destroy
ルーチンは,並列領域の外からだけ呼び出します。
mpc_destroy
ルーチンは
libots3
ライブラリに定義されています。
以降の各項では,並列化されたプログラムでよく発生するエラーについて説明します。
13.4.1 範囲指定
OpenMP の parallel 構造は,そのすぐ後の構造化ブロックに適用されます。 複数の文を並列に実行する場合は,構造化ブロックを必ず中カッコ内に入れます。 次に例を示します。
#pragma omp parallel
{
pstatement one
pstatement two
}
この構造化ブロックは,次に示す,OpenMP の parallel 構造が最初の文にのみ適用される構造化ブロックとは全く異なります。
#pragma omp parallel pstatement one pstatement two
中カッコを使用して後続のブロックの範囲を明示的に定義することを強くお勧めします。
13.4.2 デッドロック
どのマルチスレッド・アプリケーションにも言えることですが,プログラマは実行時のデッドロック状態を回避するよう注意する必要があります。 多くの OpenMP 構造には最後に暗黙のバリアがあるため,すべてのスレッドがその構造にアクティブに加わらない場合,アプリケーションでデッドロックが生じます。 このような状態は,アプリケーションの動的なエクステントを並列化する場合により多く生じます。 次に例を示します。
worker ()
{
#pragma omp barrier
}
main ()
{
#pragma omp parallel sections
{
#pragma omp section
worker();
}
}
この例では,すべてのスレッドが
worker
ルーチンに行くわけではないのに,バリアがすべてのスレッドを待つため,(複数のスレッドがアクティブなままで) デッドロックが生じます。
このような状態の検出には,-check_omp
オプション (13.1 節を参照) が役に立ちます。
有効および無効な指示文のネストの詳細については,『OpenMP C and C++ Application Programming Interface』仕様書を参照してください。
13.4.3 threadprivate ストレージ
threadprivate
指示文は,ファイルの有効範囲を持ちながらも各スレッドにプライベートな変数を識別します。
スレッド数が一定である場合,これらの変数の値は維持されます。
プログラム内でスレッド数を明示的に増減したときの
threadprivate
変数の値への影響は定義されていません。
13.4.4 ロックの使用
ロック制御ルーチン (『OpenMP C and C++ Application Programming Interface』仕様書を参照) を使用するには,特定の順序で呼び出す必要があります。
まず,ロック変数と関連付けるロックを初期化します。
関連付けられたロックが実行スレッドで使用できるようにします。
実行スレッドのロックの所有を解除します。
終了したら,ロックとロック変数の関連付けを解除します。
これ以外の順序でロックを使用しようとすると,デッドロック状態などの予期しない動作が生じることがあります。
13.5 インプリメンテーション固有の動作
OpenMP 仕様では,いくつかの機能と省略時の値をインプリメンテーション固有のものとしています。 この節では,このような事例と Compaq C で選択されているインプリメンテーションを示します。
ネストされた並列領域があると,1 つのスレッドで構成されるチームがその領域の実行のために作成されます。
OMP_SCHEDULE
の省略時の値省略時の値は
dynamic,1
です。
この値は,アプリケーションが実行時スケジュールを使用するときに,OMP_SCHEDULE
が定義されていない場合に使用されます。
OMP_NUM_THREADS
の省略時の値省略時の値は,マシンのプロセッサの数と同じです。
OMP_DYNAMIC
の省略時の値省略時の値は 0 です。
このインプリメンテーションでは,スレッド・カウントの動的な調整はサポートされません。
omp_set_dynamic
を 0 以外の値で使用しようとしても,実行時環境には何も作用しません。
for または parallel for ループにスケジュール句が含まれていない場合,スケジュール・タイプには DYNAMIC が使用され,チャンクサイズは 1 に設定されます。
flush
指示文は,指示文に 1 つまたは複数の変数が指定されていても,すべての変数をフラッシュします。
以下の節には,OpenMP アプリケーション・プログラミング・インタフェース (API) を使用するアプリケーションの動作を診断し,デバッグする方法についてのヒントを示します。
13.6.1 デバッグに必要な背景知識
-mp または -omp オプションを使用すると,コンパイラは OpenMP 指示文を認識し,コードの指定された部分を並列処理リージョンに変換します。 コンパイラは,リージョン内のコードを取り出し,それをコンパイラが作成した別のルーチンに入れることで,並列処理リージョンを実現します。 この処理は,ルーチンが呼び出された所でソース・コードをルーチンに入れるインライン化の逆なので,アウトライン化と呼ばれます。
注意
デバッガと他のアプリケーション分析ツールを効率良く使用するためには,並列処理リージョンをアウトライン化する方法を理解しなければなりません。
並列処理リージョンの場所に,コンパイラは実行時ライブラリ・ルーチンへの呼び出しを挿入します。 実行時ライブラリ・ルーチンは,チームの中にスレーブ・スレッドを作成し (まだ作成されていない場合),チーム内のすべてのスレッドを開始し,アウトライン・ルーチンを呼び出します。 アウトライン・ルーチンからスレッドが戻ると,スレッドは実行時ライブラリに戻ります。 ライブラリはすべてのスレッドが完了するまで待ち,その後マスタ・スレッドが呼び出し元のルーチンに戻ります。 マスタ・スレッドが非並列実行を継続している間,スレーブ・スレッドは,新しい並列処理リージョンに遭遇するか,または環境変数によって決まる待ち時間 (MP_SPIN_COUNT) が経過するまで待機 (つまりスピン) します。 待ち時間が経過すると,スレーブ・スレッドは次に並列処理リージョンに遭遇するまでスリープ状態になります。
次のソース・コードに含まれる並列処理リージョンでは,変数
id
は各スレッドにプライベートです。
並列処理リージョンの前にあるコードは,並列処理リージョンで使用するスレッドの数を明示的に 2 としています。
次に,並列処理リージョンは,実行しているスレッドのスレッド番号を取得し,それを
printf
文で表示します。
1
2 main()
3 {
4 int id;
5 omp_set_num_threads(2);
6 # pragma omp parallel private (id)
7 {
8 id= omp_get_thread_num();
9 printf ("Hello World from OpenMP Thread %d\n", id);
10 }
11 }
dis
コマンドを用いて,上記のソース・コードから生成されたオブジェクト・モジュールを逆アセンブルすると,次のような結果が出力されます。
_ _main_6: [1]
0x0: 27bb0001 ldah gp, 1(t12)
0x4: 2ffe0000 ldq_u zero, 0(sp)
0x8: 23bd8110 lda gp, -32496(gp)
0xc: 2ffe0000 ldq_u zero, 0(sp)
0x10: 23defff0 lda sp, -16(sp)
0x14: b75e0000 stq ra, 0(sp)
0x18: a2310020 ldl a1, 32(a1)
0x1c: f620000e bne a1, 0x58
0x20: a77d8038 ldq t12, -32712(gp)
0x24: 6b5b4000 jsr ra, (t12), omp_get_thread_num
0x28: 27ba0001 ldah gp, 1(ra)
0x2c: 47e00411 bis zero, v0, a1
0x30: 23bd80e8 lda gp, -32536(gp)
0x34: a77d8028 ldq t12, -32728(gp)
0x38: a61d8030 ldq a0, -32720(gp)
0x3c: 6b5b4000 jsr ra, (t12), printf
0x40: 27ba0001 ldah gp, 1(ra)
0x44: 23bd80d0 lda gp, -32560(gp)
0x48: a75e0000 ldq ra, 0(sp)
0x4c: 63ff0000 trapb 0x50: 23de0010 lda sp, 16(sp)
0x54: 6bfa8001 ret zero, (ra), 1
0x58: 221ffff4 lda a0, -12(zero)
0x5c: 000000aa call_pal gentrap
0x60: c3ffffef br zero, 0x20
0x64: 2ffe0000 ldq_u zero, 0(sp)
0x68: 2ffe0000 ldq_u zero, 0(sp)
0x6c: 2ffe0000 ldq_u zero, 0(sp)
main:
0x70: 27bb0001 ldah gp, 1(t12)
0x74: 2ffe0000 ldq_u zero, 0(sp)
0x78: 23bd80a0 lda gp, -32608(gp)
0x7c: 2ffe0000 ldq_u zero, 0(sp)
0x80: a77d8020 ldq t12, -32736(gp)
0x84: 23defff0 lda sp, -16(sp)
0x88: b75e0000 stq ra, 0(sp)
0x8c: 47e05410 bis zero, 0x2, a0
0x90: 6b5b4000 jsr ra, (t12), omp_set_num_threads
0x94: 27ba0001 ldah gp, 1(ra)
0x98: 47fe0411 bis zero, sp, a1
0x9c: 2ffe0000 ldq_u zero, 0(sp)
0xa0: 23bd807c lda gp, -32644(gp)
0xa4: 47ff0412 bis zero, zero, a2
0xa8: a77d8010 ldq t12, -32752(gp)
0xac: a61d8018 ldq a0, -32744(gp)
0xb0: 6b5b4000 jsr ra, (t12), _OtsEnterParallelOpenMP [2]
0xb4: 27ba0001 ldah gp, 1(ra) : a75e0000 ldq ra,
0(sp)
0xbc: 2ffe0000 ldq_u zero, 0(sp)
0xc0: 23bd805c lda gp, -32676(gp)
0xc4: 47ff0400 bis zero, zero, v0
0xc8: 23de0010 lda sp, 16(sp)
0xcc: 6bfa8001 ret zero, (ra), 1
_ _main_6
は,リストの 6 行目の,ルーチン main で始まる並列処理リージョンに対して,コンパイラが作成したアウトライン・ルーチンです。
コンパイラが生成するアウトライン・ルーチンの名前は,次のような形式になっています。
_ _original-routine-name
[例に戻る]_listing-line-number
_OtsEnterParallelOpenMP
への呼び出しがコンパイラによって挿入され,スレッド作成と並列処理リージョンの実行の整合がとられます。
実行の制御は,すべてのスレッドが並列処理リージョンを終了するまで,_OtsEnterParallelOpenMP
の内部に留まります。
[例に戻る]
OpenMP アプリケーションをデバッグするための主要なツールは Ladebug デバッガです。
その他のツールには,Visual Threads,Atom ツールの
pixie
と
third,および OpenMP ツール
ompc
があります。
13.6.2.1 Ladebug
この項では,OpenMP アプリケーションで Ladebug デバッガを使用する方法について説明します。 ここでは,従来のマルチスレッド・アプリケーションと比較して,OpenMP アプリケーションに特有の事項について説明します。 13.6.1 項 でのプログラム例を使用して,OpenMP アプリケーションのデバッグのコンセプトを示します。 マルチスレッド・プログラムのデバッグについての詳細は,『Ladebug Debugger Manual』 を参照してください。
OpenMP アプリケーションはマルチスレッドなので,通常のマルチスレッド・プログラムの場合と同じ方法でデバッグできます。 ただし,考慮すべきことがいくつかあります。
最適化されたコードでは,コンパイラはソース・モジュールを変更して OpenMP をサポートできるようにしています。 したがって,デバッガに表示されるソース・モジュールでは,プログラムの実際の実行が反映されません。 たとえば,コンパイラが実行するアウトライン化処理で生成されるルーチンは,独立したルーチンとしては表示されません。 デバッグ・セッションの前には,出力リストまたはオブジェクト・モジュールの逆アセンブルにより,これらのルーチンの名前がわかります。 これらのルーチンは,通常のルーチンと同じように Ladebug セッションで分析できます。
OpenMP 標準では,スレッド 0 (マスタ・スレッド) から始まるスレッド番号を定義しています。
Ladebug は OpenMP のスレッド番号は扱いません。
代りに,番号が 1 から始まる
pthreads
でのスレッド番号を扱います。
OpenMP スレーブ・スレッドの呼び出しスタックは,thdBase
という
pthreads
ライブラリ・ルーチンから始まり,slave_main
という
libots3
のルーチンまで続きます。
並列処理リージョンにプライベートな変数は,各スレッドにプライベートです。
明らかにプライベートな変数 (firstprivate,lastprivate,private
または
reduction
で修飾) には,スレッドごとに異なるメモリ位置があります。
並列処理リージョンをデバッグする場合,アウトライン・ルーチン名にブレークポイントを設定します。 次の例は,Ladebug セッションの開始,並列処理リージョンへのブレークポイントの設定,実行の継続を示しています。 ユーザ・コマンドは脚注で説明しています。
> ladebug example [1]
Welcome to the Ladebug Debugger Version 4.0-48
------------------
object file name: example
Reading symbolic information ...done
(ladebug) stop in _ _main_6 [2]
[#1: stop in void _ _main_6(int, int) ]
(ladebug) run [3]
[1] stopped at [void _ _main_6(int, int):6 0x1200014e0]
6 # pragma omp parallel private (id)
(ladebug) thread [4]
Thread Name State Substate Policy Pri
------ --------------- ------------ ----------- ------------ ---
>*> 1 default thread running SCHED_OTHER 19
(ladebug) cont [5]
Hello World from OpenMP Thread 0
[1] stopped at [void _ _main_6(int, int):6 0x1200014e0]
6 # pragma omp parallel private (id)
(ladebug) thread [6]
Thread Name State Substate Policy Pri
------ --------------- ------------ ----------- ------------ ---
>* 2 <anonymous> running SCHED_OTHER 19
(ladebug) cont [7]
Hello World from OpenMP Thread 1
Process has exited with status 0
例のアプリケーションを指定して Ladebug セッションを開始します。 [例に戻る]
アウトライン・ルーチン
_ _main_6
の開始点で止めるためにブレークポイントを設定します。
[例に戻る]
プログラムを起動します。
_ _main_6
の先頭で制御が止まります。
[例に戻る]
並列処理リージョンをアクティブに実行しているスレッドを表示します (この例では pthread 1,OpenMP スレッド 0)。 [例に戻る]
この地点から実行を継続し,再びブレークポイントで止まる前に,OpenMP スレッド 0 の並列処理リージョンが終了して,適切な OpenMP スレッド番号で「Hello World」というメッセージが出力されることを確認します。
[例に戻る]
並列処理リージョンをアクティブに実行している次のスレッドを表示します (pthread 2,OpenMP スレッド 1)。 [例に戻る]
この地点から実行を継続すると,次のメッセージが出力され,プログラムの実行が終了します。 [例に戻る]
次の例では,pthread 2 (OpenMP スレッド 1) が並列処理リージョンの実行を開始したときに,アウトライン・ルーチンの先頭にブレークポイントを設定する方法を示します。
> ladebug example
Welcome to the Ladebug Debugger Version 4.0-48
------------------
object file name: example
Reading symbolic information ...done
(ladebug) stop thread 2 in _ _main_6 [1]
[#1: stop thread (2) in void _ _main_6(int, int) ]
(ladebug) r
Hello World from OpenMP Thread 0
[1] stopped at [void _ _main_6(int, int):6 0x1200014e0]
6 # pragma omp parallel private (id)
(ladebug) thread
Thread Name State Substate Policy Pri
------ ---------------- ------------ ----------- ------------ ---
>* 2 <anonymous> running SCHED_OTHER 19
(ladebug) c
Hello World from OpenMP Thread 1
Process has exited with status 0
並列処理リージョンの開始点で OpenMP スレッド 1 (pthread 2) を止めます。 [例に戻る]
OpenMP 組込みのワーク・シェアリング構造 (for
および
sections
指示文) のデバッグは,前の例と同じように行います。
注意
Ladebug デバッガは,OpenMP デバッグをまだ完全にはサポートしていません。
threadprivateとして宣言された変数は,Ladebug では認識されず,表示できません。
OpenMP が組み込まれたプログラムは,Compaq Visual Threads (dxthreads) 製品でモニタリングできます。
この製品は,「Associated Products Volume 1」CD-ROM にあります。
詳細は,Visual Threads のオンライン・ヘルプを参照してください。
13.6.2.3 Atom および OpenMP ツール
OpenMP アプリケーションは,OpenMP アプリケーションをモニタリングするために作成された特殊なツールの
ompc,Atom ベースのツール
pixie
(実行のプロファイル用),Third Degree (メモリ・アクセスとリークをモニタリングする
third) を用いて計測できます。
ompc
ツールは,関連する環境変数設定をキャプチャし,OpenMP に関する実行時ライブラリ・ルーチンの呼び出しをカウントします。
開発者の意図しない状況では,警告およびエラー・メッセージを生成して注意を促します。
最後に,環境変数の設定に基づいて,これらの実行時ライブラリ・ルーチンへの呼び出しをすべてトレースし,ルーチンが呼び出された順番を (OpenMP スレッド番号で) 通知します。
詳細は
ompc(5)
Atom ベースの
pixie
ツールは,アプリケーションでの効率の良くないスレッド使用を検出するために使用します。
13.6.1 項
で説明したように,スレーブ・スレッドは,新しい並列処理リージョンの実行が始まるか,または MP_SPIN_COUNT が経過するまで待機 (つまりスピン) します。
アプリケーションの並列処理リージョン間の時間が長い場合,スレッドはスリープ状態になるまでスピンします。
pixie でアプリケーションを計測すると,アプリケーションがどこで多くの時間を費やしているかを確認できます。
アプリケーションが slave_main で CPU 時間を大量に費やしている場合は,スレッドがスピンに費やす時間が長すぎることを示しています。
このようなアプリケーションでは,MP_SPIN_COUNT の値 (省略時の値は 16000000) を小さくすると,全体の性能が良くなります。
pixie
についての詳細は,第 8 章
と
pixie(1)
Third Degree ツールについては,第 7 章
と
third(1)13.6.2.4 その他のデバッグ支援機能
その他のデバッグ支援機能には,次のようなものがあります。
コンパイル時オプションの -check_omp。 デッドロックや競合条件を検出するための実行時チェックが組み込まれる (13.1 節 を参照)。
プログラム内のアクティブなスレッド数を変更可能にする
omp_set_num_threads
および
mpc_destroy
関数。
omp_set_num_threads
または
mpc_destroy
を呼び出すと,プログラム内でアクティブなスレッドの数を変更できます。
いずれの場合も,threadprivate
で宣言されたデータや,スレーブ・スレッドに関係するデータは,アプリケーションの起動時の値で再度初期化されます。
たとえば,アクティブなスレッドの数が 4 のときに,omp_set_num_threads
を呼び出してこの数を 2 に設定すると,OpenMP スレッドの 1,2,3 に対応する
threadprivate
データがリセットされます。
マスタ・スレッド (OpenMP スレッド 0) に対応するthreadprivate
データは変更されません。
mpc_destroy
についての詳細は,13.3.2 項
を参照してください。