Книжная полка Сохранить
Размер шрифта:
А
А
А
|  Шрифт:
Arial
Times
|  Интервал:
Стандартный
Средний
Большой
|  Цвет сайта:
Ц
Ц
Ц
Ц
Ц

Параллельное программирование над общей памятью. OpenMP

Покупка
Основная коллекция
Артикул: 778158.01.99
В учебном пособии приводится описание прикладного программного интерфейса OpenMP, рассматриваются примеры разработки, отладки и оптимизации параллельных программ на его основе, содержится лабораторный практикум.
Арыков, С. Б. Параллельное программирование над общей памятью. OpenMP : учебное пособие / С. Б. Арыков, М. А. Городничев, Г. А. Щукин. - Новосибирск : Изд-во НГТУ, 2019. - 95 с. - ISBN 978-5-7782-3796-4. - Текст : электронный. - URL: https://znanium.com/catalog/product/1866910 (дата обращения: 05.05.2024). – Режим доступа: по подписке.
Фрагмент текстового слоя документа размещен для индексирующих роботов. Для полноценной работы с документом, пожалуйста, перейдите в ридер.
Министерство науки и высшего образования Российской Федерации 

НОВОСИБИРСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ 

 
 
 
 
 
С.Б. АРЫКОВ,  
М.А. ГОРОДНИЧЕВ, Г.А. ЩУКИН 
 
 
 
 
ПАРАЛЛЕЛЬНОЕ 
ПРОГРАММИРОВАНИЕ 
НАД ОБЩЕЙ ПАМЯТЬЮ 
 
 
OpenMP 
 
 
Утверждено  
Редакционно-издательским советом университета 
в качестве учебного пособия 
 
 
 
 
 
НОВОСИБИРСК 
2019 

УДК 004.424.032.24 (075.8) 
   А 895 
 
 
 
Рецензенты 
д-р техн. наук, профессор Б.М. Глинский 
канд. техн. наук, доцент В.П. Маркова 
 
 
 
Работа подготовлена на кафедре Параллельных вычислительных 
технологий для студентов ФПМИ направлений «Прикладная  
математика и информатика» и «Математическое обеспечение  
и администрирование информационных систем». 
 
 
 
Арыков С.Б. 
А 895  
Параллельное программирование над общей памятью. OpenMP: 
учебное пособие / С.Б. Арыков, М.А. Городничев, Г.А. Щукин. – 
Новосибирск: Изд-во НГТУ, 2019. – 95 с. 

ISBN 978-5-7782-3796-4 

В учебном пособии приводится описание прикладного программного интерфейса OpenMP, рассматриваются примеры разработки,  
отладки и оптимизации параллельных программ на его основе, содержится лабораторный практикум. 
 
 
 
УДК 004.424.032.24 (075.8) 
 
 
 
ISBN 978-5-7782-3796-4 
© Арыков С.Б., Городничев М.А., 
 
    Щукин Г.А., 2019 
 
© Новосибирский государственный 
 
    технический университет, 2019 

ОГЛАВЛЕНИЕ 
 

Предисловие ............................................................................................................. 5 

Введение ................................................................................................................... 7 

1. Параллельные области ...................................................................................... 10 

Модель вычислений ......................................................................................... 10 
Объявление параллельной области ................................................................ 15 
Синхронизация потоков .................................................................................. 23 

2. Конструкции распределения работы ................................................................ 27 

Параллельные циклы ....................................................................................... 27 
Параллельные секции ...................................................................................... 31 
Выполнение работы одним потоком .............................................................. 33 

3. Параллельные задачи ......................................................................................... 34 

Явное объявление задач ................................................................................... 34 
Типичные ошибки использования задач ........................................................ 38 

4. Векторные операции .......................................................................................... 41 

Векторизация циклов ....................................................................................... 41 
Использование функций в векторизуемых циклах ....................................... 43 

5. Отладка параллельных программ ..................................................................... 47 

Инструменты отладки ...................................................................................... 47 
Поиск ошибки типа «гонки данных» .............................................................. 48 
Поиск ошибки типа «дедлок» ......................................................................... 59 

6. Оптимизация параллельных программ ............................................................ 64 

Инструменты профилирования ....................................................................... 65 
Оптимизация синхронизации потоков ........................................................... 65 
Комплексная оптимизация .............................................................................. 69 

7. Лабораторный практикум ................................................................................. 82 
Лабораторная работа № 1. Параллельные циклы .......................................... 83 
Лабораторная работа № 2. Параллельные задачи ......................................... 85 
Лабораторная работа № 3. Отладка и оптимизация ...................................... 86 
Подготовка отчета по лабораторной работе .................................................. 87 
Библиографический список .................................................................................. 88 

Приложение А. Требования к отчету ................................................................... 91 
Приложение Б. Шаблон титульного листа отчета о лабораторной работе ....... 94 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

ПРЕДИСЛОВИЕ 

Пособие предназначено для студентов дневной формы обучения 
Факультета прикладной математики и информатики НГТУ, направления подготовки «Прикладная математика и информатика» (дисциплина 
«Основы параллельного программирования») и «Математическое 
обеспечение и администрирование информационных систем» (дисциплина «Параллельное программирование»). 
Учебное пособие содержит введение в проблематику параллельного программирования с использованием прикладного программного 
интерфейса OpenMP. В разделах 1–4 содержится подробное описание 
директив OpenMP с примерами использования. Рассматривается модель вычислений OpenMP, распределение работы в параллельных циклах и секциях, использование редукции, синхронизации, параллелизма 
задач и векторизации. 
Разделы 5 и 6 посвящены отладке и оптимизации параллельных 
программ с помощью интегрированных сред разработки Oracle 
Developer Studio и Intel Parallel Studio XE. На простых примерах пошагово разбирается использование этих инструментов для поиска типичных ошибок (гонок данных, дедлоков) и устранения типичных проблем с производительностью (нерациональное использование кэшпамяти, большая доля последовательного кода). 
В разделе 7 представлен лабораторный практикум. Он ориентирован на закрепление теоретических знаний и развитие практических 
навыков использования OpenMP. Каждая лабораторная работа содержит материал, структурированный определенным образом: цель работы, порядок выполнения работы, варианты заданий для самостоятельной работы, контрольные вопросы. Кроме лабораторных работ раздел 
содержит методическую информацию о компиляции параллельных 
программ, в которых используется OpenMP, и о правилах подготовки 
отчётов.  

В пособии рассматривается спецификация OpenMP версии 4.5,  
а точнее – только ее часть, касающаяся использования OpenMP с языками С/С++. Опущены некоторые аспекты OpenMP, которые не входят 
в программы учебных дисциплин «Основы параллельного программирования» и «Параллельное программирование». В частности, не описываются переменные окружения и большинство библиотечных функций, директивы работы с внешними устройствами, механизм отмены 
исполнения; вскользь упоминаются возможности по заданию зависимостей между задачами. 
Для успешного овладения материалом пособия необходимы базовые знания языка C или C++. Желателен опыт программирования в ОС 
Linux. 
В результате изучения материала пособия студент должен: 
знать 
 модель вычислений OpenMP; 
 основные директивы OpenMP и их опции; 
 основные примитивы синхронизации для разработки параллельных программ; 
уметь 
 применять директивы OpenMP и их опции для разработки параллельных программ; 
 создавать законченные параллельные программы на основе 
OpenMP; 
 выполнять векторизацию циклов с помощью OpenMP; 
 находить ошибки в параллельных программах на основе 
OpenMP; 
 выполнять несложную оптимизацию параллельных программ на 
основе OpenMP; 
владеть 
 методами параллельного программирования с использованием 
OpenMP; 
 навыками применения отладчиков Oracle Thread Analyzer и Intel 
Inspector для поиска ошибок в параллельных программах; 
 навыками применения профилировщиков Oracle Performance 
Analyzer и Intel VTune Amplifier для оптимизации параллельных программ. 
 

ВВЕДЕНИЕ 

Прикладной программный интерфейс OpenMP® (англ. OpenMP 
Application Programming Interface, OpenMP API) – средство для задания 
параллельного выполнения операций в модели общей памяти, а также 
для управления вычислениями на сопроцессорах в программах на языках C/C++/Fortran. Спецификации интерфейса разрабатываются под 
контролем некоммерческого консорциума OpenMP Architecture Review 
Boards (OpenMP ARB), объединяющего такие компании как IBM, Intel, 
AMD, Nvidia и др. В пособии рассматривается версия 4.5 [7], изданная 
в 2015 году. 
Одной из идей, приведших к появлению спецификации OpenMP, 
стала идея «инкрементного распараллеливания». Она предполагает, 
что параллельная программа разрабатывается на основе последовательного кода, например, последовательной программы на языке С. 
Программист с помощью директив компилятора размечает код последовательной программы, явно выделяя независимые блоки. Компилятор генерирует код, обеспечивая распределение независимых блоков 
между несколькими потоками. Чтобы компилятор «понял» директивы 
OpenMP, как правило, необходимо включить специальную опцию. 
Иначе эти директивы будут проигнорированы и сгенерируется обычная последовательная программа. 
Спецификация OpenMP предполагает, что на программисте лежит 
вся ответственность за принятие решений о том, какие части кода могут выполняться параллельно, о синхронизации параллельных потоков. 
Все решения выражаются программистом явно через средства 
OpenMP. Спецификация не накладывает на компиляторы или библиотеки поддержки времени выполнения, реализующие OpenMP, никаких 
обязательств по проверке или обеспечению корректности взаимодействия параллельных потоков. 

Спецификация OpenMP развивалась с 1997 г. Версия 1.0 (1997–
1998 гг.), главным образом, была посвящена распараллеливанию циклов. Это обеспечивало реализацию модели «параллелизма по данным» 
[4] и соответствующим образом ограничивало круг приложений. Дальнейшее развитие программного интерфейса было обусловлено стремлением OpenMP ARB создать универсальный инструмент разработки 
эффективных переносимых параллельных программ, учитывающий 
тенденции в развитии аппаратного обеспечения. В спецификации 3.0 
(2008 г.) были введены конструкции для реализации модели «параллелизма задач»: стало возможным описывать множество «задач» – программных блоков, задающих произвольные независимые вычисления. 
В спецификации версии 4.0 (2014 г.) появились инструменты для программирования аппаратных ускорителей, задания векторных (SIMD) 
инструкций, обработки ошибочных ситуаций, управления привязкой 
потоков к ядрам вычислительной системы, задания зависимостей между задачами. Основными нововведениями версии 5.0 [12] стали улучшенные возможности по поддержке специализированных аппаратных 
ускорителей и средства для взаимодействия с внешними инструментами отладки и оптимизации. 
Преимущества применения OpenMP по сравнению с параллельным 
программированием на уровне потоков (например, POSIX Threads [5]) 
заключаются в следующем:  
 более высокий уровень программирования: программист указывает, какие части программы могут быть выполнены независимо друг 
от друга, но не занимается непосредственно управлением потоками 
операционной системы; 
 эффективная переносимость: программы, следующие спецификациям OpenMP исполняются на вычислительных системах различных 
производителей без изменений, для их сборки требуется только компилятор, реализующий соответствующую спецификацию; особо  
следует подчеркнуть, что спецификация OpenMP широко поддержана 
производителями аппаратных и программных средств, поэтому можно 
ожидать, что программы, разработанные с применением OpenMP, будут продолжать работать на будущих аппаратных и программных 
платформах; 
 относительно легкая трансформация имеющегося последовательного кода в параллельный. 

Спецификация прикладного программного интерфейса OpenMP 
включает в себя описания: 
 директив компиляторов языков С/С++/Fortran, с помощью которых программист размечает код, чтобы объяснить компилятору, как 
организовать вычисления параллельным образом; 
 библиотеки функций, которые дают возможность управлять ходом исполнения параллельной программы; 
 переменных окружения, позволяющих настроить параметры 
компиляции и библиотеку времени выполнения (например, задать максимально допустимое количество потоков). 
Для общего знакомства с OpnMP подойдут книги [1–3]. Для глубокого и всестороннего изучения темы рекомендуется обратиться к оригинальной спецификации [7]. Для знакомства с теорией параллельного 
программирования рекомендуется книга [4]. 
 
 
 
 
 

1. ПАРАЛЛЕЛЬНЫЕ ОБЛАСТИ 

МОДЕЛЬ ВЫЧИСЛЕНИЙ 

Модель программы 

Основным инструментом OpenMP, с помощью которого программист объясняет компилятору, как организовать параллельные вычисления, являются директивы. Каждая директива имеет вид: 

#pragma omp <directive-name> [ <clause> [ [,] <clause> ] ... ] new-line 
<structured-block> 

Здесь #pragma omp – обязательный префикс любой директивы 
OpenMP, <directive-name> – имя директивы, <clause> – опции директивы, new-line – обязательный перевод строки, <structured-block> – исполняемая инструкция (англ. statement) [18] языков С/С++, возможно 
сложная, например, цикл for, while или блок инструкций. Для различных директив поддерживаются различные наборы опций. Каждая опция имеет свое имя. Объявления внутри квадратных скобок могут быть 
опущены.  
Директивы делятся на декларативные (англ. declarative) и исполняемые (англ. executable). Декларативные директивы служат для порождения объявлений объектов, например, директива 

#pragma omp declare simd 

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

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

#pragma omp parallel for 

требует исполнить следующий за ней цикл типа for параллельно за 
счет распределения итераций цикла между несколькими потоками. 

Модель исполнения 

В терминологии спецификации OpenMP выполнение программы 
состоит в том, что потоки (англ. threads) выполняют множество так 
называемых задач (англ. task). Задачи разделяются на два подмножества: определяемые явно (посредством директивы task) и неявно.  
В частности, неявно определенной задачей является начальная задача 
(англ. initial task), которая состоит в выполнении всей программы. Выполнение начальной задачи осуществляет начальный поток. В ходе 
выполнения задач могут порождаться другие задачи, потоки могут переключаться между задачами, выполнение или продолжение выполнения задач может зависеть от завершения других задач. 
Спецификация OpenMP предполагает [7, с. 14], что параллельные 
вычисления реализуются по модели fork-join [4], как показано на 
рис. 1. 
 

Порождение команды из N потоков: fork 

0 
1 
2
N-1 

Завершение выполнения параллельной области: join 

Выполнение параллельной 
области командой потоков

 
Рис. 1. Модель fork-join 

Когда какой-либо поток, в том числе начальный, в ходе своего выполнения встречает директиву OpenMP parallel (см. раздел «Объявле
ние параллельной области»), поток порождает так называемую команду потоков (англ. team), состоящую как минимум из одного потока. 
Происходит порождение неявных задач – по одной задаче на поток. 
Суть каждой задачи состоит в выполнении кода, заключенного в рамках конструкции parallel. Каждый поток получает свой идентификатор 
(натуральное число от 0 до размер команды-1). Порождающий поток в 
контексте порожденной им команды называется мастер-потоком 
(англ. master-thread) и имеет идентификатор 0. В конце области действия директивы parallel предполагается неявная барьерная синхронизация: все потоки команды ожидают завершения задач другими потоками, затем команда расформировывается, и выполнение кода после 
области действия директивы parallel осуществляет поток, встретивший 
директиву parallel. Код, который выполняется командой потоков, 
называется параллельной областью. Для общности терминологии считается, что вся программа заключена в неявную параллельную область, 
которая выполняется командой из одного начального потока. 
В ходе выполнения задач могут порождаться другие задачи. Они 
делятся на отложенные (англ. deferred), которые ставятся в очередь на 
выполнение при том, что продолжается выполнение породивших их 
задач, и неотложные (англ. undeferred), которые выполняются немедленно и на время их выполнения приостанавливается (англ. suspend) 
выполнение породивших их задач. Кроме того, задачи разделяются на 
привязанные (англ. tied) – выполнение которых после приостановки 
обязательно осуществляется теми же потоками, которые выполняли их 
до приостановки, и непривязанные (англ. untied) – выполнение которых 
после приостановки может осуществляться произвольными потоками 
из команды, к которой принадлежит породивший их поток. Так, задачи, неявно порождаемые директивой parallel, являются привязанными. Код явно порождаемых задач не считается частью параллельной 
области. 
Спецификация определяет так называемые точки планирования задач (англ. task scheduling points) [7, с. 94]. Когда поток в ходе выполнения какой-либо задачи достигает такой точки, выполнение текущей 
задачи может быть приостановлено и поток будет переключен на выполнение другой задачи из очереди задач. Если текущая задача относится к классу привязанных, то ее выполнение будет возобновлено выполнявшем ее ранее потоком. Возобновить выполнение непривязанной 
задачи может другой поток.