Вперед: 3.2.8. Директива ATOMIC
Назад: 3.2.6. Выполнение кода только главной нитью, директива MASTER
К содержанию: Оглавление


3.2.7. Последовательное выполнение кода, директива CRITICAL

Директива оформляет критическую секцию (участок) программы. В каждый момент времени в критической секции может выполняться не более одной нити. Очередность выполнения критических участков различными нитями определяется порядком достижения участка нитями. Недопустимо переходить внутрь или выходить из критического участка операторами перехода. Критический участок может быть поименован. Может существовать несколько участков с различными именами. Участки, имеющие одинаковые имена, трактуются как один участок, так же как и несколько не именованных участков. В языке Фортран имена критических участков рассматриваются как глобальные объекты программы и могут конфликтовать с именами других объектов.

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
 


Вперед: 3.2.8. Директива ATOMIC
Назад: 3.2.6. Выполнение кода только главной нитью, директива MASTER
К содержанию: Оглавление