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