Что такое OpenMP

Автор работы: Пользователь скрыл имя, 26 Декабря 2011 в 20:22, реферат

Описание

OpenMP (Open Multi-Processing) - это набор директив компилятора, библиотечных процедур и переменных окружения, которые предназначены для программирования многопоточных приложений на многопроцессорных системах с общей памятью (SMP-системах).
Первый стандарт OpenMP был разработан в 1997 г. как API, ориентированный на написание легко переносимых многопоточных приложений. Сначала он был основан на языке Fortran, но позднее включил в себя и языки Си и Си++.

Работа состоит из  1 файл

Стандарт интерфейса приложений для параллельных систем с общей памятью.doc

— 102.50 Кб (Скачать документ)

   Что такое OpenMP? 

   OpenMP (Open Multi-Processing) - это набор директив компилятора, библиотечных процедур и переменных окружения, которые предназначены для программирования многопоточных приложений на многопроцессорных системах с общей памятью (SMP-системах).

   Первый  стандарт OpenMP был разработан в 1997 г. как API, ориентированный на написание  легко переносимых многопоточных  приложений. Сначала он был основан  на языке Fortran, но позднее включил  в себя и языки Си и Си++.

   Интерфейс OpenMP стал одной из наиболее популярных технологий параллельного программирования. OpenMP успешно используется как при программировании суперкомпьютерных систем с большим количеством процессоров, так и в настольных пользовательских системах или, например, в Xbox 360.

   Разработчики  OpenMP хотели предоставить простой способ создания потоков в приложениях, не требуя от программиста знаний о создании, синхронизации и уничтожении потоков, а также необходимости определения, сколько потоков следует создать. Для этого разработчики OpenMP создали независимый от платформы набор прагм, директив, вызовов функций и переменных среды, которые явным образом указывают компилятору, как и где именно следует вставить потоки в приложение. Большинство циклов можно распараллелить, вставив всего одну прагму непосредственно перед циклом. Более того, оставив исполнение рутинных функций компилятору и OpenMP, вы можете больше времени уделить определению того, какие циклы следует распараллелить, и как наилучшим образом изменить структуру алгоритмов для достижения максимальной производительности. Максимальная производительность OpenMP реализуется при использовании этого инструмента для распараллеливания "горячих точек", - наиболее трудоемких циклов в приложении.

   Разработку  спецификации OpenMP ведут несколько  крупных производителей вычислительной техники и программного обеспечения, чья работа регулируется некоммерческой организацией "OpenMP Architecture Review Board" (ARB). 

   Прагмы OpenMP 

   Спецификация OpenMP определяет набор прагм. Прагма - это директива компилятора, указывающая, как обрабатывать код, следующий за прагмой. Наиболее существенной является прагма #pragma omp parallel, определяющая область параллельности.

   В OpenMP используется модель параллельного  выполнения "ветвление-слияние". Программа OpenMP начинается как единстванный поток выполнения, называемый начальным потоком. Когда поток встречает параллельную конструкцию, он создает новую группу потоков, состоящую из себя и неотрицательного числа дополнительных потоков, и становится главным в новой группе. Все члены новой группы (включая главный) выполняют код внутри параллельной конструкции. В конце параллельной конструкции имеется неявный барьер. После параллельной конструкции выполнение пользовательского кода продолжает только главный поток.

   Число потоков в группе, выполняющихся  в области параллельности, можно  контролировать несколькими способами. Один из них -- использование переменной среды OMP_NUM_THREADS. Другой способ -- вызов процедуры omp_set_num_threads(). Еще один способ -- использование выражения num_threads в сочетании с прагмой parallel.

   В OpenMP поддерживаются две основных конструкции  разделения работы для указания того, что работу в области параллельности следует разделить между потоками группы. Эти конструкции разделения работы - циклы и разделы. Прагма #pragma omp forиспользуется для циклов, а прагма #pragma omp sections используется для разделов -- блоков кода, которые могут быть выполнены параллельно.

   Прагма #pragma omp barrier дает всем потокам указание ожидать друг друга перед тем, как они продолжат выполнение за барьером. Как было отмечено выше, в конце области параллельности имеется неявный барьер. Прагма #pragma omp master дает компилятору указание о том, что следующий блок кода должен выполняться только главным потоком. Прагма #pragma omp singleпоказывает, что следующий блок кода должен выполняться только одним потоком группы; этот поток не обязательно должен быть главным. Прагма #pragma omp critical может использоваться для защиты блока кода, который должен выполняться одновременно только одним потоком. Конечно, все эти прагмы имеют смысл только в контексте прагмы parallel (области параллельности). 

   Процедуры OpenMP 

   OpenMP предоставляет ряд процедур, которые  можно использовать для получения  сведений о потоках в программе. В их число входят omp_get_num_threads(), omp_set_num_threads(), omp_get_max_threads(), omp_in_parallel() и другие. Кроме того, OpenMP предоставляет ряд процедур блокировки, которые можно использовать для синхронизации потоков. 

   Переменные среды OpenMP 

   OpenMP предоставляет несколько переменных  среды, которые можно использовать  для управления поведением программы,  использующей OpenMP.

   Важной  переменной среды является переменная OMP_NUM_THREADS, указывающая число потоков в группе, которая должна использоваться для выполнения в области параллельности (включая главный поток группы). Другая широко применяемая переменная среды - OMP_DYNAMIC. Чтобы отключить динамическое изменение числа потоков реализацией во время выполнения, для этой переменной следует установить значение FALSE. Общим правилом является не делать число потоков большим, чем число процессорных ядер в системе.

   Помимо  переменных среды, предусмотренных  стандартом OpenMP, компиляторы Sun Studio предоставляют  дополнительный набор специфических переменных среды, обеспечивающий дополнительные возможности управления средой времени выполнения. Эти переменные описаны в Руководстве пользователя по OpenMP. 

   Технология OpenMP 

   Стандарт  OpenMP создавался для упрощения разработки параллельных программ для вычислительных систем с общей памятью, а так же для распараллеливания уже существующих последовательных программ. Стандартом определены специальные комментарии (команды препроцессору для C/C++) – директивы компилятору, непосредственно управляющие параллелизмом программы, вспомогательные функции, позволяющие создавать алгоритмы, ориентированные на параллельное выполнение, и переменные окружения, управляющие процессом выполнения параллельных областей. 

Пример

Sequential code

void main(){

  double x[1000];

  for(i=0; i<1000; i++){

    calc_smth(&x[i]);

  }

}

Parallel code

void main(){

  double x[1000];

#pragma omp parallel for ...

  for(i=0; i<1000; i++){

    calc_smth(&x[i]);

  }

}

 

   В OpenMP используется модель параллельного  выполнения "ветвление-слияние". Программа OpenMP начинается как единственный поток выполнения, называемый начальным потоком. Когда поток встречает параллельную конструкцию, он создает новую группу потоков, состоящую из себя и некоторого числа дополнительных потоков, и становится главным в новой группе. Все члены новой группы (включая главный) выполняют код внутри параллельной конструкции. В конце параллельной конструкции имеется неявный барьер. После параллельной конструкции выполнение пользовательского кода продолжает только главный поток. В параллельный регион могут быть вложены другие параллельные регионы, в которых каждый поток первоначального региона становится основным для своей группы потоков. Вложенные регионы могут в свою очередь включать регионы более глубокого уровня вложенности.

   Число потоков в группе, выполняющихся  параллельно, можно контролировать несколькими способами. Один из них - использование переменной окружения OMP_NUM_THREADS. Другой способ - вызов процедуры omp_set_num_threads(). Еще один способ - использование выражения num_threads в сочетании с директивой parallel.

   Программа, использующая директивы OpenMP, состоит из последовательных и параллельных участков. В начале ее выполнения создается одна нить, которая существует на протяжении всей программы. Когда какая-либо нить доходит до параллельного участка, то порождаются дополнительные нити, выполняющие вместе с ней этот участок. Группой нитей называется множество нитей, созданных при входе в данную параллельную область, включая породившую их нить, называемую главной. Нить, достигшая конца параллельной области, дожидается всю группу. Когда все нити одной группы дойдут до конца параллельного участка, все нити кроме главной освобождаются, а главная нить продолжает выполнение программы. На рисунке 1 показан пример создания и освобождения нитей в параллельных областях в случае наличия вложенных параллельных участков.

   

   Рисунок 1: Пример выполнения параллельного участка 

   В OpenMP память подразделяется на 2 вида: общая память и локальная память.

   Общая память доступна нескольким нитям одновременно. Однако, для работы с ней необходимо использовать синхронизирующие конструкции, которые позволяют избежать недетерминизма.

   Локальная память доступна только одной нити. 
 
 
 

   Ошибки, возникающие при  использовании OpenMP 

   В 2004-2005 годах в University of Kassel(Германия) проводилось исследование, целью которого было выявление наиболее часто совершаемых ошибок, обусловленных некорректным использованием функций и директив OpenMP, и приводящих к неверному выполнению программы. Эксперимент проводился на студентах этого университета, которые должны были написать некоторую программу с использованием OpenMP версии 2.5 или более ранней. Большинство испытуемых ранее не имели опыта работы с OpenMP, что позволило выявить ошибки, допускаемые начинающими программистами. В результате были обнаружены следующие ошибки [3]:

  1. Незащищенный доступ к общим переменным.

   Данная  ошибка возникает, когда несколько нитей работают с общей памятью без какой-либо синхронизации. В этом случае возможны следующие ситуации:

   - все нити только читают переменную, тогда ошибки нет, т.к. значение  переменной в любой момент  времени остается неизменным.

   - все нити только пишут в переменную. Поскольку они это делают одновременно, то нельзя определить, какое значение получит переменная после выполнения всех операций записи. И значение данной переменной будет при каждом запуске программы различным.

   - часть нитей читают переменную, а часть пишут в нее. Здесь помимо эффекта предыдущего случая, наблюдается аналогичная неопределенность. Когда какая-либо нить пытается прочитать значение переменной, то неизвестно, какое именно значение будет получено.

  1. Использование механизма замков без директивы flush.

   Этот  пункт является ошибкой только для  ранних версий OpenMP(до версии 2.5).

   При работе с общими переменными предполагается, что каждая нить работает с копией этой переменной, расположенной в  кэше соответствующего процессора. Директива flush обновляет во всех нитях значения общих переменных, т.е. все нити будут видеть последние изменения. Поэтому, если использовать замки без директивы flush, то возможна ситуация, когда одна нить замок поставит, а другая не увидит никаких изменений, и будет считать, что ресурс свободен, и его можно захватить. В результате будет некорректная ситуация, когда сразу несколько нитей установили один и тот же замок. Начиная с версий OpenMP 2.5, директива flush входит в состав функций для работы с замками.

  1. Чтение общих переменных без директивы flush.

   Ситуация  аналогичная предыдущему случаю. Если не использовать директиву flush перед чтением переменной, то нить может не получить последнее обновленное значение переменной. Вообще, в последних версиях OpenMP flush неявно включена во многие директивы, в особенности в синхронизационные, что позволяет избежать во многих случаях данной ошибки.

  1. Использование переменных как приватных, хотя таковыми они не являются.

   Эта ошибка вызвана тем, что программист  забыл указать, что переменная является приватной. Во время выполнения программы, данную ошибку невозможно отличить от ошибки, описанной в первом пункте.

  1. Использование предложения ordered без конструкции ordered.

   Предполагается, что если в директиве распараллеливания  цикла указано условие ordered, то внутри этого цикла должна располагаться область, помеченная как ordered. Это означает, что указанная область должна быть выполнена в том же порядке (по итерациям цикла), что и в последовательной программе. Отсутствие такой области в теле цикла, при наличии условия ordered считается ошибкой.

Информация о работе Что такое OpenMP