Параллельное программирование с использованием OpenMP. Антонов (2009) (Параллельное программирование с использованием OpenMP. Антонов (2009).pdf), страница 4
Описание файла
PDF-файл из архива "Параллельное программирование с использованием OpenMP. Антонов (2009).pdf", который расположен в категории "". Всё это находится в предмете "суперкомпьютерное моделирование и технологии" из 11 семестр (3 семестр магистратуры), которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 4 страницы из PDF
Директива master позволяет обеспечить печать толькопроцессом-мастером. В системах с динамическим изменением числа нитейвыданное значение может отличаться от заданного (128).19#include <stdio.h>#include <omp.h>int main(int argc, char *argv[]){printf("Значение OMP_DYNAMIC: %d\n", omp_get_dynamic());omp_set_dynamic(1);printf("Значение OMP_DYNAMIC: %d\n", omp_get_dynamic());#pragma omp parallel num_threads(128){#pragma omp master{printf("Параллельная область, %d нитей\n",omp_get_num_threads());}}}Пример 6a. Функции omp_set_dynamic() и omp_get_dynamic() на языке Си.program example6binclude "omp_lib.h"print *, "Значение OMP_DYNAMIC: ", omp_get_dynamic()call omp_set_dynamic(.TRUE.)print *, "Значение OMP_DYNAMIC: ", omp_get_dynamic()!$omp parallel num_threads(128)!$omp masterprint *, "Параллельная область,", omp_get_num_threads(),&" нитей"!$omp end master!$omp end parallelendПример 6b.
Функции omp_set_dynamic() и omp_get_dynamic() на языке Фортран.Функция omp_get_max_threads() возвращает максимально допустимое число нитей для использования в следующей параллельной области.Си:int omp_get_max_threads(void);Фортран:integer function omp_get_max_threads()Функция omp_get_num_procs() возвращает количество процессоров, доступных для использования программе пользователя на момент вызова.
Нужно учитывать, что количество доступных процессоров может динамическиизменяться.Си:int omp_get_num_procs(void);20Фортран:integer function omp_get_num_procs()Параллельные области могут быть вложенными; по умолчанию вложеннаяпараллельная область выполняется одной нитью. Это управляется установкой переменной среды OMP_NESTED. Например, в Linux в командной оболочкеbash разрешить вложенный параллелизм можно при помощи следующей команды:export OMP_NESTED=trueИзменить значение переменной OMP_NESTED можно с помощью вызова функции omp_set_nested().Си:void omp_set_nested(int nested)Фортран:subroutine omp_set_nested(nested)logical nestedФункция omp_set_nested() разрешает или запрещает вложенный параллелизм.
На языке Си в качестве значения параметра задаётся 0 или 1, а на языкеФортран – .FALSE. или .TRUE. Если вложенный параллелизм разрешён, токаждая нить, в которой встретится описание параллельной области, породитдля её выполнения новую группу нитей. Сама породившая нить станет в новой группе нитью-мастером. Если система не поддерживает вложенный параллелизм, данная функция не будет иметь эффекта.Пример 7 демонстрирует использование вложенных параллельных областейи функции omp_set_nested(). Вызов функции omp_set_nested() передпервой частью разрешает использование вложенных параллельных областей.Для определения номера нити в текущей параллельной секции используютсявызовы функции omp_get_thread_num().
Каждая нить внешней параллельной области породит новые нити, каждая из которых напечатает свой номервместе с номером породившей нити. Далее вызов omp_set_nested() запрещает использование вложенных параллельных областей. Во второй частивложенная параллельная область будет выполняться без порождения новыхнитей, что и видно по получаемой выдаче.21#include <stdio.h>#include <omp.h>int main(int argc, char *argv[]){int n;omp_set_nested(1);#pragma omp parallel private(n){n=omp_get_thread_num();#pragma omp parallel{printf("Часть 1, нить %d - %d\n", n,omp_get_thread_num());}}omp_set_nested(0);#pragma omp parallel private(n){n=omp_get_thread_num();#pragma omp parallel{printf("Часть 2, нить %d - %d\n", n,omp_get_thread_num());}}}Пример 7a.
Вложенные параллельные области на языке Си.program example7binclude "omp_lib.h"integer ncall omp_set_nested(.TRUE.)!$omp parallel private(n)n=omp_get_thread_num()!$omp parallelprint *, "Часть 1, нить ", n, " - ",&omp_get_thread_num()!$omp end parallel!$omp end parallelcall omp_set_nested(.FALSE.)!$omp parallel private(n)n=omp_get_thread_num()!$omp parallelprint *, "Часть 2, нить ", n, " - ",&omp_get_thread_num()!$omp end parallel!$omp end parallelendПример 7b. Вложенные параллельные области на языке Фортран.Узнать значение переменной OMP_NESTED можно при помощи функцииomp_get_nested().22Си:int omp_get_nested(void);Фортран:logical function omp_get_nested()Функция omp_in_parallel() возвращает 1 (.TRUE.
для языка Фортран), если она была вызвана из активной параллельной области программы.Си:int omp_in_parallel(void);Фортран:logical function omp_in_parallel()Пример 8 иллюстрирует применение функции omp_in_parallel(). Функцияmode демонстрирует изменение функциональности в зависимости от того,вызвана она из последовательной или из параллельной области.
В последовательной области будет напечатано "Последовательная область", а в параллельной – "Параллельная область".#include <stdio.h>#include <omp.h>void mode(void){if(omp_in_parallel()) printf("Параллельная область\n");else printf("Последовательная область\n");}int main(int argc, char *argv[]){mode();#pragma omp parallel{#pragma omp master{mode();}}}Пример 8a.
Функция omp_in_parallel() на языке Си.23!$omp!$omp!$omp!$ompprogram example8bcall mode()parallelmastercall mode()end masterend parallelendsubroutine mode()include "omp_lib.h"if(omp_in_parallel()) thenprint *, "Параллельная область"elseprint *, "Последовательная область"end ifendПример 8b. Функция omp_in_parallel() на языке Фортран.Директива singleЕсли в параллельной области какой-либо участок кода должен быть выполнен лишь один раз, то его нужно выделить директивами single (single ...end single).Си:#pragma omp single [опция [[,] опция]...]Фортран:!$omp single [опция [[,] опция]...]<код для одной нити>!$omp end single [опция [[,] опция]...]Возможные опции:private(список) – задаёт список переменных, для которых порожда-ется локальная копия в каждой нити; начальное значение локальныхкопий переменных из списка не определено;firstprivate(список) – задаёт список переменных, для которых по-рождается локальная копия в каждой нити; локальные копии переменных инициализируются значениями этих переменных в нити-мастере;copyprivate(список) – после выполнения нити, содержащей конструкцию single, новые значения переменных списка будут доступнывсем одноименным частным переменным (private и firstprivate),описанным в начале параллельной области и используемым всеми еёнитями; опция не может использоваться совместно с опцией nowait;24переменные списка не должны быть перечислены в опциях private иfirstprivate данной директивы single;nowait – после выполнения выделенного участка происходит неявнаябарьерная синхронизация параллельно работающих нитей: их дальнейшее выполнение происходит только тогда, когда все они достигнутданной точки; если в подобной задержке нет необходимости, опцияnowait позволяет нитям, уже дошедшим до конца участка, продолжитьвыполнение без синхронизации с остальными.В программах на языке Си все опции указываются у директивы single, а впрограммах на языке Фортран опции private и firstprivate относятся кдирективе single, а опции copyprivate и nowait – к директиве end single.Какая именно нить будет выполнять выделенный участок программы, неспецифицируется.
Одна нить будет выполнять данный фрагмент, а все остальные нити будут ожидать завершения её работы, если только не указанаопция nowait. Необходимость использования директивы single часто возникает при работе с общими переменными.Пример 9 иллюстрирует применение директивы single вместе с опциейnowait. Сначала все нити напечатают текст "Сообщение 1", при этом однанить (не обязательно нить-мастер) дополнительно напечатает текст "Однанить".
Остальные нити, не дожидаясь завершения выполнения области single, напечатают текст "Сообщение 2". Таким образом, первое появление"Сообщение 2" в выводе может встретиться как до текста "Одна нить", таки после него. Если убрать опцию nowait, то по окончании области singleпроизойдёт барьерная синхронизация, и ни одна выдача "Сообщение 2" неможет появиться до выдачи "Одна нить".#include <stdio.h>int main(int argc, char *argv[]){#pragma omp parallel{printf("Сообщение 1\n");#pragma omp single nowait{printf("Одна нить\n");}printf("Сообщение 2\n");}}Пример 9a. Директива single и опция nowait на языке Си.25!$omp!$omp!$omp!$ompprogram example9bparallelprint *, "Сообщение 1"singleprint *, "Одна нить"end single nowaitprint *, "Сообщение 2"end parallelendПример 9b.
Директива single и опция nowait на языке Фортран.Пример 10 иллюстрирует применение опции copyprivate. В данном примере переменная n объявлена в параллельной области как локальная. Каждаянить присвоит переменной n значение, равное своему порядковому номеру, инапечатает данное значение. В области single одна из нитей присвоит переменной n значение 100, и на выходе из области это значение будет присвоенопеременной n на всех нитях. В конце параллельной области значение n печатается ещё раз и на всех нитях оно равно 100.#include <stdio.h>#include <omp.h>int main(int argc, char *argv[]){int n;#pragma omp parallel private(n){n=omp_get_thread_num();printf("Значение n (начало): %d\n", n);#pragma omp single copyprivate(n){n=100;}printf("Значение n (конец): %d\n", n);}}Пример 10a.