C/C++:
#pragma omp parallel [ ключ [ ключ ] ... ] new-line
structured-block
Fortran:
!$OMP PARALLEL [ ключ [ [ , ] ключ ] ... ]
Фрагмент программы
!$OMP END PARALLEL
Директивы PARALLEL/END PARALLEL должны находиться внутри одной процедуры
В языках C/C++ не требуется завершающего оператора, поскольку эти языки поддерживают блочную структуру и директива относится к блоку.
Ключи определяют типы переменных и их поведение при входе в параллельную область и выходе из нее.
Возможные ключи:
IF (условие) - Выполнение параллельной области по условию. Вхождение в параллельную область происходит только, если условие принимает значение <Истина>.
SHARED (список) - Явным образом определяет список переменных, которые должны быть общими для всех нитей параллельной области.
PRIVATE (список) - Определяет список переменных, которые должны быть локальными для каждой нити. При входе в параллельную область для каждой нити создается отдельный экземпляр переменной, который не имеет никакой связи с оригинальной переменной вне параллельной области. Изменение значения локальной переменной какой-либо нитью ни как не влияет на значения этой переменной в других нитях.
FIRSTPRIVATE (список) - Список локальных переменных, которые при входе в параллельную область наследуют значение оригинальных переменных.
DEFAULT (PRIVATE|FIRSPRIVATE|SHARED|NONE) - Всем переменным в параллельной области, которым явно не назначен класс, будет назначен класс PRIVATE, FIRSTPRIVATE или SHARED соответственно. Значение NONE указывает, что значение по умолчанию ни каким переменным не устанавливается. В языках C/C++ допустимы только значения SHARED или NONE.
REDUCTION(операция: список) - Операция редукции производится над копиями переменных во всех нитях, и результат присваивается базовой переменной.
Допустимые операции:
C/C++:
+, *, -, &, ^, |, &&, or, ||
Fortran:
+, *, -, .and., .or., .eqv., .neqv.,max, min, iand, ior, ieor
COPYIN (список) - Применяется к глобальным переменным в С/С++ и COMMON-блокам в Фортране, которые помечены как THREADPRIVATE. При входе в параллельную область приватные копии этих данных инициируются оригинальными значениями.
NUM_THREADS (целочисленное выражение) задание количества нитей, порождаемых в параллельной области. По умолчанию выбирается последнее значение, установленное с помощью функции omp_set_num_threads(), или значение переменной OMP_NUM_THREADS.
Приведем пример простейшей параллельной программы на языках Си и Фортран.
Программа parallel.c
#include <omp.h> main () { int nthreads, tid; /* Генерация ансамбля нитей */ #pragma omp parallel private(tid) { /* получение и печать идентификаторов нитей */ tid = omp_get_thread_num(); printf("Hello World from thread = %d\n", tid); /* определение мастер-нитью общего числа нитей */ if (tid == 0) { nthreads = omp_get_num_threads(); printf("Number of threads = %d\n", nthreads); } } /* Закрытие всех нитей, кроме мастер-нити */ }
Программа parallel.f
PROGRAM PARALLEL INTEGER NTHREADS, TID, OMP_GET_NUM_THREADS, + OMP_GET_THREAD_NUM C Генерация ансамбля нитей !$OMP PARALLEL PRIVATE(TID) C получение и печать идентификаторов нитей TID = OMP_GET_THREAD_NUM() PRINT *, 'Hello World from thread = ', TID C определение мастер-нитью общего числа нитей IF (TID .EQ. 0) THEN NTHREADS = OMP_GET_NUM_THREADS() PRINT *, 'Number of threads = ', NTHREADS END IF C Закрытие всех нитей, кроме мастер-нити !$OMP END PARALLEL END
Создание параллельных областей само по себе не приводит к ускорению работы программы, Каждая нить будет выполнять одну и ту же последовательность команд. Для распределения работы между нитями служат специальные директивы.
В OpenMP имеется несколько возможностей по распределению вычислений между нитями.