Параллельное программирование с использованием OpenMP. Антонов (2009) (Параллельное программирование с использованием OpenMP. Антонов (2009).pdf), страница 5
Описание файла
PDF-файл из архива "Параллельное программирование с использованием OpenMP. Антонов (2009).pdf", который расположен в категории "". Всё это находится в предмете "суперкомпьютерное моделирование и технологии" из 11 семестр (3 семестр магистратуры), которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 5 страницы из PDF
Опция copyprivate на языке Си.!$omp!$omp!$omp!$ompprogram example10binclude "omp_lib.h"integer nparallel private(n)n=omp_get_thread_num()print *, "Значение n (начало): ", nsinglen=100;end single copyprivate(n)print *, "Значение n (конец): ", nend parallelendПример 10b. Опция copyprivate на языке Фортран.26Директива masterДирективы master (master ... end master) выделяют участок кода, который будет выполнен только нитью-мастером. Остальные нити просто пропускают данный участок и продолжают работу с оператора, расположенногоследом за ним.
Неявной синхронизации данная директива не предполагает.Си:#pragma omp masterФортран:!$omp master<код для нити-мастера>!$omp end masterПример 11 демонстрирует применение директивы master. Переменная n является локальной, то есть каждая нить работает со своим экземпляром. Сначала все нити присвоят переменной n значение 1. Потом нить-мастер присвоит переменной n значение 2, и все нити напечатают значение n. Затем нитьмастер присвоит переменной n значение 3, и снова все нити напечатают значение n.
Видно, что директиву master всегда выполняет одна и та же нить. Вданном примере все нити выведут значение 1, а нить-мастер сначала выведетзначение 2, а потом - значение 3.#include <stdio.h>int main(int argc, char *argv[]){int n;#pragma omp parallel private(n){n=1;#pragma omp master{n=2;}printf("Первое значение n: %d\n", n);#pragma omp barrier#pragma omp master{n=3;}printf("Второе значение n: %d\n", n);}}Пример 11a. Директива master на языке Си.27!$omp!$omp!$omp!$omp!$omp!$omp!$ompprogram example11binteger nparallel private(n)n=1mastern=2end masterprint *, "Первое значение n: ", nbarriermastern=3;end masterprint *, "Второе значение n: ", nend parallelendПример 11b. Директива master на языке Фортран.Задания• Определите, какое максимальное количество нитей позволяет породитьдля выполнения параллельных областей программы ваша система.• В каких случаях может быть необходимо использование опции if директивы parallel?• Определите, сколько процессоров доступно в вашей системе для выполнения параллельной части программы, и займите каждый из доступных процессоров выполнением одной нити в рамках общей параллельной области.• При помощи трёх уровней вложенных параллельных областей породите 8 нитей (на каждом уровне параллельную область должны исполнять 2 нити).
Посмотрите, как будет исполняться программа, если запретить вложенные параллельные области.• Чем отличаются директивы single и master?• Может ли нить-мастер выполнить область, ассоциированную с директивой single?• Может ли нить с номером 1 выполнить область, ассоциированную сдирективой master?28Модель данныхМодель данных в OpenMP предполагает наличие как общей для всех нитейобласти памяти, так и локальной области памяти для каждой нити.В OpenMP переменные в параллельных областях программы разделяются надва основных класса:• shared (общие; все нити видят одну и ту же переменную);• private (локальные, приватные; каждая нить видит свой экземплярданной переменной).Общая переменная всегда существует лишь в одном экземпляре для всей области действия и доступна всем нитям под одним и тем же именем.
Объявление локальной переменной вызывает порождение своего экземпляра даннойпеременной (того же типа и размера) для каждой нити. Изменение нитьюзначения своей локальной переменной никак не влияет на изменение значения этой же локальной переменной в других нитях.Если несколько переменных одновременно записывают значение общей переменной без выполнения синхронизации или если как минимум одна нитьчитает значение общей переменной и как минимум одна нить записываетзначение этой переменной без выполнения синхронизации, то возникает ситуация так называемой «гонки данных» (data race), при которой результатвыполнения программы непредсказуем.По умолчанию, все переменные, порождённые вне параллельной области,при входе в эту область остаются общими (shared).
Исключение составляютпеременные, являющиеся счетчиками итераций в цикле, по очевидным причинам. Переменные, порождённые внутри параллельной области, по умолчанию являются локальными (private). Явно назначить класс переменных поумолчанию можно с помощью опции default. Не рекомендуется постояннополагаться на правила по умолчанию, для большей надёжности лучше всегдаявно описывать классы используемых переменных, указывая в директивахOpenMP опции private, shared, firstprivate, lastprivate, reduction.Пример 12 демонстрирует использование опции private.
В данном примерепеременная n объявлена как локальная переменная в параллельной области.Это значит, что каждая нить будет работать со своей копией переменной n,при этом в начале параллельной области на каждой нити переменная n не будет инициализирована. В ходе выполнения программы значение переменнойn будет выведено в четырёх разных местах. Первый раз значение n будет выведено в последовательной области, сразу после присваивания переменной n29значения 1. Второй раз все нити выведут значение своей копии переменной nв начале параллельной области, неинициализированное значение может зависеть от реализации. Далее все нити выведут свой порядковый номер, полученный с помощью функции omp_get_thread_num() и присвоенный переменной n.
После завершения параллельной области будет ещё раз выведенозначение переменной n, которое окажется равным 1 (не изменилось во времявыполнения параллельной области).#include <stdio.h>#include <omp.h>int main(int argc, char *argv[]){int n=1;printf("n в последовательной области (начало): %d\n", n);#pragma omp parallel private(n){printf("Значение n на нити (на входе): %d\n", n);/* Присвоим переменной n номер текущей нити */n=omp_get_thread_num();printf("Значение n на нити (на выходе): %d\n", n);}printf("n в последовательной области (конец): %d\n", n);}Пример 12a.
Опция private на языке Си.program example12binclude "omp_lib.h"integer nn=1print *, "n в последовательной области (начало): ", n!$omp parallel private(n)print *, "Значение n на нити (на входе): ", nC Присвоим переменной n номер текущей нитиn=omp_get_thread_num()print *, "Значение n на нити (на выходе): ", n!$omp end parallelprint *, "n в последовательной области (конец): ", nendПример 12b. Опция private на языке Фортран.Пример 13 демонстрирует использование опции shared. Массив m объявленобщим для всех нитей. В начале последовательной области массив m заполняется нулями и выводится на печать.
В параллельной области каждая нитьнаходит элемент, номер которого совпадает с порядковым номером нити вобщем массиве, и присваивает этому элементу значение 1. Далее, в последовательной области печатается изменённый массив m.30#include <stdio.h>#include <omp.h>int main(int argc, char *argv[]){int i, m[10];printf("Массив m в начале:\n");/* Заполним массив m нулями и напечатаем его */for (i=0; i<10; i++){m[i]=0;printf("%d\n", m[i]);}#pragma omp parallel shared(m){/* Присвоим 1 элементу массива m, номер которогосовпадает с номером текущий нити */m[omp_get_thread_num()]=1;}/* Ещё раз напечатаем массив */printf("Массив m в конце:\n");for (i=0; i<10; i++) printf("%d\n", m[i]);}Пример 13a.
Опция shared на языке Си.program example13binclude "omp_lib.h"integer i, m(10)print *, "Массив m в начале:"C Заполним массив m нулями и напечатаем егоdo i=1, 10m(i)=0print *, m(i)end do!$omp parallel shared(m)C Присвоим 1 элементу массива m, номер которогоC совпадает с номером текущий нитиm(omp_get_thread_num()+1)=1!$omp end parallelC Ещё раз напечатаем массив */print *, "Массив m в конце:"do i=1, 10print *, m(i)end doendПример 13b. Опция shared на языке Фортран.В языке Си статические (static) переменные, опредёленные в параллельнойобласти программы, являются общими (shared). Динамически выделеннаяпамять также является общей, однако указатель на неё может быть как общим, так и локальным.31В языке Фортран по умолчанию общими (shared) являются элементыCOMMON-блоков.Отдельные правила определяют назначение классов переменных при входе ивыходе из параллельной области или параллельного цикла при использовании опций reduction, firstprivate, lastprivate, copyin.Пример 14 демонстрирует использование опции firstprivate.
Переменнаяn объявлена как firstprivate в параллельной области. Значение n будетвыведено в четырёх разных местах. Первый раз значение n будет выведено впоследовательной области сразу после инициализации. Второй раз все нитивыведут значение своей копии переменной n в начале параллельной области,и это значение будет равно 1. Далее, с помощью функцииomp_get_thread_num() все нити присвоят переменной n свой порядковыйномер и ещё раз выведут значение n. В последовательной области будет ещёраз выведено значение n, которое снова окажется равным 1.#include <stdio.h>#include <omp.h>int main(int argc, char *argv[]){int n=1;printf("Значение n в начале: %d\n", n);#pragma omp parallel firstprivate(n){printf("Значение n на нити (на входе): %d\n", n);/* Присвоим переменной n номер текущей нити */n=omp_get_thread_num();printf("Значение n на нити (на выходе): %d\n", n);}printf("Значение n в конце: %d\n", n);}Пример 14a. Опция firstprivate на языке Си.program example14binclude "omp_lib.h"integer nn=1print *, "Значение n в начале: ", n!$omp parallel firstprivate(n)print *, "Значение n на нити (на входе): ", nC Присвоим переменной n номер текущей нитиn=omp_get_thread_num()print *, "Значение n на нити (на выходе): ", n!$omp end parallelprint *, "Значение n в конце: ", nendПример 14b.
Опция firstprivate на языке Фортран.32Директива threadprivate указывает, что переменные из списка должныбыть размножены с тем, чтобы каждая нить имела свою локальную копию.Си:#pragma omp threadprivate(список)Фортран:!$omp threadprivate(список)Директива threadprivate может позволить сделать локальные копии длястатических переменных языка Си и COMMON-блоков языка Фортран, которые по умолчанию являются общими. Для корректного использования локальных копий глобальных объектов нужно гарантировать, что они используются в разных частях программы одними и теми же нитями.