Параллельное программирование над общей памятью. POSIX Threads. Учебное пособие
.pdfдолжен соответствовать характеру зависимости между количеством операций алгоритма и размером задачи: так, если время умножения квадратных матриц размера N на P процессорных ядрах составляет M секунд, то время умножения матриц размера 2•N на P процессорных ядрах должно быть близко к 8•M.
Если наблюдаемая картина не соответствует ожиданиям, в отчете должно быть сформулировано обоснование и дано пояснение, может ли программа быть оптимизирована, чтобы это несоответствие устранить. Примером такой ситуации может быть скачкообразное увеличение времени работы программы, объясняющееся выходом данных за пределы кэш-памяти третьего уровня.
В отчете по лабораторной работе должны быть указаны характеристики вычислительной системы и системного программного обеспечения, на которых производилось тестирование (см. образец в табл. 6), в том числе: наименование процессора и его частота, объем оперативной памяти, операционная система, производитель и версия компилятора, опции оптимизации компилятора и другие имеющие значение параметры.
|
|
Таблица 6 |
|
|
Список использованных вычислительных систем |
||
|
|
|
|
№ |
Описание системы |
||
п/п |
|||
|
|
||
1 |
Аппаратная конфигурация |
ЦП Intel Core i5-8250U @ 1.60 GHz |
|
|
|
(гипертрединг включен), ОЗУ 4 ГБ |
|
|
Программная конфигура- |
ОС Windows 7, компилятор Intel C++ |
|
|
ция |
Compiler v. 18.0 (уровень оптимизации |
|
|
|
-O3) |
|
Результаты измерений времени исполнения программы необходимо представить в отчете в виде таблиц (см. образец в табл. 7). В заголовок таблицы включается ссылка на конфигурацию вычислительной системы. Если используются логические ядра, то рядом с количеством ядер указываются символы HT (англ. Hyper-threading). Все измерения должны выполняться в отсутствие другой вычислительной нагрузки на процессоры (во всех приведенных примерах предполагается, что вначале занимаются все физические ядра и только потом начинают использоваться логические ядра HT).
71
Таблица 7
Время (с) работы программы умножения квадратных матриц при различных размерах задачи и количестве процессорных ядер на вычислительной системе № 1 из табл. 6
|
|
Количество ядер |
|
|||
Размер задачи |
1 |
2 |
3 |
4 |
8 (HT) |
|
(сторона матрицы) |
||||||
|
|
|
|
|
||
64 |
0,0005 |
0,0003 |
0,0008 |
0,0012 |
0,0021 |
|
512 |
0,2764 |
0,1397 |
0,0941 |
0,0718 |
0,0823 |
|
1024 |
2,3123 |
1,1565 |
0,7942 |
0,5913 |
0,3623 |
|
4096 |
148,3242 |
74,1832 |
50,4323 |
37,1234 |
20,5638 |
|
Подробные рекомендации по измерению времени исполнения программы приведены в разделе 4.3 учебного пособия [6]. Отметим некоторые из них.
Для получения достоверных результатов (чтобы исключить влияние посторонних процессов в операционной системе компьютера) необходимо при одинаковых условиях многократно повторить измерение времени исполнения программы и выбрать наименьшее время.
Рекомендуется измерять астрономическое время работы программы.
Необходимо измерять время исполнения не всей программы, а только ее вычислительной части, без учета операций ввода / вывода, если преподавателем специально не оговорено иное.
Ускорение и эффективность
Судить о качестве параллельной программы позволяют также производные характеристики от времени исполнения программы:
ускорение программы SP на P ядрах – отношение времени работы программы на одном ядре T1 ко времени работы программы на P ядрах TP при тех же входных данных: SP = T1 / TP;
эффективность работы программы EP на P ядрах – отношение ускорения на P ядрах SP к количеству ядер P: EP = SP / P.
Необходимо стремиться к тому, чтобы на P ядрах программа достигала ускорения в P раз относительно времени выполнения на одном ядре T1. Как правило, наблюдается меньшее ускорение, что связано с накладными расходами на организацию параллельных вычисле-
72
ний: порождение дополнительных потоков, синхронизация потоков при доступе к общим данным и т. д. В задачу программиста входит минимизация таких расходов. В некоторых задачах получается достигать «сверхлинейного» ускорения, когда на P ядрах программа работает быстрее, чем в P раз. Для объяснения этих явлений необходимы знания об архитектуре процессора, которые можно найти в книге [6].
Эффективность параллельной программы оценивается относительно последовательной, реализующей тот же самый алгоритм, и позволяет судить о том, какая доля времени в работе параллельной программы тратится на вычислительные операции алгоритма, а какую долю занимают накладные расходы на организацию параллельных вычислений. В предположении, что последовательная программа загружает ядро процессора максимально полно (на 100 %), характеристика эффективности позволяет оценить, насколько полно параллельная программа нагружает P процессорных ядер. В процессорах с технологией Hyper-
threading, где физически присутствует |
P |
ядер, а логически – 2*P, |
|
иногда использование большего количества потоков T > P позволяет |
|||
получать дополнительное ускорение |
ST > SP. |
Поэтому имеет смысл |
|
исследовать ускорение и эффективность |
для |
различных вариантов |
|
T > P. Эффективность для случая T > P |
рассчитывается по форму- |
||
ле ET = ST / P.
Характеристики ускорения и эффективности в отчетах по лабораторным работам необходимо представлять в табличном виде (см. образец в табл. 8) и в виде графиков (см. образцы на рис. 4 и 5).
Таблица 8
Ускорение S и эффективность E работы программы умножения квадратных матриц при различных размерах задачи и количестве процессорных ядер на вычислительной системе № 1 из табл. 6
|
|
|
Количество ядер |
|
|||
Размер задачи |
Ускорение |
|
|
|
|
|
|
(сторона матри- |
и эффектив- |
1 |
2 |
3 |
4 |
8 (HT) |
|
цы) |
ность |
|
|
|
|
|
|
64 |
S |
1 |
1,67 |
0,63 |
0,42 |
0,24 |
|
E |
1 |
0,84 |
0,21 |
0,11 |
0,06 |
||
|
|||||||
|
|
|
|
|
|
|
|
512 |
S |
1 |
1,98 |
2,94 |
3,85 |
3,35 |
|
|
|
|
|
|
|
||
E |
1 |
0,99 |
0,98 |
0,96 |
0,84 |
||
|
|||||||
|
|
|
|
|
|
|
|
73
Ускорение
4,5
4
3,5
3
2,5
2
1,5
1
0,5
0
64
512
1 |
2 |
3 |
4 |
8(HT) |
Количество ядер
Рис. 4. Ускорение работы программы умножения квадратных матриц при различных размерах задачи и количестве процессорных ядер на вычислительной системе № 1 из табл. 6
Для краткости примеров в таблице и графиках количество вариантов размеров задачи уменьшено относительно табл. 7, однако в отчетах по лабораторным работам требуется приводить показатели для всех вариантов.
Эффективность
1,2
1
0,8
0,6
0,4
0,2
0
64
512
1 |
2 |
3 |
4 |
8(HT) |
Количество ядер
Рис. 5. Эффективность работы программы умножения квадратных матриц при различных размерах задачи и количестве процессорных ядер на вычислительной системе № 1 из табл. 6
74
ЛАБОРАТОРНАЯ РАБОТА №1 ПРОГРАММИРОВАНИЕ НЕЗАВИСИМЫХ ПОТОКОВ
Цель работы
Познакомиться с базовыми возможностями многопоточного программирования; научиться работать с потоками, не имеющими информационных зависимостей.
Порядок выполнения работы
1.Изучить теоретическую часть из раздела 1 настоящего пособия.
2.Записать программу из примера 1. Скомпилировать ее и проверить корректность работы.
3.Доработать программу с целью поддержки n потоков.
4.Оценить стоимость запуска одного потока операционной системой. Изменяя количество операций (можно использовать любую арифметическую операцию), которые исполняет функция потока, определить такое их количество, чтобы порождение потока было оправданным.
5.Добавить в программу возможность запуска потоков с разными атрибутами (см. пример 2).
6.Добавить в программу возможность передавать в поток сразу несколько параметров (см. пример 3).
7.Добавить в функцию потока возможность вывода информации о всех параметрах потока, с которыми он был создан.
8.Разработать программу, которая обеспечивает параллельное применение заданной функции к каждому элементу массива. Размер массива, применяемая функция и количество потоков задаются динамически.
9.Выполнить задание для самостоятельной работы (вариант согласовывается с преподавателем), по результатам подготовить отчет.
Варианты заданий для самостоятельной работы
Создать упрощенный HTTP-сервер, отвечающий на любой запрос клиента (например, браузера) строкой «Request number <номер запроса> has been processed», где под номером запроса понимается порядковый номер, присвоенный запросу сервером. Нумерация начинается с единицы.
75
1. Доработать однопоточную версию сервера, доступную по адре-
су: http://rosettacode.org/wiki/Hello_world/Web_server#C. Обработка каждого запроса выполняется в отдельном потоке: при получении запроса создается новый поток для его обработки, после отправки результата клиенту поток завершает свою работу. Соединение с клиентом закрывается сразу после обработки запроса. Подробную информацию о работе с сокетами можно найти в книге [2].
2.Оценить производительность сервера с помощью утилиты ab4, входящей в комплект поставки веб-сервера Apache. Утилита создана для оценки производительности веб-сервера Apache, однако может быть использована и для оценки любого другого веб-сервера. Список оцениваемых параметров согласовать с преподавателем.
3.Оценить максимальное количество потоков, с которым может
работать сервер, для различных размеров стека по умолчанию (2 Мбайт, 1 Мбайт, 512 Кбайт).
4. Добавить в обработчик запроса от клиента запуск простейшего
PHP-скрипта, возвращающего версию PHP (<?php echo phpversion(); ?>). Вернуть номер версии клиенту. Оценить изменение производительности сервера с помощью утилиты ab.
Контрольные вопросы
1.Что такое POSIX Threads? Для чего он используется в параллельном программировании?
2.Как можно создать новый поток? Могут ли вновь созданные потоки создавать другие потоки?
3.Какие способы завершения потока существуют? В чем их разли-
чие?
4.Как задаются атрибуты потока? Можно ли изменить атрибуты созданного потока?
5.Каким образом поток, завершивший свою работу, может вернуть
некоторое значение? Каким образом можно вернуть группу значений?
6.Чем отличается присоединяемый поток от отсоединенного?
7.Какой функцией (набором функций) можно отсоединить текущий поток?
8.Как выполнить некоторую функцию однократно любым потоком процесса?
4 ab – Apache HTTP server benchmarking tool [Electronic resource] // The Apache Software Foundation. – URL: https://httpd.apache.org/docs/2.4/programs/ ab.html (accessed: 08.08.2017).
76
ЛАБОРАТОРНАЯ РАБОТА №2
ПРОГРАММИРОВАНИЕ ВЗАИМОДЕЙСТВУЮЩИХ ПОТОКОВ
Цель работы
Познакомиться со средствами планирования и синхронизации потоков; научиться работать с потоками, которые обмениваются информацией между собой.
Порядок выполнения работы
1.Изучить теоретическую часть из раздела 2 и 3 настоящего посо-
бия.
2.Записать программу из примера 4. Скомпилировать ее и проверить корректность работы.
3.Добавить в пример 4 вывод информации о том, какой поток какую задачу взял на исполнение, а также некоторое достаточно продолжительное вычисление в функцию do_task(). Проверить, что все за-
дачи выполняются, причем каждая – не более одного раза. Отключить вызовы функций pthread_mutex_lock() и pthread_mutex_ unlock() и убедиться, что при отсутствии мьютекса некоторые задачи будут выполняться дважды, тогда как другие не выполнятся ни разу.
4.Сравнить скорости работы примитивов синхронизации – мьютекса и спинлока. Выяснить, как количество потоков, одновременно обращающихся к ресурсу, защищенному примитивом синхронизации, влияет на скорость исполнения программы.
5.Реализовать условную переменную с помощью мьютекса и цикла ожидания.
6.Реализовать функцию для выполнения вычислений по модели
MapReduce. Подробную информацию о модели MapReduce можно найти в электронном документе: Калита Р. MapReduce5. В качестве параметров функция должна принимать массив данных для обработки,
имена функций map и reduce, количество разрешенных потоков. В качестве реализации параллельного применения функции map к каж-
5 Калита Р. MapReduce [Электронный ресурс] // Блог о разработке, про-
граммировании на С#/.NET, и не только. – URL: http://regfordev.blogspot.ru/ 2015/09/mapreduce.html (дата обращения: 10.08.2017).
77
дому элементу массива использовать результаты пункта 8 порядка выполнения лабораторной работы № 1. Реализовать параллельное применение функции reduce к списку, полученному в результате работы функции map.
7. Выполнить задание для самостоятельной работы (вариант согласовывается с преподавателем), по результатам подготовить отчет.
Варианты заданий для самостоятельной работы
Пул потоков – это набор потоков, которые могут использоваться для решения различных задач. Задачи помещаются в общую очередь. Свободный поток (поток, который не решает в настоящий момент никакую задачу) обращается к очереди для получения очередной задачи, выполняет ее, после чего запрашивает в очереди следующую задачу. В результате исполнения некоторой задачи могут появляться новые задачи. Они также добавляются в очередь. Программа завершается, когда в очереди не остается задач и все потоки оказываются свободными.
Необходимо реализовать пул потоков и на его основе решить одну из следующих задач (по согласованию с преподавателем).
1.Упрощенный веб-сервер (см. описание в разделе «Варианты заданий для самостоятельной работы» к лабораторной работе № 1). Отличие от лабораторной работы № 1 состоит в том, что на каждый запрос клиента отдельный поток не создается – вместо этого он ставится
вочередь, откуда его забирает один из потоков пула. Сравнить максимальное количество поддерживаемых запросов для каждой из реализаций.
2.Загрузчик интернет-страниц. Доработать однопоточную версию загрузчика интернет-страницы, доступную по адресу: http://rosettacode.org/wiki/Web_scraping#C. Загрузка каждой страницы выполняется потоком из пула потоков. Содержимое загруженной страницы сохраняется в файл, из которого извлекаются все ссылки на другие страницы и ставятся в очередь на загрузку.
3.Производитель-потребитель с несколькими потоками-потреби- телями, одним потоком-производителем и несколькими местами на складе. За основу взять программу из примера 7.
4.Многопоточный поиск подстроки в файлах. Необходимо просмотреть все имена файлов в заданной директории (путь к директории
78
передается в качестве параметра). Если найдена директория – все файлы внутри ее также просматриваются. Если найден текстовый файл (определяется по расширению *.txt), то осуществляется поиск подстроки в его содержимом.
5. Генерации простых чисел с помощью алгоритма «Решето Эратосфена»6.
Контрольные вопросы
1.Для чего нужны примитивы синхронизации?
2.Каков процесс работы с мьютексом? Какие функции для этого предоставляет Pthreads?
3.Перечислите основные атрибуты мьютексов и способы работы с
ними.
4.Каковы ограничения на использование спинлоков?
5.Приведет ли использование спинлока к выигрышу производительности на одноядерном процессоре? Почему?
6.В каких целях используется примитив синхронизации «барьер»?
7.Объясните механизм работы условных переменных.
8.Сравните мьютексы, спинлоки, барьеры и условные переменные
сточки зрения области применения.
ЛАБОРАТОРНАЯ РАБОТА №3 ОТЛАДКА МНОГОПОТОЧНЫХ ПРОГРАММ
Цель работы
Ознакомиться со средствами отладки многопоточных программ; изучить наиболее часто встречающиеся виды ошибок в многопоточных программах и средства их обнаружения и исправления.
Порядок выполнения работы
1.Изучить теоретическую часть из раздела 4 настоящего пособия.
2.Выполнить поиск ошибки из примера 8 первым и вторым способами (см. раздел «Примеры сеансов работы с GDB»).
6 Решето Эратосфена [Электронный ресурс] // Википедия. – URL: https://ru.wikipedia.org/ wiki/Решето_Эратосфена (дата обращения: 10.11.2017).
79
3.Выполнить задание для самостоятельной работы (поиск ошибок
впрограмме, предоставленной преподавателем), по результатам подготовить отчет.
Контрольные вопросы
1.Перечислите наиболее часто встречающиеся ошибки при разработке параллельных программ. Какие действия приводят к ошибке в каждом случае?
2.Какие ошибки чаще всего допускают при использовании Pthreads? Как их избежать?
3.Какие категории инструментов для отладки параллельных программ вы знаете? На какие классы ошибок ориентирован каждый из них?
4.Расскажите о методах отладки программ в GDB.
5.Какие команды отладчика GDB предназначены для отладки параллельных программ?
6.Какие режимы отладчика GDB используются для отладки параллельных программ?
7.Приведите пример возможного сеанса работы в GDB.
ПОДГОТОВКА ОТЧЕТА ПО ЛАБОРАТОРНОЙ РАБОТЕ
Отчет оформляется по результатам выполнения каждой лабораторной работы и предоставляется на проверку в печатной форме. Каждый студент готовит отчет самостоятельно, независимо от того, выполнялась ли лабораторная работа индивидуально или в составе группы студентов. Вместе с отчетом предоставляется разработанная программа, которая может быть оформлена в печатной (в виде приложения к отчету) либо в электронной форме.
При сдаче отчета преподаватель может сделать устные или письменные замечания, попросить уточнить расчеты или выполнить их с другими параметрами. Эти задания выполняются студентом на отдельных листах и оформляются приложением к отчету.
Требования к тексту отчета
Отчет по лабораторной работе должен содержать следующие разделы:
а) постановка задачи – включает в себя цель выполнения работы и теоретическую часть;
80
