Опубликован: 28.10.2009 | Уровень: специалист | Доступ: платный
Лекция 5:

Параллельное программирование с использованием OpenMP

7.9. Краткий обзор раздела

Данный раздел посвящен рассмотрению методов параллельного программирования для вычислительных систем с общей памятью с использованием технологии OpenMP.

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

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

В подразделе 7.2 проводится быстрое и простое введение в разработку параллельных программ с использованием OpenMP. Дается описание директивы parallel и приводится пример первой параллельной программы с использованием OpenMP. В подразделе обсуждаются важные для дальнейшего рассмотрения понятия фрагмента, области и секции параллельной программы.

В подразделе 7.3 рассматриваются вопросы распределения вычислительной нагрузки между потоками на примере распараллеливания циклов по данным. Дается описание директивы for и описываются способы управления распределением итераций цикла между потоками.

В подразделе 7.4 подробно обсуждаются вопросы управления данными для параллельно выполняемых потоков. Дается понятие общих и локальных переменных для потоков. Приводится описание важной и часто встречающейся при обработке общих данных операции редукции.

В подразделе 7.5 рассматриваются вопросы организации взаимоисключения при использовании общих переменных. Среди описываемых подходов - использование атомарных ( неделимых ) операций, определение критических секций, применение семафоров специального типа ( замков ).

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

В подразделе 7.7 рассматриваются расширенные возможности технологии OpenMP. Дается описание ряда новых директив ( master, single, barrier, flush, threadprivate, copyin ), обсуждаются возможности управления потоками (количество создаваемых потоков, динамический режим создания потоков, вложенность параллельных фрагментов).

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

7.10. Обзор литературы

В наиболее полном виде информация по параллельному программированию для вычислительных систем с общей памятью с использованием OpenMP содержится в Chandra et al. (2000). Краткое описание OpenMP приводится в Воеводин В.В. и Воеводин Вл.В. (2002) и Немнюгин и Стесик (2002), полезная информация представлена также в Kumar et al. (1994), Quinn (2004).

Достаточно много информации о технологии OpenMP содержится в сети Интернет. Так, могут быть рекомендованы информационно-аналитический портал www.parallel.ru и, конечно же, ресурс www.openmp.org.

Дополнительная информация по разработке многопоточных программ содержится в Вильямс (2001) (для ОС Windows) и Butenhof (1997) (стандарт POSIX Threads).

Для рассмотрения общих вопросов параллельного программирования для вычислительных систем с общей памятью может быть рекомендована работа Andrews (2000).

7.11. Контрольные вопросы

  1. Какие компьютерные платформы относятся к числу вычислительных систем с общей памятью?
  2. Какие подходы используются для разработки параллельных программ?
  3. В чем состоят основы технологии OpenMP?
  4. В чем состоит важность стандартизации средств разработки параллельных программ?
  5. В чем состоят основные преимущества технологии OpenMP?
  6. Что понимается под параллельной программой в рамках технологии OpenMP?
  7. Что понимается под понятием потока (thread)?
  8. Какие возникают проблемы при использовании общих данных в параллельно выполняемых потоках?
  9. Какой формат записи директив OpenMP?
  10. В чем состоит назначение директивы parallel?
  11. В чем состоит понятие фрагмента, области и секции параллельной программы?
  12. Какой минимальный набор директив OpenMP позволяет начать разработку параллельных программ?
  13. Как определить время выполнения OpenMP программы?
  14. Как осуществляется распараллеливание циклов в OpenMP? Какие условия должны выполняться, чтобы циклы могли быть распараллелены?
  15. Какие возможности имеются в OpenMP для управления распределением итераций циклов между потоками?
  16. Как определяется порядок выполнения итераций в распараллеливаемых циклах в OpenMP?
  17. Какие правила синхронизации вычислений в распараллеливаемых циклах в OpenMP?
  18. Как можно ограничить распараллеливание фрагментов программного кода с невысокой вычислительной сложностью?
  19. Как определяются общие и локальные переменные потоков?
  20. Что понимается под операцией редукции?
  21. Какие способы организации взаимоисключения могут быть использованы в OpenMP?
  22. Что понимается под атомарной (неделимой) операцией?
  23. Как определяется критическая секция?
  24. Какие операции имеются в OpenMP для переменных семафорного типа (замков)?
  25. В каких ситуациях следует применять барьерную синхронизацию?
  26. Как осуществляется в OpenMP распараллеливание по задачам (директива sections )?
  27. Как определяются однопотоковые участки параллельных фрагментов (директивы single и master )?
  28. Как осуществляется синхронизация состояния памяти (директива flush )?
  29. Как используются постоянные локальные переменные потоков (директивы threadprivate и copyin )?
  30. Какие средства имеются в OpenMP для управления количеством создаваемых потоков?
  31. Что понимается под динамическим режимом создания потоков?
  32. Как осуществляется управление вложенностью параллельных фрагментов?
  33. В чем состоят особенности разработки параллельных программ с использованием OpenMP на алгоритмическом языке Fortran?
  34. Как обеспечивается единственность программного кода для последовательного и параллельного вариантов программы?
  35. Какие компиляторы обеспечивают поддержку технологии OpenMP?

7.12. Задачи и упражнения

  1. Разработайте программу для нахождения минимального (максимального) значения среди элементов вектора.
  2. Разработайте программу для вычисления скалярного произведения двух векторов.
  3. Разработайте программу для задачи вычисления определенного интеграла с использованием метода прямоугольников
    1. .

    (описание методов интегрирования дано, например, в Kahaner, Moler and Nash (1988)).

  4. Разработайте программу решения задачи поиска максимального значения среди минимальных элементов строк матрицы (такая задача имеет место для решения матричных игр)

    ,

  5. Разработайте программу для задачи 4 при использовании матриц специального типа (ленточных, треугольных и т.п.). Определите время выполнения программы и оцените получаемое ускорение. Выполните вычислительные эксперименты при разных правилах распределения итераций между потоками и сравните эффективность параллельных вычислений (выполнение таких экспериментов целесообразно выполнить для задач, в которых вычислительная трудоемкость итераций циклов является различной).
  6. Реализуйте операцию редукции с использованием разных способов организации взаимоисключения (атомарные операции, критические секции, синхронизацию при помощи замков). Оцените эффективность разных подходов. Сравните полученные результаты с быстродействием операции редукции, выполняемой посредством параметра reduction директивы for.
  7. Разработайте программу для вычисления скалярного произведения для последовательного набора векторов (исходные данные можно подготовить заранее в отдельном файле). Ввод векторов и вычисление их произведения следует организовать как две раздельные задачи, для распараллеливания которых используйте директиву sections.
  8. Выполните вычислительные экспериментами с ранее разработанными программами при различном количестве потоков (меньше, равно или больше числа имеющихся вычислительных элементов). Определите время выполнения программ и оцените получаемое ускорение.
  9. Уточните, поддерживает ли используемый Вами компилятор вложенные параллельные фрагменты. При наличии такой поддержки разработайте программы с использованием и без использования вложенного параллелизма. Выполните вычислительные эксперименты и оцените эффективность разных подходов.
  10. Разработке программу для задачи 4 с использованием распараллеливания циклов разного уровня вложенности. Выполните вычислительные эксперименты и сравните полученные результаты. Оцените величину накладных расходов на создание и завершение потоков.

Приложение: Справочные сведения об OpenMP

П1. Сводный перечень директив OpenMP

Для справки приведем перечень директив OpenMP с кратким пояснением их назначения.

Таблица П1. Сводный перечень директив OpenMP
Директива Описание
parallel [<параметр>…] Директива определения параллельного фрагмента в коде программы (подраздел 7.2). Параметры: if, private, shared, default, firstprivate, reduction, copyin, num_threads
for [<параметр>…] Директива распараллеливания циклов (подраздел 7.2). Параметры: private, firstprivate, lastprivate, reduction, ordered, nowait, schedule
sections [<параметр>…] Директива для выделения программного кода, который далее будет разделен на параллельно выполняемые параллельные секции (подраздел 7.6). Выделение параллельных секций осуществляется при помощи директивы section. Параметры: private, firstprivate, lastprivate, reduction, nowait
section Директива выделения параллельных секций - должна располагаться в блоке директивы sections (подраздел 7.6).
single [<параметр>…] Директива для выделения программного кода в параллельном фрагменте, исполняемого только одним потоком (п. 7.7.1). Параметры: private, firstprivate, copyprivate, nowait
parallel for [< параметр >… Объединенная форма директив parallel и for (подраздел 7.2). Параметры: private, firstprivate, lastprivate, shared, default, reduction, ordered, schedule, copyin, if, num_threads
parallel sections [<параметр>… Объединенная форма директив parallel и sections (подраздел 7.6). Параметры: private, firstprivate, lastprivate, shared, default, reduction, copyin, if, num_threads
master Директива для выделения программного кода в параллельном фрагменте, исполняемого только основным ( master ) потоком (п. 7.7.1).
critical [(name)] Директива для определения критических секций (п. 7.5.2).
barrier Директива для барьерной синхронизации потоков (п. 7.7.2).
atomic Директива для определения атомарной (неделимой) операции (п. 7.5.1).
flush [list] Директива для синхронизации состояния памяти (п. 7.7.3).
threadprivate (list) Директива для определения постоянных локальных переменных потоков (п. 7.7.4).
ordered Директивы управления порядком вычислений в распараллеливаемом цикле (п. 7.3.2). При использовании данной директивы в директиве for должен быть указан одноименный параметр ordered

П2. Сводный перечень параметров директив OpenMP

Для справки приведем перечень параметров директив OpenMP с кратким пояснением их назначения.

Таблица П2. Сводный перечень параметров директив OpenMP
Параметр Описание
private (list) Параметр для создания локальных копий для перечисленных в списке переменных для каждого имеющегося потока (п. 7.4.1). Исходные значения копий не определены. Директивы: parallel, for, sections, single
firstprivate ( list ) Тоже что и параметр private и дополнительно инициализация создаваемых копий значениями, которые имели перечисленные в списке переменные перед началом параллельного фрагмента (п. 7.4.1). Директивы: parallel, for, sections, single
lastprivate (list) Тоже что и параметр private и дополнительно запоминание значений локальных переменных после завершения параллельного фрагмента (п. 7.4.1). Директивы: for, sections
shared ( list ) Параметр для определения общих переменных для всех имеющихся потоков (п. 7.4.1). Директивы: parallel
default ( shared | none ) Параметр для установки правила по умолчанию на использование переменных в потоках (п. 7.4.1). Директивы: parallel
reduction ( operator: list ) Параметр для задания операции редукции (п. 7.4.2). Директивы: parallel, for, sections
nowait Параметр для отмены синхронизации при завершении директивы. Директивы: for, sections, single
if (expression) Параметр для задания условия, только при выполнении которого осуществляется создание параллельного фрагмента (п. 7.3.4). Директивы: parallel
ordered Параметр для задания порядка вычислений в распараллеливаемом цикле (п. 7.3.2). Директивы: for
schedule (type [, chunk]) Параметр для управления распределением итераций распараллеливаемого цикла между потоками (п. 7.3.1). Директивы: for
copyin (list) Параметр для инициализации постоянных переменных потоков (п. 7.7.4). Директивы: parallel
copyprivate (list) Копирование локальных переменных потоков после выполнения блока директивы single (п. 7.7.1). Директивы: single
num_treads Параметр для задания количества создаваемых потоков в параллельной области (п. 7.7.5). Директивы: parallel

Приведем для наглядности сводную таблицу использования параметров в директивах OpenMP.

Таблица П3. Сводная таблица по использованию параметров в директивах OpenMP
Параметр Директива
parallel for sections single parallel for parallel sections
if ( ( (
private ( ( ( ( ( (
shared ( ( ( (
default ( ( (
firstprivate ( ( ( ( ( (
lastprivate ( ( ( (
reduction ( ( ( ( (
copyin ( ( (
schedule ( (
ordered ( (
nowait ( ( (
num_threads ( (
copyprivate (

П3. Сводный перечень функций OpenMP

Для справки приведем перечень функций библиотеки OpenMP с кратким пояснением их назначения.

Таблица П4. Сводный перечень функций OpenMP
Функция Описание
void omp_set_num_threads (int num_threads) Установить количество создаваемых потоков (п. 7.7.5)
int omp_get_max_threads (void) Получение максимально-возможного количества потоков (п. 7.7.5)
int omp_get_num_threads (void) Получение количества потоков в параллельной области программы (п. 7.7.5)
int omp_get_thread_num (void) Получение номера потока (п. 7.7.5)
int omp_get_num_procs (void) Получение числа вычислительны элементов (процессоров или ядер), доступных приложению (п. 7.7.5)
void omp_set_dynamic (int dynamic) Установить режим динамического создания потоков (п. 7.7.6)
int omp_get_dynamic (void) Получение состояние динамического режима (п. 7.7.6)
void omp_set_nested (int nested) Установить режим поддержки вложенных параллельных фрагментов (п. 7.7.7)
int omp_get_nested (void) Получения состояние режима поддержки вложенных параллельных фрагментов (п. 7.7.7)
void omp_init_lock (omp_lock_t *lock) 
void omp_init_nest_lock(omp_nest_lock_t *lock)
Инициализировать замок (п. 7.5.3)
void omp_set_lock (omp_lock_t &lock)
void omp_set_nest_lock (omp_nest_lock_t &lock)
Установить замок (п. 7.5.3)
void omp_unset_lock (omp_lock_t &lock)
void omp_unset_nest_lock (omp_nest_lock_t &lock)
Освободить замок (п. 7.5.3)
int omp_test_lock (omp_lock_t &lock)
int  omp_test_nest_lock (omp_nest_lock_t &lock)
Установить замок без блокировки (п. 7.5.3)
void omp_destroy_lock(omp_lock_t &lock)
void omp_destroy_nest_lock(omp_nest_lock_t &lock)
Перевод замка в неинициализированное состояние (п. 7.5.3)
double omp_get_wtime (void) Получение времени текущего момента выполнения программы (п. 7.2.5)
double omp_get_wtick (void) Получение времени в секундах между двумя последовательными показателями времени аппаратного таймера (п. 7.2.5)
int omp_in_parallel (void) Проверка нахождения программы в параллельном фрагменте

П4. Сводный перечень переменных окружения OpenMP

Для справки приведем перечень переменных окружения OpenMP с кратким пояснением их назначения.

Таблица П5. Сводный перечень переменных окружения OpenMP
Переменная Описание
OMP_SHEDULE Переменная для задания способа управления распределением итераций распараллеливаемого цикла между потоками (п. 7.3.1). Значение по умолчанию: static
OMP_NUM_THREADS Переменная для задания количество потоков в параллельном фрагменте (п. 7.7.5). Значение по умолчанию: количество вычислительных элементов (процессоров/ядер) в вычислительной системе.
OMP_DYNAMIC Переменная для задания динамического режима создания потоков (п. 7.7.6). Значение по умолчанию: false.
OMP_NESTED Переменная для задания режима вложенности параллельных фрагментов (п. 7.7.7). Значение по умолчанию: false.
Алексей Николаев
Алексей Николаев
Россия, г. Саранск
Рамиль Ариков
Рамиль Ариков
Россия, Республика Мордовия