Спец часть (часть 3) (3 поток) (2015) (by Кибитова) (1161603), страница 45
Текст из файла (страница 45)
Используйте то, что вам больше нравится. НоОченьскоростанетясно,что прииспользованиисистемыпараллельногозадачи,вопросэффективностиможетоказатьсякак тольковыначнетерешатьбольшиезадачи ключевым.и,любойособенно,предельнобольшие программированиямноговариантныежеланиеповыситьпроизводительностьвычислительнойтехникинавашейзадачесопровождаетсяОченьскоростанетясно,чтоприиспользованиилюбойсистемыпараллельногопрограммированиязадачи, вопрос эффективности может оказаться ключевым.тем,чтоскороот васстанеттребуетсяи большекаких-тосведенийо структурезадачи,желаниеповыситьпроизводительностьвычислительнойтехникинапараллельноговашейзадаче программированиясопровождаетсяОченьясно,всечтобольшепри использованиилюбойновыхсистемыпрограммыилитребуетсяалгоритма.одна системапараллельногопрограммированияне гарантируеттем,что отповыситьвасвсеНибольшеи большекаких-то новыхсведенийо структурезадачи,желаниепроизводительностьвычислительнойтехникина вашейзадачесопровождаетсявысокуюпроцессовбез предоставлениясведений.программыНи большеодна системапараллельногопрограммированияне гарантируеттем, что эффективностьотиливасалгоритма.требуетсявычислительныхвсеи большекаких-тоновыхсведенийдополнительныхо структурезадачи,высокуюэффективностьвычислительныхпроцессовбез предоставлениядополнительныхсведений.программыили алгоритма.Ни одна системапараллельногопрограммированияне гарантируетвысокую эффективность вычислительных процессов без предоставления дополнительных сведений.
23. Технологии параллельного программирования MPI и OpenMP. Одним из наиболее популярных средств программирования компьютеров собщей памятью, базирующихся на традиционных языках программированияи использовании специальных комментариев, в настоящее время являетсятехнология OpenMP. За основу берется последовательная программа, а длясоздания ее параллельной версии пользователю предоставляется набордиректив, процедур и переменных окружения. Стандарт OpenMPразработан для языков Фортран, С и С++. Поскольку все основныеконструкции для этих языков похожи, то рассказ о данной технологии мыбудем вести на примере только одного из них, а именно на примере языкаФортран.Как, с точки зрения OpenMP, пользователь должен представлять своюпараллельную программу? Весь текст программы разбит напоследовательные и параллельные области (см.
рис.1). В начальный моментвремени порождается нить-мастер или "основная" нить, которая начинаетвыполнение программы со стартовой точки. Здесь следует сразу сказать,почему вместо традиционных для параллельного программированияпроцессов появился новый термин - нити (threads, легковесные процессы).Технология OpenMP опирается на понятие общей памяти, поэтому она, взначительной степени, ориентирована на SMP-компьютеры.
На подобныхархитектурах возможна эффективная поддержка нитей, исполняющихся наразличных процессорах, что позволяет избежать значительных накладныхрасходов на поддержку классических UNIX-процессов.Основная нить и только она исполняет все последовательные областипрограммы. При входе в параллельную область порождаютсядополнительные нити. После порождения каждая нить получает свойуникальный номер, причем нить-мастер всегда имеет номер 0. Все нитиисполняют один и тот же код, соответствующий параллельной области.
Привыходе из параллельной области основная нить дожидается завершенияостальных нитей, и дальнейшее выполнение программы продолжает толькоона.В параллельной области все переменные программы разделяются на двакласса: общие (SHARED) и локальные (PRIVATE). Общая переменная всегдасуществует лишь в одном экземпляре для всей программы и доступна всемнитям под одним и тем же именем. Объявление же локальной переменнойвызывает порождение своего экземпляра данной переменной для каждойнити. Изменение нитью значения своей локальной переменной, естественно,никак не влияет на изменение значения этой же локальной переменной вдругих нитях.По сути, только что рассмотренные два понятия: области и классыпеременных, и определяют идею написания параллельной программы врамках OpenMP: некоторые фрагменты текста программы объявляетсяпараллельными областями; именно эти области и только они исполняютсянабором нитей, которые могут работать как с общими, так и с локальнымипеременными.
Все остальное - это конкретизация деталей и описаниеособенностей реализации данной идеи на практике.Рассмотрим базовые положения и основные конструкции OpenMP. Вседирективы OpenMP располагаются в комментариях и начинаются с одной изследующих комбинаций: !$OMP, C$OMP или *$OMP (напомним, что строка,начинающаяся с одного из символов '!', 'C' или '*' по правилам языкаФортран считается комментарием).
В дальнейшем изложении при описанииконкретных директив для сокращения записи мы иногда будем опускать этипрефиксы, хотя в реальных программах они, конечно же, всегда должныприсутствовать. Все переменные окружения и функции, относящиеся кOpenMP, начинаются с префикса OMP_ .#pragma omp директива<> опция[ [ [,] опция]...]Описание параллельных областей. Для определения параллельных областейпрограммы используется пара директивСпецификация OpenMP для C/C++, выпущенная на год позже фортранной,содержит в основном аналогичную функциональность.Необходимо лишь отметить следующие моменты:1) Вместо спецкомментариев используются директивы компилятора"#pragma omp".2) Компилятор с поддержкой OpenMP определяет макрос "_OPENMP",который может использоваться для условной компиляции отдельныхблоков, характерных для параллельной версии программы.3) Распараллеливание применяется к for-циклам, для этого используетсядиректива "#pragma omp for". В параллельных циклах запрещаетсяиспользовать оператор break.4) Статические (static) переменные, определенные в параллельной областипрограммы, являются общими (shared).5) Память, выделенная с помощью malloc(), является общей (однакоуказатель на нее может быть как общим, так и приватным).6) Типы и функции OpenMP определены во включаемом файле <omp.h>.7) Кроме обычных, возможны также "вложенные" (nested) замки - вместологических переменных используются целые числа, и нить, уже захватившаязамок, при повторном хахвате может увеличить это число.Пример распараллеливания for-цикла в C#pragma omp parallel for private(i)#pragma omp shared(x, y, n) reduction(+: a, b)for (i=0; i<n; i++){a = a + x[i];b = b + y[i];}Опция scheduleУправляет распределением работы между нитями в конструкции распределения работы цикла.schedule тип([, chunk])Опция задаёт, каким образом итерации цикла распределяются между нитями; Задается видалгоритма планирования и, если необходимо, числовой параметр алгоритма (обычно размер блокапространства итераций).В опции schedule параметр type задаёт следующий тип распределения итераций:1.
static – блочно-циклическое распределение итераций цикла; размер блока – chunk.Первый блок из chunk итераций выполняет нулевая нить, второй блок – следующая и т.д. допоследней нити, затем распределение снова начинается с нулевой нити. Если значение chunkне указано, то всё множество итераций делится на непрерывные куски примерноодинакового размера (конкретный способ зависит от реализации), и полученные порцииитераций распределяются между нитями.2. dynamic – динамическое распределение итераций с фиксированным размером блока: сначалакаждая нить получает chunk итераций (по умолчанию chunk=1), та нить, котораязаканчивает выполнение своей порции итераций, получает первую свободную порцию изchunk итераций. Освободившиеся нити получают новые порции итераций до тех пор, покавсе порции не будут исчерпаны.
Последняя порция может содержать меньше итераций, чемвсе остальные.3. guided – динамическое распределение итераций, при котором размер порции уменьшается снекоторого начального значения до величины chunk (по умолчанию chunk=1)пропорционально количеству ещё не распределённых итераций, делённому на количествонитей, выполняющих цикл. Размер первоначально выделяемого блока зависит отреализации. В ряде случаев такое распределение позволяет аккуратнее разделить работу исбалансировать загрузку нитей. Количество итераций в последней порции может оказатьсяменьше значения chunk.4.
auto – способ распределения итераций выбирается компилятором и/или системой выполнения.Параметр chunk при этом не задаётся.runtime – способ распределения итераций выбирается во время работы программы по значениюпеременной среды OMP_SCHEDULE. Параметр chunk при этом не задаётся.Директива parallell.
97Директива parallel создает параллельную область для следующего за ней структурированногоблока, параллельная область задаётся при помощи записи: l. 99#pragma omp parallel опция[[[,] опция]...]структурированныйблокl. 104Возможные опции:12.if (условие) – выполнение параллельной области по условию. Вхождение в параллельнуюобласть осуществляется только при выполнении некоторого условия. Если условие невыполнено, то директива не срабатывает и продолжается обработка программы в прежнемрежиме;13.num_threads (целочисленное выражение) – явное задание количества нитей, которыебудут выполнять параллельную область; по умолчанию выбирается последнее значение,установленное с помощью функции omp_set_num_threads(), или значениепеременной OMP_NUM_THREADS;14.default(shared|none) – всем переменным в параллельной области, которым явно неназначен класс, будет назначен класс shared; none означает, что всем переменным впараллельной области класс должен быть назначен явно;15.private (список) – задаёт список переменных, для которых порождается локальная копияв каждой нити; начальное значение локальных копий переменных из списка не определено;16.firstprivate (список) – задаёт список переменных, для которых порождается локальнаякопия в каждой нити; локальные копии переменных инициализируются значениями этихпеременных в нити-мастере;17.shared (список) – задаёт список переменных, общих для всех нитей;18.copyin (список) – задаёт список переменных, объявленных как threadprivate, которые привходе в параллельную область инициализируются значениями соответствующихпеременных в нити-мастере;19.reduction (оператор:список) – задаёт оператор и список общих переменных; для каждойпеременной создаются локальные копии в каждой нити; локальные копииинициализируются соответственно типу оператора (для аддитивных операций – 0 или егоаналоги, для мультипликативных операций – 1 или её аналоги); над локальными копиямипеременных после выполнения всех операторов параллельной области выполняетсязаданный оператор; оператор это: +, *, -, &, |, ^, &&, ||; порядок выполненияоператоров не определён, поэтому результат может отличаться от запуска к запуску.l.
116Эта директива сообщает компилятору, что структурированный блок кода должен быть выполненпараллельно, в нескольких потоках. Каждый поток будет выполнять один и тот же поток команд,но не один и тот же набор команд – все зависит от операторов, управляющих логикой программы,таких как if-else. l. 118При входе в параллельную область порождаются новые OMP_NUM_THREADS-1 нитей, каждаянить получает свой уникальный номер, причём порождающая нить получает номер 0 и становитсяосновной нитью группы (“мастером”). Остальные нити получают в качестве номера целые числа с1 до OMP_NUM_THREADS-1. Количество нитей, выполняющих данную параллельную область,остаётся неизменным до момента выхода из области. При выходе из параллельной областипроизводится неявная синхронизация и уничтожаются все нити, кроме породившей.