339 63 376KB
Russian Pages 31 [32] Year 2006
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ ФЕДЕРАЛЬНОЕ АГЕНСТВО ПО ОБРАЗОВАНИЮ Государственное образовательное учреждение высшего профессионального образования «РОСТОВСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ»
Методические указания на тему:
«Параллельное программирование: OpenMP API»
Ростов-на-Дону 2006
Методические указания разработаны кандидатом физико-математических наук, доцентом кафедры информатики и вычислительного эксперимента В.А. Савельевым. Компьютерный набор и верстка автора.
Печатается в соответствии с решением кафедры информатики и вычислительного эксперимента мехмата РГУ, протокол № 3 от «20» ноябра 2006 года.
1.Введение При распараллеливания программы для системы с разделяемой памятью мы можем использовать следующие инструменты: ●
Библиотеки поддержки нитей, такие как Pthreads или Win32 threads API.
●
Компиляторы с поддержкой OpenMP. Этот стандарт поддерживается
компиляторами Intel (C/C++, FORTRAN 95 для Win32, Linux), компиляторами Sun Studio, компиляторами IBM, HP, SGI, KAI, Lahey. ●
Компиляторы,
выполняющие
автоматическое
распараллеливание.
Автоматическое распараллеливание выполняют для некоторых классов программ компиляторы Intel. ●
Системы программирования, поддерживающие нити (многозадачность)
на уровне языка программирования. Например, Java, Python, Ada~83/95/05. В данных методических указаниях мы рассмотрим программирование с использованием OpenMP API.
2.Введение в OpenMP Разработчики систем с общей памятью (SMP, многоядерные процессоры, NUMA, ...) создали спецификацию расширения OpenMP ― промышленный cтандарт de facto разработки параллельных программ для SMP-систем. Непосредственно
разработкой
занимается
OpenMP
Architecture
Board
. Последняя версия спецификации 2.5 принята в 2005 году, предыдущая(2.0) была принята в 2000-2001 годах. Отличие между этими версиями состоит в более строгом описании семантики директив и клауз OpenMP, в более четком изложении ограничений на использование директив и функций библиотеки времени исполнения OpenMP, а также в объединении спецификаций для C/C++ и FORTRAN'а в один документ. 3
3.Основные понятия OpenMP не определяет новый язык, а использует базовый язык в качестве основания для OpenMP API. В спецификациях 2.x в качестве базовых языков используются C90, C99, C++, FORTRAN 77, FORTRAN 90 и FORTRAN 95. Исходной программой называется программа, написанная на базовом языке. Директивой OpenMP является в C/C++ ― прагма, а в FORTRAN'е ― комментарий. Функции времени выполнения являются обычными функциями соответствующего языка программирования. Спецификация включает модуль-заглушку с этими функциями для компиляторов не поддерживающих OpenMP. Программой OpenMP называется исходная программа, аннотированная (размеченная) с помощью директив OpenMP. Структурной областью называется: ●
FORTRAN последовательность выполнимых операторов с единствен-
ной точкой входа в начале и единственной точкой выхода в конце. Однако оператор STOP допускается в структурном блоке. ●
C/C++ выполнимое предложение, возможно составное, с единственной
точкой входа в начале и единственной точкой выхода в конце. Однако вызов exit() допустим в структурном блоке. Структурный область не запрещает использования явных переходов (операторов go to), он запрещает переходы извне внутрь структурного блока, и из структурного блока во-вне. В языке C в структурной области запрещено также использование longjump. 3.1.Модель вычислений Модель вычислений в OpenMP основана на порождении и объединении нитей (fork-join). Эта модель может быть приспособлена для решения различных задач, но её реализация в OpenMP направлена на распараллеливание программ, в 4
которых основная работа происходит в циклах, в частности программ обрабатывающих большие массивы данных. Заметим, что порождение дополнительных нитей и их уничтожение требуют затрат вычислительных ресурсов и памяти, и тоже должны минимизироваться. Параллельная область
Нити
Время
Рисунок 1 ― Модель выполнения OpenMP Программа начинается выполнением одной нити, называемой начальной (initial) нитью. Начальная нить выполняется последовательно. Когда нить достигает директивы parallel она создает команду нитей, состоящую из неё самой и нуля или более дополнительных нитей, и становится хозяйкой (master) созданной команды. Все члены команды исполняют код структурной области, связанной с директивой parallel (параллельной области). В конце параллельной области размещается неявный барьер. Только нить-хозяйка продолжает выполнение после завершения параллельной области. В программе может находится любое количество директив parallel. Параллельные области могут быть вложены друг в друга. Если вложенный параллелизм запрещен или не поддерживается реализацией, новая команда будет состоять только из самой нити, встретившей вложенную директиву parallel. 5
Команда нитей, встретившая конструкцию распределения работы, разделяет работу заданную этой конструкцией между нитями команды, и эта работа выполняется нитями совместно, вместо того чтобы выполняться полностью каждой нитью. После конструкции распределения работы все нити продолжают выполнение кода параллельной области. Конструкции синхронизации и библиотечные подпрограммы позволяют согласовывать выполнение нитей и доступ к данным в параллельных областях. Отметьте, что нет гарантий синхронного доступа к файлам при выполнении ввода/вывода из разных нитей, поэтому синхронизация в этом случае возлагается на программиста. 3.2.Модель памяти OpenMP предполагает, что программа выполняется в системе с разделяемой памятью, в которой хранятся (могут быть сохранены и выбраны) переменные программы доступные всем её нитям. Кроме того каждая нить имеет доступ к памяти, недоступной для всех других нитей; такая память называется частной памятью нити. Директива parallel разделяет память, доступную параллельной области, на разделяемую (shared) и частную (private). Каждая переменная, встречающаяся в параллельной области, имеет соотвествующую одноименную (оригинальную) переменную вне параллельной области. Разделяемая переменная ссылается на ту же память, что и оригинальная переменная вне параллельной области. Для каждой частной переменной создается новая переменная в памяти каждой нити, кроме, быть может, нити-хозяйки. Частные переменные в параллельной области ссылаются на частную память нити. Дополнительно каждая нить может иметь своё временное представление памяти. Это временное представление не является необходимой частью модели
6
памяти OpenMP, но учитывает наличие в современных вычислительных системах регистров процессора, кэшей различных уровней и других структур, позволяющих нити кэшировать переменные и избегать лишних обращений к памяти. Это временное представление не обязано быть все время согласованным с памятью. Поэтому OpenMP предоставляет средства позволяющие принудительно установить согласованность временного представления с памятью. Предполагается, что компилятор C/C++ поддерживающий OpenMP, автоматически поддерживает согласованность разделяемых переменных, описанных с ключевым словом volatile. Естественно предполагается, что для таких переменных проводится принудительное согласование непосредственно перед чтением и непосредственно после записи. Компиляторы не ограничиваются в переупорядочивании операций нити с памятью и использовании преимуществ временного представления кроме необходимости сохранять порядок принудительных согласований. Поскольку согласование могут выполнять различные нити, OpenMP предполагает слабое упорядочение согласований. 3.3.Синтаксис директив в FORTRAN'е В FORTRAN'е директивы задаются специальными комментариями. В фиксированном формате (устаревшем) это C$OMP | *$OMP | !$OMP
а в свободном формате !$OMP
Таким образом, директивы OpenMP имеют вид !$OMP directive-name [clause[[,] clause]...]
7
Директивы, клаузы и их аргументы в FORTRAN'е не учитывают регистр букв. Директивы OpenMP не могут встречаться в процедурах, описанных с атрибутами PURE или ELEMENTAL. 3.4.Синтаксис директив в C Директивы OpenMP для C используют предусмотренный в этом языке механизм директив компилятора. #pragma omp directivename [clause[,clause]…] new-line
Компилятор с поддержкой OpenMP определяет макрос _OPENMP, что позволяет организовывать условную компиляцию.
4.Директивы OpenMP API Директива parallel
Начинает параллельное выполнение. FORTRAN !$omp parallel [clause[[,] clause]...] structured-region !$omp end parallel
C/C++ #pragma omp parallel [clause[[,]clause] ...] new-line structured-block
Когда нить повстречает директиву parallel, создатеся рабочая команда нитей, совместно выполняющих код параллельной области. Число нитей в команде не изменяется на протяжении одной параллельной области. В параллельной области 8
номер нити однозначно идентифицирует нить. Нить-хозяйка команды всегда имеет номер 0. Каждая нить выполняет одну и ту же параллельную область, хотя путь выполнения может быть разным в различных нитях. Если одна из нитей завершается, завершаются и все прочие нити во всех командах. Порядок завершения не определяется. Вся работа выполненная командой нитей до достижения барьера, успешно пройденного командой гарантировано выполнена.
Количество
работы
выполненной
нитями
после
последнего
пройденного барьера и до завершения не определено. 4.1.Директивы распределения работы Распределение циклов
Эта директива указывает, что итерации следующего за ней цикла могут выполняться параллельно. В результате итерации цикла распределяются среди нитей уже существующей команды. В конце области цикла устанавливается неявный барьер (может быть отменен клаузой nowait) !$omp do [clause[[,] clause] ... ] do-loop [!$omp end do [nowait] ]
#pragma omp for [clause[[,] clause] ... ] new-line for-loop
Директива sections
Неитеративная конструкция, содержащая набор структурных областей, вы-
9
полняющихся по области на нить. В конце присутствует неявный барьер, который может быть убран клаузой nowait. FORTRAN !$omp sections [clause[[,] clause] ...] [!$omp section] structured-region [!$omp section structured-region ] ... !$omp end sections [nowait]
C/C++ #pragma omp sections [clause[[,] clause]...] new-line { [#pragma omp section new-line] structured-block [#pragma omp section new-line structured-block ] ... }
Директива single
Задает структурную область, которая выполняется только одной нитью в команде (не обязательно нитью-хозяйкой). Остальные нити ждут на неявном барьере завершения этой области, если не задана клауза nowait. 10
FORTRAN !$omp single [clause[[,] clause] ...] structured-region !$omp end single [end_clause[[,] end_clause] ...]
Здесь клаузами в начале конструкции могут быть private и firstprivate, а в конце – copyprivate и nowait. В случае C/C++ все клаузы указываются в одной директиве. C/C++ #pragma omp single [clause[[,] clause]...] new-line structured-block
Директива workshare
Эта директива используется только в Фортране. Она приводит к разделению структурной области на раздельные работы и распределению их между командой нитей так, что каждая работа выполняется только один раз. !$omp workshare structured-region !$omp end workshare [nowait]
Структурная область, вложенная в директиву workshare, может содержать следующее: - векторные присваивания; - скалярные присваивания; - оператор FORALL; - оператор WHERE; - конструкцию atomic; - конструкцию critical; - конструкцию parallel Все эти конструкции могут содержать вызовы пользовательских функций, только если это ELEMENTAL-функции.
11
Реализация
директивы
workshare
должна
добавлять
необходимую
синхронизацию для обеспечения стандартной семантики FORTRAN'а. В остальном операторы в структурной области разделяются на работы следующим образом ●
для
векторных
выражений,
включая
встроенные
векторные
трансформационные функции (MATMUL, DOT_PRODUCT, SUM, PRODUCT, MAXVAL, MINVAL, COUNT, ANY, ALL, SPREAD, PACK, UNPACK, RESHAPE, TRANSPOSE, EOSHIFT, CSHIFT, MINLOC, MAXLOC.) ●
вычисление каждого из элементов векторного выражения, включая ELEMENTAL-функции, является отдельной работой
●
вычисление встроенных векторных функций может разделяться компилятором на любое ему удобное число работ
●
в векторном присваивании присваивание каждого элемента вектора
является отдельной работой ●
каждое скалярное присваивание является отдельной работой
●
в операторе WHERE вычисление маскирующих выражений и связанных с
ними присваиваний является распределяемой работой ●
в операторе FORALL вычисление элементов пространства итераций,
маскирующих выражений и присваиваний является распределяемой работой ●
для конструкций atomic присваивание каждой скалярной величины
является отдельной работой ●
для конструкций critical каждая критическая область является
отдельной работой 4.2.Комбинированные конструкции Очень часто параллельная область не содержит ничего, кроме конструкции разделения работы (т.е. конструкция разделения работы тесно вложена в 12
параллельную область). В этом случае можно указывать не две директивы, а указать одну комбинированную. Отметим, что во всех комбинированных директивах
нельзя
указывать
клаузу
nowait,
в
остальном
возможно
использование клауз, допустимых в директиве parallel и в соответствующей конструкции разделения работы. Приведем сначала комбинированные конструкции для FORTRAN'а: !$omp parallel do [clause[[,] clause]...] do-loop [!$omp end parallel do]
!$omp parallel sections [clause[[,] clause] ...] [!$omp section] structured-region [!$omp section structured-region ] ... !$omp end parallel sections
!$omp parallel workshare [clause[[,] clause] ...] structured-region !$omp end parallel workshare
Для C/C++ определены только две комбинированые конструкции: #pragma omp parallel for [clause[[,] clause]...] new-line
13
for-loop
#pragma omp parallel sections [clause[[,]clause]...]new-line { [#pragma omp section new-line] structured-block [#pragma omp section new-line structured-block ] ... }
4.3.Директивы синхронизации Директива master
Задает область, выполняемую исключительно нитью-хозяйкой команды нитей. С этой директивой не связано какой-либо неявной синхронизации. Просто нитьхозяйка выполняет указанную область, а все остальные нити эту область полностью игнорируют. !$omp master structured-region !$omp end master
#pragma omp master new-line structured-block
14
Директива critical
Ограничивает выполнение структурной области единственной нитью из всех нитей программы, вне зависимости от принадлежности команде, в каждый момент времени. Критическая область может иметь имя, все области без имени считаются областями с одним и тем же именем. Имя критической области является глобальным идентификатором. !$omp critical [(name)] structured-region !$omp end critical [(name)]
#pragma omp critical [(name)] new-line structured-block
Директива barrier
Задает явный барьер для текущей команды нитей в точке нахождения директивы. Директива связывается с ближайшей объемлющей параллельной областью. Барьер должен достигаться всеми нитями команды или ни одной из них. Кроме того, последовательность выполнения областей разделения работы и барьеров (явных или неявных) должна быть одинакова для всех нитей в команде. !$omp barrier
#pragma omp barrier new-line
15
Первая нить, достигшая барьера
простой простой простой
простой
Область барьера
Время
Последняя нить, достигшая барьера
Рисунок 2 ― Барьерная синхронизация Директива atomic
Упрощенная версия критической области, обеспечивающая атомарное изменение переменной. Отметим, что атомарно происходит именно загрузка и сохранение измененного значения переменной, вычисление всех других выражений не атомарны. То есть, если оператором является x = x + sin(2*a), то атомарно обновление x, а вычисление синуса не является атомарным. !$omp atomic statement
#pragma omp atomic new-line expression-stmt
Директива flush
Выполняет явное и принудительное согласование временного представления
16
памяти нити с разделяемой памятью программы. Выполнение влияет только на представление памяти той нити, которая достигла этой директивы. При указании списка происходит согласование значений только указанных переменных. Если же список отсутствует, происходит согласование значений всей памяти, доступной для нити. !$omp flush [(list)]
#pragma omp flush [(list)] new-line
Неявное согласование памяти без списка переменных производится при: ●
проходе барьера
●
входе и выходе в параллельные, критические и упорядоченные (ordered)
области ●
выходе из области разделения работы без указания nowait
●
входе и выходе в комбинированные области разделения работы
●
во время выполнения функций omp_set_lock,
omp_test_lock,
omp_set_nest_lock,
omp_unset_lock,
omp_unset_nest_lock
и
omp_test_nest_lock
Согласование памяти со списком переменных неявно происходит на входе и выходе в атомарный оператор, где список содержит только переменную, обновляемую в этом операторе. Директива ordered
Задает область внутри параллельной области цикла, которая должна выполняться последовательно в порядке итераций исходного цикла. Код вне этого региона может выполняться параллельно.
17
!$omp ordered structured-region !$omp end ordered
#pragma omp ordered new-line structured-block
4.4.Клаузы планирования и синхронизации Клауза if
Позволяет условно исполнять директивы OpenMP. Данная клауза используется в директиве parallel. Если выражение в этой клаузе ложно, команда нитей не создается и связанный с ними структурный блок выполняется последовательною. if(scalar_logical_expression)
Клауза num_threads
Указывается в начале параллельной области, и перекрывает другие способы задания количества нитей в команде. num_threads(scalar_integer_expression)
Клауза schedule
Управляет распределением работы между нитями в конструкции распределения работы цикла. schedule(kind[, chunk_size])
Задается вид алгоритма планирования и, если необходимо, числовой параметр 18
алгоритма (обычно размер блока пространства итераций). kind static
Пространство итераций цикла разделяется на фрагменты размером chunk_size и эти фрагменты статически присваиваются нитям, используя карусельный алгоритм (round-robin) в порядке номеров нитей. Если chunk_size не указан, пространство итераций делится на приблизительно равные фрагменты и нити присваивается один фрагмент.
dynamic
Пространство итераций цикла разделяется на фрагменты размером chunk_size и эти фрагменты присваиваются нитям по запросу. Выполнив один фрагмент, нить может запросить другой, и так пока остаются еще не выполненные фрагменты. Все фрагменты содержат по chunk_size итераций, кроме может быть последнего. Если chunk_size не указан, он полагается равным 1.
guided
Здесь тоже фрагменты присваиваются нитям по запросу. Однако размер фрагмента определяется как число еще не распределенных итераций деленное на число нитей в команде, уменьшенное на единицу. Необязательный параметр chunk_size задает минимально возможное число итераций во фрагменте (кроме может быть последнего фрагмента). Если chunk_size не указан, он полагается равным 1.
runtime
Решение о планировании откладывается до времени выполнения. Во время выполнения решение принимается с учетом умолчание системы и значения переменной окружения OMP_SCHEDULE.
Клауза nowait
Устраняет неявный барьер в конце конструкций, где он предусмотрен. В программах на FORTRAN'е указывается в закрывающей область директиве. nowait
19
Клауза ordered
Указываются в конструкциях распределения работы в циклах, для того чтобы указать, что внутри распараллеливаемого цикла есть упорядоченная область. ordered
4.5.Управление данными Правила определения являются ли данные разделяемыми или частными, достаточно сложны. Хотя понятно, что локальные в параллельной области данные считаются частными, глобальные или явно размещенные на куче данные считаются разделяемыми, и т.д. Но многочисленные частные случаи могут сделать не очевидным отнесение данных к конкретному классу памяти. Кроме того, правила существенно отличаются в случае C/C++ и FORTRAN'а. Во всяком случае явное указание атрибутов класса памяти всегда перекрывает правила по умолчанию, и описанием директив и клауз позволяющих явно управлять атрибутами памяти. Директива threadprivate
Задает список имен глобальных именованных данных, которые реплицируются каждой нити, так что каждая нить имеет свою копию такой переменной. !$omp threadprivate(list)
#pragma omp threadprivate(list) new-line
Клаузы разделения данных Рассматриваемые клаузы позволяют управлять разделением данных между нитями. Не все из этих клауз допустимы во всех директивах.
20
Клауза default
Позволяет программисту управлять свойствами переменных встретившихся в параллельной области. Для FORTRAN'а возможны три выбора default(private |shared |none)
в то время, как для C/C++ только два default(shared |none) ●
private все явно не упомянутые в объемлющих их директивах перемен-
ные являются частными. ●
shared все явно не упомянутые в объемлющих их директивах перемен-
ные являются разделяемыми. ●
none умолчание отсутствует и все встречающиеся переменные должны
иметь явно установленные свойства. Отсутствие явного определения является ошибкой. Очевидно, что в директиве может быть только одна клауза default. Клауза shared
Указывает, что все переменные из списка разделяются между всеми нитями команды, то есть эти переменные во всех нитях команды ссылаются на одну и ту же память. shared(list)
Клауза private
Указывает, что все переменные из списка являются частными переменными нитей. При входе в параллельную область для каждой оригинальной переменной, перечисленной в списке, в частной памяти нити создается соответствующая
21
переменная того же типа и все ссылки на оригинальную переменную внутри конструкции, содержащей эту клаузу, заменяются
на ссылки на частную
переменную. Однако частная переменная после создания остается неопределенной, а после выхода из параллельной области не существует и, кроме того, становится неопределенным значение оригинальной переменной. private(list)
Ограничения на клаузу естественные. Клауза firstprivate
Указывает, что все переменные из списка являются частными переменными нитей, и при входе в соответствующую область инициализируются значением оригинальной переменной. firstprivate(list)
Клауза lastprivate
Указывает, что все переменные из списка являются частными переменными нитей, и по выходу из соответствующей области оригинальные переменные обновляются. lastprivate(list)
После завершения конструкции, содержащей рассматриваемую клаузу, все оригинальные переменные-элементы списка получают значения, которые имели соответствующие частные переменные во время последовательно-последнего прохода
ассоциированного
цикла
или
section.
22
лексически-последней
конструкции
Клауза reduction
Редукция используется для распараллеливания некоторых форм рекуррентных вычислений. Рассматриваемая клауза задает оператор и список из одной или более переменных. Для каждого элемента списка в каждой нити создается частная переменная, инициализируемая в соответствии с указанным оператором. После выхода из области, значение оригинальной переменной обновляется путем комбинирования с помощью указанного оператора предшествующего значения оригинальной переменной и значений всех созданных частных переменных. В FORTRAN'е кроме операторов могут использоваться встроенные функции. reduction({operator | intrinsic_procedure_name}:list)
Следующая таблица перечисляет поддерживаемые операторы и функции и соответствующие им начальные значения частной переменной Оператор,
Начальное значение
функция +
0
*
1
-
0
.and. .or. .eqv. .neqv.
.true. .false. .true. .false.
max
Наименьшее представимое число в типе данных редуцируемой переменной
min
Наибольшее представимое число в типе данных редуцируемой переменной
iand
Все биты установлены в 1
ior
0
ieor
0 23
В случае C/C++ можно указывать только операторы, причем в случае C++ это должны быть неперегруженные операторы. reduction(operator:list)
Вот список допустимых операторов и начальных значений переменных. Оператор
Начальное значение
+
0
*
1
-
0
&
~0
|
0
^
0
&&
1
|| 0 На редукцию накладываются вполне естественные ограничения: ●
элементы списка переменных должны быть объявлены разделяемыми
переменными в какой-либо из объемлющих параллельных областей. ●
элементы списка не должны быть объявлены частными ни в одной
объемлющей конструкции разделения работы. ●
возможно использование нескольких клауз reduction в одной дирек-
тиве, но каждый элемент списка должен входить только в одну клаузу reduction. ●
тип переменной должен быть подходящим для указанного оператора.
●
переменные агрегатных типов (массивов, структур, классов), указатели и
ссылки недопустимы в этой клаузе. ●
переменные не должны быть квалифицированны как константы.
24
Клаузы копирования данных Клауза copyin
Предоставляет способ копировать threadprivate-переменные нити-хозяйки в threadprivate-переменные всех прочих нитей команды. Может встречаться только в директиве parallel. copyin(list)
Копирование проводится после создания команды нитей, но до запуска выполнения параллельной области. Клауза copyprivate
Предоставляет механизм для распространения значений частных переменных от одной нити ко всем другим нитям из команды. Эта клауза может появляться только в директиве single. copyprivate(list)
В результате этой клаузы значения частных переменных из списка, достигнутые после выполнения конструкции single, копируются в одноименные частные переменные других нитей команды перед тем как все нити команды покинут барьер в конце этой конструкции. На эту клаузу накладываются следующие ограничения: ●
все переменные из списка должны быть объявлены частными в одной из
объемлющих конструкций. ●
переменные из списка не могут появляться в клаузах private или
firstprivate той же самой директивы single.
25
4.6.Вложенные области Существуют следующие ограничения на вложение областей: ●
Область разделения работы не может быть тесно вложена в другую об-
ласть разделения работы и в области директив critical, ordered или master. ●
Директива barrier не может быть тесно вложена в область разделения
работы и в области директив critical, ordered или master. ●
Область директивы master не может быть тесно вложена в область
разделения работы. ●
Область директивы ordered не может быть тесно вложена в область
директивы critical. ●
Область директивы ordered должна быть тесно вложена в область
цикла с клаузой ordered. ●
Критическая область не может быть вложена в критическую область с
тем же именем.
5.Библиотека времени выполнения 5.1.Среда выполнения void omp_set_num_threads(int num_threads);
subroutine omp_set_num_threads(num_threads) integer num_threads
― Подпрограмма влияет на число нитей, возникающих при вхождении в следующую параллельную область. Аргумент должен быть положительным
26
числом. int omp_get_num_threads(void);
integer function omp_get_num_threads()
― Функция возвращает число нитей в текущей команде нитей. int omp_get_max_threads(void);
integer function omp_get_max_threads()
― Функция возвращает число нитей, которые будут созданы при следующем вхождении в параллельную область. int omp_get_thread_num(void);
integer function omp_get_thread_num()
― Функция возвращает номер нити в текущей команде нитей. int omp_get_num_procs(void);
integer function omp_get_num_procs()
― Функция возвращает число процессоров, доступных программе. int omp_in_parallel(void);
logical function omp_in_parallel()
27
― Функция возвращает находимся ли мы в параллельной области. Имеется в виду не ближайшая параллельная область, а наличие хотя бы одной активной объемлющей параллельной области. void omp_set_dynamic(int dynamic_threads);
subroutine omp_set_dynamic (dynamic_threads) logical dynamic_threads
― Подпрограмма устанавливает, можно ли динамически определять число нитей в команде при обнаружении следующей параллельной области. int omp_get_dynamic(void);
logical function omp_get_dynamic()
― Функция возвращает логическое значение, определяющее будет ли динамически определяться число нитей в команде следующей параллельной области. void omp_set_nested(int nested);
subroutine omp_set_nested (nested) logical nested
― Подпрограмма определяет, позволяется ли распараллеливать следующую вложенную параллельную область. int omp_get_nested(void);
28
logical function omp_get_nested()
― Функция возвращает логическое значение, показывающее позволяется ли распараллеливать следующую вложенную параллельную область. 5.2.Блокировки Библиотека OpenMP включает набор блокировок общего назначения. Блокировки могут быть в одном из трех состояний: неинициализирована, неблокирована и блокирована. Поддерживаются два вида блокировок: простые и вложенные. Простые блокировки должны точно выдерживать равновесие захватов и освобождений. Является ошибкой повторный захват блокировки нитью, уже её захватившей.
Вложенные
блокировки
позволяют
владельцу
блокировки
многократно захватывать её, освобождая её только один раз. void omp_init_lock(omp_lock_t *lock); void omp_init_nest_lock(omp_nest_lock_t *lock);
subroutine omp_init_lock(svar) integer (kind=omp_lock_kind) svar subroutine omp_init_nest_lock(nvar) integer (kind=omp_nest_lock_kind) nvar
― Инициализирует переменную блокировки. До вызова она должна находиться в неинициализированном состоянии. void omp_destroy_lock(omp_lock_t *lock);
29
void omp_destroy_nest_lock(omp_nest_lock_t *lock);
subroutine omp_destroy_lock(svar) integer (kind=omp_lock_kind) svar
subroutine omp_destroy_nest_lock(nvar) integer (kind=omp_nest_lock_kind) nvar
― Разрушает блокировку, переводя соответствующую переменную в неинициализированное состояние. void omp_set_lock(omp_lock_t *lock); void omp_set_nest_lock(omp_nest_lock_t *lock);
subroutine omp_set_lock(svar) integer (kind=omp_lock_kind) svar
subroutine omp_set_nest_lock(nvar)
integer (kind=omp_nest_lock_kind) nvar ― Устанавливает блокировку. void omp_unset_lock(omp_lock_t *lock); void omp_unset_nest_lock(omp_nest_lock_t *lock);
subroutine omp_unset_lock(svar) integer (kind=omp_lock_kind) svar
30
subroutine omp_unset_nest_lock(nvar) integer (kind=omp_nest_lock_kind) nvar
― Освобождает блокировку. int omp_test_lock(omp_lock_t *lock); int omp_test_nest_lock(omp_nest_lock_t *lock);
logical function omp_test_lock(svar) integer (kind=omp_lock_kind) svar integer function omp_test_nest_lock(nvar) integer (kind=omp_nest_lock_kind) nvar
― Проверяет, установлена ли блокировка. 5.3.Измерение времени double precision function omp_get_wtime()
double omp_get_wtime(void);
― Возвращает затраченное время в секундах. double omp_get_wtick(void);
double precision function omp_get_wtick()
― Возвращает точность таймера, используемого предыдущей описанной
функцией.
6.Переменные среды Управлять поведением приложения использующего OpenMP можно задавая переменные среды. Имя
Формат
Умолчания в
Умолчания
переменной
значения
компиляторах
в Sun Studio 10
Intel OMP_NUM_THREADS
n
количество
нитей
в число процессоров 1
команде
OMP_SCHEDULE
schedule
предпочтительный
[,chunk]
алгоритм
при
STATIC
STATIC, N/P
FALSE
TRUE
распре-
делении обработки цикла
OMP_DYNAMIC
{TRUE |
Динамическое
FALSE}
определение числа нитей в команде
OMP_NESTED
{TRUE |
Обрабатывать
FALSE}
женные
вло- FALSE
FALSE
параллельные
области
6.1.Использованная литература 1. OpenMP Application Program Interface / Version 2.5 May 2005 ― OpenMP Architecture Review Board, 2005. 2. Богачёв К.Ю. Основы параллельного программирования. ― М.: БИНОМ. Лаборатория знаний, 2003. ― 342~с., ил. 3. Эндрюс Г.Р. Основы многопоточного, параллельного и распределенного программирования. ― М.: Изд. дом «Вильямс», 2003. ― 512 с.: ил.