Самая важная и распространенная директива в OpenMP.
Назначение:
- Cоздает параллельный регион для следующего за ней структурированного блока.
Формат:
#pragma omp parallel [clause...] newline if (scalar_expression) private (list) shared (list) default (shared | none) firstprivate (list) reduction (operator: list) copyin (list) num_threads (integer-expression) structured_blockОсобенности:
- Когда основной (последовательный) поток достигает директивы, он порождает набор нитей и становится основной нитью в этом наборе, которой присваивается индекс 0.
- Начиная с начала региона, код дублируется, и все нити выполняют один и тот же код.
- В конце секции предполагается барьер синхронизации. После выхода из региона мастер продолжает работу.
Ограничения:
- Запрещены любые переходы в/из параллельного региона
Директива сообщает компилятору, что структурированный блок кода должен быть выполнен параллельно, в нескольких потоках-нитях.
Процесс, выполнивший данную директиву (нить-мастер), всегда получает номер 0.
Каждый поток будет выполнять один и тот же поток команд, но не один и тот же набор команд — все зависит от операторов, управляющих логикой программы, таких как if-else.
|
|
Необходимость порождения нитей и параллельного исполнения кода параллельной секции пользователь может определять динамически с помощью дополнительной опции if.
#pragma omp parallel if ( <условие> )Если <условие> не выполнено, то директива не срабатывает и продолжается обработка программы в прежнем режиме.
Параметр num_threads указывает на число создаваемых нитей, участвующих в параллельной обработке. По умолчанию число нитей равно числу логических процессоров на машине.
Для распределения работы между нитями OpenMP дает возможность программировать на самом низком уровне, распределяя работу с помощью функций omp_get_thread_num() и omp_get_num_threads(), возвращающих номер нити и общее количество порожденных нитей соответственно. Например, если написать фрагмент вида:
if(omp_get_thread_num() == 3)
{
< код для нити с номером 3 >
}
else
{
< код для всех остальных нитей >
}
то часть программы между директивами if:else будет выполнена только нитью с номером 3, а оставшаяся часть - всеми остальными. Как и прежде, этот код будет выполнен всеми нитями, однако функция omp_get_thread_num() возвратит значение 3 только для нити с номером 3, поэтому и выполнение данного участка кода для третьей нити и всех остальных будет идти по-разному.