Директива оформляет критическую секцию (участок) программы. В каждый момент времени в критической секции может выполняться не более одной нити. Очередность выполнения критических участков различными нитями определяется порядком достижения участка нитями. Недопустимо переходить внутрь или выходить из критического участка операторами перехода. Критический участок может быть поименован. Может существовать несколько участков с различными именами. Участки, имеющие одинаковые имена, трактуются как один участок, так же как и несколько не именованных участков. В языке Фортран имена критических участков рассматриваются как глобальные объекты программы и могут конфликтовать с именами других объектов.
C/C++:
#pragma omp critical [ ( name ) ] new-line
structured-block
Fortran:
!$OMP CRITICAL [ ( name ) ]
block
!$OMP END CRITICAL [ ( name ) ]
Директива CRITICAL применяется в тех случаях, когда параллельное выполнение кода несколькими нитями может приводить к неоднозначности результата. Приведем пример программы, иллюстрирующей действие директивы CRITICAL.
Программа critical.c
#include <stdio.h> #include <stdlib.h> #include <omp.h> #define SIZE 1000 int main() { int i; int b; int max; int a[SIZE]; for (i = 0; i < SIZE; i++) { a[i] = i; } max = a[0]; #pragma omp parallel num_threads(4) { #pragma omp single { printf("Num threads=%d\n",omp_get_num_threads()); } #pragma omp for for (i = 1; i < SIZE; i++) { #pragma omp critical { b=a[i]+4*a[i]; if (a[i] > max) max = a[i]; } } } printf("max = %d\n", max); return 0; }
Программа critical.f
program critical integer i,n,b,max,a(1000), omp_get_num_threads n = 1000 do i = 1,n a(i) = i end do max = a(1) !$OMP PARALLEL NUM_THREADS(4) !$OMP SINGLE print *, 'Num threads = ', omp_get_num_threads() !$OMP END SINGLE !$OMP DO do i = 1,n !$OMP CRITICAL b = a(i) + 4 * a(i) if ( a(i).gt.max) max = a(i) !$OMP END CRITICAL end do !$OMP END DO !$OMP END PARALLEL print *, 'Max = ', max end