2006 Ответы на экзаменационные вопросы по ПОД (Lilalbrother), страница 14
Описание файла
PDF-файл из архива "2006 Ответы на экзаменационные вопросы по ПОД (Lilalbrother)", который расположен в категории "". Всё это находится в предмете "суперкомпьютерное моделирование и технологии" из 11 семестр (3 семестр магистратуры), которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 14 страницы из PDF
Поскольку все основныеконструкции для этих языков похожи, то рассказ о данной технологии мы будем вести напримере только одного из них, а именно на примере языка Фортран.Как, с точки зрения OpenMP, пользователь должен представлять своюпараллельную программу? Весь текст программы разбит на последовательные ипараллельные области (см. рис.1). В начальный момент времени порождается нить-мастерили "основная" нить, которая начинает выполнение программы со стартовой точки. Здесьследует сразу сказать, почему вместо традиционных для параллельногопрограммирования процессов появился новый термин - нити (threads, легковесныепроцессы). Технология OpenMP опирается на понятие общей памяти, поэтому она, взначительной степени, ориентирована на SMP-компьютеры.
На подобных архитектурахвозможна эффективная поддержка нитей, исполняющихся на различных процессорах, чтопозволяет избежать значительных накладных расходов на поддержку классических UNIXпроцессов.Основная нить и только она исполняет все последовательные области программы.При входе в параллельную область порождаются дополнительные нити.
Послепорождения каждая нить получает свой уникальный номер, причем нить-мастер всегдаимеет номер 0. Все нити исполняют один и тот же код, соответствующий параллельнойобласти. При выходе из параллельной области основная нить дожидается завершенияостальных нитей, и дальнейшее выполнение программы продолжает только она.В параллельной области все переменные программы разделяются на два класса:общие (SHARED) и локальные (PRIVATE). Общая переменная всегда существует лишь водном экземпляре для всей программы и доступна всем нитям под одним и тем жеименем. Объявление же локальной переменной вызывает порождение своего экземпляраданной переменной для каждой нити.
Изменение нитью значения своей локальнойпеременной, естественно, никак не влияет на изменение значения этой же локальнойпеременной в других нитях.По сути, только что рассмотренные два понятия: области и классы переменных, иопределяют идею написания параллельной программы в рамках OpenMP: некоторыефрагменты текста программы объявляется параллельными областями; именно эти областии только они исполняются набором нитей, которые могут работать как с общими, так и слокальными переменными. Все остальное - это конкретизация деталей и описаниеособенностей реализации данной идеи на практике.40. OpenMP: основные конструкции для организации параллельных ипоследовательных секций, для распределения работы между нитями.Описание параллельных областей.
Для определения параллельных областейпрограммы используется пара директив!$OMP PARALLEL< параллельный код программы >!$OMP END PARALLELДля выполнения кода, расположенного между данными директивами,дополнительно порождается OMP_NUM_THREADS-1 нитей, где OMP_NUM_THREADS это переменная окружения, значение которой пользователь, вообще говоря, можетизменять. Процесс, выполнивший данную директиву (нить-мастер), всегда получаетномер 0. Все нити исполняют код, заключенный между данными директивами. ПослеEND PARALLEL автоматически происходит неявная синхронизация всех нитей, и кактолько все нити доходят до этой точки, нить-мастер продолжает выполнениепоследующей части программы, а остальные нити уничтожаются.Параллельные секции могут быть вложенными одна в другую.
По умолчаниювложенная параллельная секция исполняется одной нитью. Необходимую стратегиюобработки вложенных секций определяет переменная OMP_NESTED, значение которойможно изменить с помощью функции OMP_SET_NESTED.Если значение переменной OMP_DYNAMIC установлено в 1, то с помощьюфункции OMP_SET_NUM_THREADS пользователь может изменить значение переменнойOMP_NUM_THREADS, а значит и число порождаемых при входе в параллельную секциюнитей. Значение переменной OMP_DYNAMIC контролируется функциейOMP_SET_DYNAMIC.Необходимость порождения нитей и параллельного исполнения кода параллельнойсекции пользователь может определять динамически с помощью дополнительной опцииIF в директиве:!$OMP PARALLEL IF( <условие> )Если <условие> не выполнено, то директива не срабатывает и продолжаетсяобработка программы в прежнем режиме.Мы уже говорили о том, что все порожденные нити исполняют один и тот же код.Теперь нужно обсудить вопрос, как разумным образом распределить между ними работу.OpenMP предлагает несколько вариантов.
Можно программировать на самом низкомуровне, распределяя работу с помощью функций OMP_GET_THREAD_NUM иOMP_GET_NUM_THREADS, возвращающих номер нити и общее количествопорожденных нитей соответственно. Например, если написать фрагмент вида:IF( OMP_GET_THREAD_NUM() .EQ. 3 ) THEN< код для нити с номером 3 >ELSE< код для всех остальных нитей >ENDIF ,то часть программы между директивами IF:ELSE будет выполнена только нитью сномером 3, а часть между ELSE:ENDIF - всеми остальными.
Как и прежде, этот код будетвыполнен всеми нитями, однако функция OMP_GET_THREAD_NUM() возвратитзначение 3 только для нити с номером 3, поэтому и выполнение данного участка кода длятретьей нити и всех остальных будет идти по-разному.Если в параллельной секции встретился оператор цикла, то, согласно общемуправилу, он будет выполнен всеми нитями, т.е. каждая нить выполнит все итерацииданного цикла. Для распределения итераций цикла между различными нитями можноиспользовать директиву!$OMP DO [опция [[,] опция]:]!$OMP END DO ,которая относится к идущему следом за данной директивой оператору DO.Опция SCHEDULE определяет конкретный способ распределения итерацийданного цикла по нитям:STATIC [,m] - блочно-циклическое распределение итераций: первый блок из mитераций выполняет первая нить, второй блок - вторая и т.д.
до последней нити, затемраспределение снова начинается с первой нити; по умолчанию значение m равно 1;DYNAMIC [,m] - динамическое распределение итераций с фиксированнымразмером блока: сначала все нити получают порции из m итераций, а затем каждая нить,заканчивающая свою работу, получает следующую порцию опять-таки из m итераций;GUIDED [,m] - динамическое распределение итераций блоками уменьшающегосяразмера; аналогично распределению DYNAMIC, но размер выделяемых блоков все времяуменьшается, что в ряде случаев позволяет аккуратнее сбалансировать загрузку нитей;RUNTIME - способ распределения итераций цикла выбирается во время работыпрограммы в зависимости от значения переменной OMP_SCHEDULE.Выбранный способ распределения итераций указывается в скобках после опцииSCHEDULE, например:!$OMP DO SCHEDULE (DYNAMIC, 10)В данном примере будет использоваться динамическое распределение итерацийблоками по 10 итераций.В конце параллельного цикла происходит неявная барьерная синхронизацияпараллельно работающих нитей: их дальнейшее выполнение происходит только тогда,когда все они достигнут данной точки.
Если в подобной задержке нет необходимости, тодиректива END DO NOWAIT позволяет нитям уже дошедшим до конца циклапродолжить выполнение без синхронизации с остальными. Если директива END DO вявном виде и не указана, то в конце параллельного цикла синхронизация все равно будетвыполнена.Параллелизм на уровне независимых фрагментов оформляется в OpenMP спомощью директивы SECTIONS : END SECTIONS:!$OMP SECTIONS< фрагмент 1>!$OMP SECTIONS< фрагмент 2>!$OMP SECTIONS< фрагмент 3>!$OMP END SECTIONSВ данном примере программист описал, что все три фрагмента информационнонезависимы, и их можно исполнять в любом порядке, в частности, параллельно другдругу.
Каждый из таких фрагментов будет выполнен какой-либо одной нитью.Если в параллельной секции какой-то участок кода должен быть выполнен лишь одинраз (такая ситуация иногда возникает, например, при работе с общими переменными), тоего нужно поставить между директивами SINGLE : END SINGLE. Такой участок кодабудет выполнен нитью, первой дошедшей до данной точки программы.41. OpenMP: основные конструкции для синхронизации нитей и работы с общими илокальными данными.Одно из базовых понятий OpenMP - классы переменных. Все переменные,используемые в параллельной секции, могут быть либо общими, либо локальными.Общие переменные описываются директивой SHARED, а локальные директивойPRIVATE.
Каждая общая переменная существует лишь в одном экземпляре и доступнадля каждой нити под одним и тем же именем. Для каждой локальной переменной вкаждой нити существует отдельный экземпляр данной переменной, доступный толькоэтой нити. Предположим, что следующий фрагмент расположен в параллельной секции:I = OMP_GET_THREAD_NUM()PRINT *, IЕсли переменная I в данной параллельной секции была описана как локальная, тона выходе будет получен весь набор чисел от 0 до OMP_NUM_THREADS-1, идущих,вообще говоря, в произвольном порядке, но каждое число встретиться только один раз.Если же переменная I была объявлена общей, то единственное, что можно сказать суверенностью - мы получим последовательность из OMP_NUM_THREADS чисел,лежащих в диапазоне от 0 до OMP_NUM_THREADS-1 каждое.
Сколько и каких именночисел будет в последовательности заранее сказать нельзя. В предельном случае, это можетбыть даже набор из OMP_NUM_THREADS одинаковых чисел I0. Предположим, что всепроцессы, кроме процесса I0, выполнили первый оператор, но затем их выполнение покакой-то причине было прервано. В это время процесс с номером I0 присвоил этозначение переменной I, а поскольку данная переменная является общей, то одно и тожезначение затем и будет выведено каждой нитью.Целый набор директив в OpenMP предназначен для синхронизации работы нитей.Самый распространенный способ синхронизации - барьер.
Он оформляется с помощьюдирективы!$OMP BARRIER .Все нити, дойдя до этой директивы, останавливаются и ждут пока все нити недойдут до этой точки программы, после чего все нити продолжают работать дальше.Пара директив MASTER : END MASTER выделяет участок кода, который будет выполнентолько нитью-мастером. Остальные нити пропускают данный участок и продолжаютработу с выполнения оператора, расположенного следом за директивой END MASTER.С помощью директив!$OMP CRITICAL [ (<имя_критической_секции>) ]...!$OMP END CRITICAL [ (< имя_ критической_секции >) ],оформляется критическая секция программы. В каждый момент времени в критическойсекции может находиться не более одной нити. Если критическая секция уже выполняетсякакой-либо нитью P0, то все другие нити, выполнившие директиву для секции с даннымименем, будут заблокированы, пока нить P0 не закончит выполнение данной критическойсекции.