OpenMP* のクリティカル・セクションを使用して、複数のスレッドがクリティカルなコード領域を同時に実行するのを防止し、1 つのアクティブなスレッドのみがコードで参照されているデータを更新します。クリティカル・セクションは、入れ子ではないミューテックスに適しています。
単一操作に対する細粒度の同期を提供する OpenMP* のアトミック操作とは異なり、クリティカル・セクションは複数操作に対する粗粒度の同期を提供します。
次を使用します。
#pragma omp critical を使用します。Fortran では、
!$omp criticalと!$omp end criticalを使用します。
オプションの(name)が省略されると、単一の名前なしグローバル・ミューテックスをロックします。共有ミューテックスによりパフォーマンスが大幅に低下しない場合、最も簡単なアプローチは名前なしの形式を使用することです。
例えば、次のアノテーション付きの C/C++ シリアルプログラムについて考えてみます。
int count;
void Tick() {
ANNOTATE_LOCK_ACQUIRE(0);
count++;
ANNOTATE_LOCK_RELEASE(0);
}..次に、#include <omp.h> と #pragma omp critical を追加した C/C++ 並列コード:
#include <omp.h> // .dll を検出できないロード時の問題を解決します
int count;
void Tick() {
// ロック・アノテーションと入れ替えます
#pragma omp critical
count++;
}
..次のようなアノテーション付きの Fortran シリアルコードについて考えてみます。
program ABC
integer(kind=4) :: count = 0.contains
subroutine Tick
call annotate_lock_acquire(0)
count = count + 1
call annotate_lock_release(0)
end subroutine Tick.end program ABC次に、use omp_lib、!$omp critical および!$omp end criticalを追加した Fortran 並列コード:
program ABC
use omp_lib
integer(kind=4) :: count = 0...contains subroutine Tick
!$omp critical
count = count + 1
!$omp end critical
end subroutine Tick
..
..
end program ABC