Паттерны параллельного программирования Евгений Козинов Цели 2 Рассмотреть последовательность создания параллельного решения на основе паттернов Рассмотреть паттерны, представленные на каждой из стадии создания решения Схема создания решения Поиск параллельности Выбор структуры алгоритма Поддерживающие структуры Механизмы реализации 3 Замечания к изложению Каждая из выше изложенных стадий содержит ряд паттернов – Все паттерны в терминах технологий – – – 4 Сначала будут перечислены все паттерны стадии, а затем каждый рассмотрен в отдельности MPI OpenMP Java Поиск параллельности Анализ зависимостей Декомпозиция Группировка задач Декомпозиция задач Управление задачами Декомпозиция данных Распределение данных 5 Анализ развития Декомпозиция задач: Решаемая задача 6 Как разделить проблему на ряд задач, исполняемых параллельно? Декомпозиция задач: Основные усилия #1 Ключом к хорошей декомпозиции является разбиение проблемы таким образом, что задача управления зависимостями была мы лишь маленьким фактором при решении проблемы Следует обращать внимание на наиболее затратные по вычислениям участки кода Следует обращать внимание на – – 7 Действия, которые ведут к решению проблемы Когда действия имеют зависимости, а когда нет Декомпозиция задач: Основные усилия #2 Задачи могут быть найдены в разных частях алгоритма – – – 8 Иной раз задачи могут представляться в виде вызова функций, а иной раз в декомпозиции самих функций Задачи можно найти в итерациях циклов Задачи также могут быть найдены в декомпозиции управления данными Декомпозиция задач: Основные усилия #3 Гибкость – Эффективность – – Задачи должны быть достаточно большими, для того что бы компенсировать затраты на параллельность Задач должно быть достаточно много для эффективной балансировки загрузки Простота – 9 Необходимо параметризовать количество и размеры задач Задачи должны легко описываться, вызываться и отлаживаться Декомпозиция данных: Решаемая задача 10 Как разбить данные на блоки которые можно было бы обрабатывать независимо? Декомпозиция данных: Основные усилия #1 Центральной проблемой является распределение данных между задачами, а не предоставить все данные после декомпозиции задач – Часто паттерны декомпозиции на подзадачи и декомпозиции данных противоречивы Выделяют два основных класса вычислений – – Вычисления основанные на массивах Вычисления с использованием структур, требующих рекурсивную обработку 11 Списки Деревья Декомпозиция данных: Основные усилия #2 Гибкость – Желательно, что бы количество частей данных было параметризованно – – Части данных должны быть достаточно большими Важно хорошее распределение данных между частями Простота – – 12 При хорошем разделении данных время, затраченное на поддержание разделения, должно быть “разумно” пропорционально Эффективность – В разных системах лучше разное соотношение количества и размера данных Сложные данные должны отображаться на простые структуры Простота отладки Группировка задач: Решаемая задача 13 Как задачи решающие проблему, распределить по группам, для упрощения управления зависимостями? Группировка задач: Категории зависимостей задач Простые временные зависимости – – Зависимость, когда в одно и тоже время должно произойти выполнение ряда задач – 14 Ситуация когда у нас есть задачи A и B, и B не может быть выполнена до завершения задачи A В этом случаи мы получаем поток вычислений Часто бывают ситуации когда нужно в одно и тоже время обновить данные определенной структуры данных Независимые задачи Группировка задач: Основные усилия #1 Цель, разбить задачи на группы основанные на вышеупомянутых зависимостях – – 15 Группировка задач в основном нужна для управления зависимостями Группировка это просто выделение задач, которые могут быть выполнены параллельно Группировка задач: Основные усилия #2 Первое, надо посмотреть на оригинальную декомпозицию задач и объединить их в группы – Операции, функции и итерации Затем, объединяются некоторые задачи с группами между которыми есть зависимости в новые группы Далее, смотрят на зависимости между группами В результате получают иерархическое представление проблемы, основанное на группах Задача Задача 16 Задача Задача Задача Задача Управление задачами: Решаемая задача 17 Пусть для решения проблемы мы разбили ее на задачи. Затем, пусть мы распределили задачи на группы. Как в этом случае лучше управлять выполнением решения задачи групп? Управление задачами: Основные усилия Получить граф зависимости решения Первое, надо посмотреть на зависимости по данным Пусть есть две группы задач A и B. Если В использует значенияГруппы полученные задачв А, тогда в полученном сетевом графике необходимо поставить зависимость Следующая стадия – Далее необходимо учесть ограничения налагаемые внешними сервисами Задача Например при записи в файл, нельзя с файлом ничего делать Задача В финале на сетевом графике необходимо выделить – задачи которые могут выполнятся параллельно Группы задач 18 Распределение данных: Решаемая задача 19 Пусть у нас есть данные и задачи, необходимые для решения поставленной проблемы. Как в этом случае наилучшим образом распределить данные между задачами? Распределение данных: Основные усилия Необходимо классифицировать данные по следующим категориям: – – – – – Локальные Только для “внешнего” чтения Задача Для “внешнего” чтения и записи Аккумулирующие (для сбора результатов) Задача Задача Много раз чтение / однажды запись Затем рекомендуется добавить эту информацию к сетевому графику Только чтение данные Соединение результатов Данный анализ в последствии даст возможность построить Чтение и запись более эффективный алгоритм решения проблемы След. стад. 20 данные Аккумуляция Анализ развития: Решаемая задача 21 Пусть мы произвели анализ зависимостей и декомпозицию задач. Можем ли мы перейти к следующей стадии? Этот паттерн практически является вопросником готовности концепции решения Анализ развития: Основные усилия #1 Ответить на следующие вопросы – – – 22 Какое максимальное число процессоров, в данном решении, может быть использовано? Каким образом “внешние” структуры данных будут распределены между блоками исполнения? Какое количество исполняемых блоков присутствует в решении и по какому правилу они распределяются между блоками исполнения? Анализ развития: Основные усилия #2 Ответить на следующие вопросы – Подходит ли выработанное решение и путь решения проблемы аппаратуре на которой будет решаться задача? – 23 К примеру если коммуникации обходятся дорого, то лучше идти по пути декомпозиции данных Как выделенные задачи и данные зависят в предлагаемом решении? Анализ развития: Основные усилия #3 Ответить на следующие вопросы – Какие виды взаимодействия возможно использовать? – 24 Синхронные или асинхронные Достаточно ли хорошо ли выполнена группировка задач? Выбор структуры алгоритма Организация через задачи Организация через потоки данных Параллелизм задач Геометрическая декомпозиция Разделяй и властвуй Рекурсивные данные Организация через декомпозицию данных Канал Параллельность основанная на событиях 25 Дерево решений для выбора структуры алгоритма начало Организация через задачи Линейный Параллелизм Задач 26 Рекурсивный Разделяй и Властвуй Организация через Декомпозицию данных Организация через Потоки данных Линейный Линейный Геометрическая Декомпозиция Рекурсивный Рекурсивные Вычисления Каналы Рекурсивный Параллельность Основанная на событиях Дерево решений для выбора структуры алгоритма начало Организация через задачи Линейный Параллелизм Задач 27 Рекурсивный Разделяй и Властвуй Организация через Декомпозицию данных Организация через Потоки данных Линейный Линейный Геометрическая Декомпозиция Рекурсивный Рекурсивные Вычисления Каналы Рекурсивный Параллельность Основанная на событиях Параллелизм задач: Решаемая задача Паттерн решает две основные задачи – – 28 Как лучше разбить проблему на задачи? Пусть проблему удалось разбить на ряд задач. Как задачи, для поиска решения, могут быть запущены параллельно? Параллелизм задач: Основные усилия #1 Разбить проблему на задачи – – 29 Задач должно быть достаточно много, чтобы обеспечить загрузку процессоров в любой момент времени Задачи должны быть достаточно большими, чтобы дополнительные затраты на параллельность были компенсированы Параллелизм задач: Основные усилия #2 Выявить и классифицировать все зависимости Несколько видов зависимостей Устраняемые int– ii = 0, jj = 0; зависимости “Отделяемые” – Другие виды for(int i = 0; i < зависимостей N; i++){ – ii = = d[i] iibig_time_consuming_work(i); +1; for(int i = 0; i <= N; i++){ d[ii] =+big_time_consuming_work(ii); a[(i*i i)/2] other_big_calc(jj); sum+ +i;f(i); } sum jj == jj } a[jj] = other_big_calc(jj); 30 } Параллелизм задач: Основные усилия #3 Создание хорошего расписания задач Виды расписаний – Статическое – Динамическое A E 31 E C D Применяется A в случае B предсказуемого Fразмера задачи Легко реализовать Плохая адаптация к новым условиям B B Применяется сведений о размере задач или D C C в отсутствии A приFчастом его изменении E D Реализация часто много сложнее и основана наF аппроксимациях Хорошо показываете себя на неоднородных кластерах Параллелизм задач: Структура программы При наличии циклов OpenMP автоматически выделяет задачи и производит балансировку нагрузки – Возможна организация с использованием – – 32 Есть возможность создания как динамического так и статического расписания Master/Worker SPMD Дерево решений для выбора структуры алгоритма начало Организация через задачи Линейный Параллелизм Задач 33 Рекурсивный Разделяй и Властвуй Организация через Декомпозицию данных Организация через Потоки данных Линейный Линейный Геометрическая Декомпозиция Рекурсивный Рекурсивные Вычисления Каналы Рекурсивный Параллельность Основанная на событиях Разделяй и властвуй: Решаемая задача 34 Пусть существует алгоритм, который позволяет разделить проблему на задачи, и этот путь объединяет задачи в коллекции логически связанных групп и подгрупп. Как в этом случае организовать параллельный запуск задач? Разделяй и властвуй: Основные усилия Сформулировать задачу в терминах “разделяй и властвуй” проблема Разделение проблемы подпроблема подпроблема подпроблема подпроблема подпроблема подпроблема решение решение решение решение решение 35 решение Слияние результатов решение Разделяй и властвуй: Рекомендуемая структура решения Func Func Func Func Func solve returns Solution; //хранение результатов split returns Problem[]; //разделение задачи на подзадачи baseCase returns Boolean; //уровень решения baseSolve returns Solution; //Решение подзадачи merge returns Solution; //слияние результатов Solution solve(Problem P){ if(baseCase(P)) return baseSolve(P) else{ Problem subProblem[N]; Solution subSolution[N]; subProblem = split(P); for(int i = 0; i < N; i++) subSolution[i] = solve(subProblem[i]); return merge(subProblem); } } 36 Разделяй и властвуй: Тактики разбиений Разбить на большие задачи – – Мало затрат на коммуникации Плохая балансировка Разбить на маленькие задачи – – Хорошая балансировка Большие затраты на коммуникации 37 Возможна ситуация, когда плохое расписание вызовет простой процессоров Можно получить не ускорение а замедление вычислений Разделяй и властвуй: Структура программы OpenMP использует модель разделяй и властвуй Этот паттерн может быть реализован с использованием паттернов – – 38 Fork/join Master/Worker Дерево решений для выбора структуры алгоритма начало Организация через задачи Линейный Параллелизм Задач 39 Рекурсивный Разделяй и Властвуй Организация через Декомпозицию данных Организация через Потоки данных Линейный Линейный Геометрическая Декомпозиция Рекурсивный Рекурсивные Вычисления Каналы Рекурсивный Параллельность Основанная на событиях Геометрическая декомпозиция: Решаемая задача 40 Как организовать алгоритм над структурой данных, которая разделена на независимо обновляемые данные? Паттерн очень часто используется вместе с другими структурами алгоритмов Геометрическая декомпозиция: Пример использования Физические задачи Операции ukp[i] = uk[i] + (dt/(dxнад * dx))матрицами * (uk[i + 1] – 2 * uk[i] + uk[i - 1]); При работе с паттерном выделяют данные которые – Обновляются Пример разных видов вычислений в данной декомпозиции – Читаются – – 41 Локальные Обновление не требует внешних данных Внешние Обновление требует внешних данных Геометрическая декомпозиция: Основные усилия Разбить данные на локальные внешние Отдельно выделить оператор обновления Выделить оператор вычисления Построить корректное расписание – 42 Вычисления должны выполняться параллельно, но при этом вычисления не должны предшествовать оператору обновления Геометрическая декомпозиция: Разделение данных Внешние данные иногда рекомендуется выделить в отдельные структуры данных В некоторых случаях рекомендуется в структурах данны выделить дополнительные поля для внешних данных которые становятся локальными в вычислениях Возможны две стратегии – Малое число больших кусков данных – Большое число маленьких кусков данных 43 В данном случае расходов на поддержание вычислений маленькие, но балансировка загрузки плохая Хорошая балансировка нагрузки, но большие затраты на поддержание вычислений Количество частей на которые разбиваются данные рекомендуется параметризировать, для запуска на разных кластерах Геометрическая декомпозиция: Структура программы Этот паттерн применяется и используется – – Родственные и связанные с этим паттерном – – Параллелизм задач Разделяй и влавствуй Геометрическая декомпозиция является основной структурой программы во многих параллельных библиотеках линейной алгебры – 44 OpenMP SPMD ScaLAPACK Дерево решений для выбора структуры алгоритма начало Организация через задачи Линейный Параллелизм Задач 45 Рекурсивный Разделяй и Властвуй Организация через Декомпозицию данных Организация через Потоки данных Линейный Линейный Геометрическая Декомпозиция Рекурсивный Рекурсивные Вычисления Каналы Рекурсивный Параллельность Основанная на событиях Рекурсивные вычисления: Решаемая задача Как рекурсивные вычисления выполнить параллельно? Как частный случай: как обеспечить параллельную обработку распространенных структур данных, таких как: – – – 46 Списки Деревья Графы Рекурсивные вычисления: Основные усилия Необходимо преобразовать алгоритм, который обходит структуру данных последовательно преобразовать в параллельный – 47 При этом результат алгоритма не должен быть изменен Преобразованный алгоритм должен обеспечивать балансировку нагрузки Алгоритм должен быть легкий для понимания и поддержки Рекурсивные вычисления: Основной метод устранения рекурсии Последовательная обработка Параллельная обработка Пример суммирования For all k in parallel{ temp[k] = next[k]; while temp[k] != null { x[temp[x]] = x[k] + x[temp[k]] temp[k] = temp[temp[k]]; } } 48 Дерево решений для выбора структуры алгоритма начало Организация через задачи Линейный Параллелизм Задач 49 Рекурсивный Разделяй и Властвуй Организация через Декомпозицию данных Организация через Потоки данных Линейный Линейный Геометрическая Декомпозиция Рекурсивный Рекурсивные Данные Каналы Рекурсивный Параллельность Основанная на событиях Каналы: Решаемая задача 50 Пусть в нашем алгоритме есть много однотипных вычислений, и пусть эти вычисления могут выть разбиты на ряд стадий. Как в этом случае организовать параллельные вычисления? Каналы: Примеры использования Каналы инструкций в современных процессорах Векторные вычисления Каналы на алгоритмическом уровне For(i =0; i < N; i++){a[i] = b[i] + c[i];} Обработка сигналов Обработка графики Командная строка 51 Каналы: Основные усилия Разбить задачи на стадии Организовать параллельную работу стадий время Стадия канала 1 С1 С2 С3 С4 С5 Стадия канала 2 С1 С2 С3 С4 С5 С1 С2 С3 С4 С5 С1 С2 С3 С4 Стадия канала 3 Стадия канала 4 52 С5 Каналы: Виды каналов Стадия 1 Стадия 2 Стадия 3 Стадия 3 Линейный канал Стадия 3 Стадия 1 Стадия 2 Стадия 3 Стадия 3 Не линейный канал 53 Каналы: Рекомендуемая структура стадии Initialize While (more data){ receive data element from previous stage perform operation on data element send data element to next stage } 54 Каналы: Рекомендуется применить Паттерны – – Возможна реализация с использованием – – 55 Общая очередь Параллелизм задач MPI Java Ввести специальные виды задач(пакетов), которые бы пересылали отладочную информацию к отладчику Дерево решений для выбора структуры алгоритма начало Организация через задачи Линейный Параллелизм Задач 56 Рекурсивный Разделяй и Властвуй Организация через Декомпозицию данных Организация через Потоки данных Линейный Линейный Геометрическая Декомпозиция Рекурсивный Рекурсивные Данные Каналы Рекурсивный Параллельность Основанная на событиях Параллельность основанная на событиях: Решаемая задача 57 Пусть, как и в каналах, в нашем алгоритме есть много однотипных вычислений, и пусть эти вычисления могут выть разбиты на ряд стадий. Пусть также в отличии от каналов, наступление и продолжительность стадий не предсказуемо, а зависит от внешних событий. Как в этом случае организовать параллельные вычисления? Параллельность основанная на событиях: Основные усилия Организовать1 работу с событиями – Отслеживание Обработку 3 Создание новых Обход в ширь: – – 58 2 1 2 Обход в глубину: 3 Организовать эффективное управление Предлагаемый каркас обработчиков событий событиями Initialize – Есть done){ две стандартные мемодики(в ширь и в глубину) While(not event receive Отслеживание и устранение deadlock-ов process event send events } finalize Параллельность основанная на событиях: Рекомендуется применить Паттерны – – Возможна реализация с использованием – – MPI Java Ввести специальные виды задач(пакетов), которые бы пересылали отладочную информацию к отладчику – 59 Общая очередь Параллелизм задач Необходимо прежде всего для отладки, так как в этом паттерне поведение очень сложное и не прогнозируемое Поддерживающие структуры Структура программы SPMD Общие данные Master/Woker Общая очередь Параллелизм циклов Распределенный массив Fork/Join 60 Структура данных Выбор паттерна #1 61 Параллелиз м задач Разделяй и властвуй Геометрическа я декомпозиция Рекурсивны е данные Каналы Параллельнос ть основанная на событиях SPMD 4 3 4 2 3 2 Параллелизм циклов 4 2 3 Мастер/Рабочи й 4 2 1 1 1 1 Fork/Join 2 4 2 4 4 Выбор паттерна #2 62 OpenMP MPI Java SPMD 3 4 2 Параллелизм циклов 4 1 3 Мастер/Рабочий 2 3 3 Fork/Join 3 4 SPMD: Решаемая задача 63 Взаимодействие исполняемы блоков может стать достаточно сложной задачей, когда необходимо организовать работу корректной и эффективной параллельной программы. Как обеспечить простоту реализации такой программы? SPMD: О паттерне 64 Этот паттерн является наиболее общей структурой параллельных программ. В частности он хорошо сочетается с MPI программами, а также с программами использующими Параллелизм задач и Геометрической декомпозицией. Он также обеспечивает эффективную реализацию паттерна “разделяй и властвую” и паттерном рекурсивные данные. SPMD: Основные усилия #1 Необходимо разбить программу на следующие блоки – Инициализация – Назначение уникальных идентификаторов исполняемым блокам 65 Загрузка исполняемых блоков с некоторым контекстом Обычно реализацию данной стадии выносят за приделы программы Чаще всего это присвоение глобального номера SPMD: Основные усилия #2 Необходимо разбить программу на следующие блоки – – – Запуск необходимых задач на исполняемых модулях Распределение данных Завершение работы 66 Удаление завершение исполняемых блоков Удаление идентификаторов Высвобождение памяти SPMD: Реализация паттерна 67 Паттерн непосредственно реализуется в реализациях стандартов MPI и PVM Паттерн также может использоваться с использованием библиотеки OpenMP Master/Worker: Решаемая задача 68 Пусть организация программы такова, что доминирует необходимость динамического баланса исполняемых задач. Как в этом случае организовать работу? Мастер/Рабочий: О паттерне 69 Этот паттерн предназначен для параллельных программ использующих параллелизм задач. Этот паттерн также часто употребляется в связке с паттерном Fork/Join Master/Worker: Основные усилия Представить проблему в следующем виде Инициализация вычислений Установка проблемы Рабочие (от 1 до N) Инициализация Создание пакета задач Запуск рабочих Спит пока рабочие работают Сбор результатов 70 Ожидание вычислений Получение результатов нет Конец? да Выход Master/Worker: Варианты реализации 71 В некоторых реализациях рабочие сам становится мастерами Когда задачи могут быть отображены на простой цикл, то иной раз реализовать мастер на основе паттерна Параллелизм циклов В качестве вспомогательной структуры для мастера рекомендуется реализовать общую очередь Параллелизм циклов: Решаемая задача 72 Пусть в программе основное время тратится на расчеты в циклах. Как в этом случае программа может быть трансформирована для параллельного исполнения? Параллелизм циклов: Основные усилия Попытаться выявить наиболее узкие места в программе(упор на циклы) и попытаться их устранить Попытаться устранить устранимые зависимости в циклах Распараллелить циклы – – Оптимизировать расписание циклов – 73 OpenMP SPMD Оптимизация с точки зрения загрузки процессоров Параллелизм циклов: Общие полезные преобразования Слияние циклов Объединение вложенных циклов До преобразования: For(i До После преобразования: = 0; i < N; i++){ преобразования: For(i For(ij A[i]==0; 0; B[i] iij <+< N; C[i]; N*N; i++){ ij++){ C[i] A[i] For(j i = ij ==/ D[i] B[i] 0; N;j+<C[i]; F[i]; N; j++){ } j C[i] = A[i][j] ij = % D[i] N; = + work(i, F[i]; j); For(i E[i]==0; } A[i][j] A[i] =iwork(i, <+N; C[i]; i++){ j); } E[i] = A[i] + C[i]; } 74 Параллелизм циклов: Реализация паттерна 75 Основная технология которая непосредственно поддерживает этот паттерн OpenMP Возможна реализация на SPMD и Master/Worker Fork/Join: Решаемая задача 76 Пусть в программе некоторое число параллельных задач, которые представляются в виде исполняемых программ. Как в этом случае проще управлять этими программами? Fork/Join: О паттерне 77 Этот паттерн часто используется в Java программа на общей памяти для проблем использующих паттерны “разделяй и властвуй” и Рекурсивные данные OpenMP внутри реализации непосредственно использует этот паттерн Fork/Join: Способы реализации Непосредственное назначение задачи исполняемому модулю – Не прямое назначение задач исполняемым модулям – – – – 78 Для каждой задачи вызывается fork и join Сначала порождаются несколько исполняемых модулей Затем задачи выстраивают в общую очередь В последствии исполняемые модули берут и исполняют задачи из очереди При опустошении очереди программа завершает работу Общие данные: Решаемая задача 79 Пусть для решения задачи существуют общие данные. Как этими данными управлять? Общие данные: Основные усилия #1 Убедиться, что общие данные действительно нужны Определить Абстрактный Тип Данных (АТД) – – – Данные Высоко-уровневые метода Например в очереди 80 Данные: звенья Методы: поставить элемент в очередь, получить элмент Общие данные: Основные усилия #2 Написать параллельную реализацию АТД, при этом есть следующие стратегии реализации – Одно исполнение во времени – – 81 Наиболее простой способ реализации но не эффективный Выделение множества оператором с запретом на вмешательство Разделение операторов на “читателей” и “писателей”, и определение для них правил блокировки Общие данные: Основные усилия #3 Написать параллельную реализацию АТД, при этом есть следующие стратегии реализации – Редуцирование критических секций – – Непосредственные блокировки Использование других видов синхронизации 82 Постепенный все более строгий запрет на вмешательство Синхронизация доступа к памяти Использование расписания доступа Общая очередь: Решаемая задача Как создать общую очередь для поддержания структуры алгоритма Это частный случай Общих данных, в котором АТД содержит следующие методы – – 83 Добавить в очередь Получить элемент Реализация возможна со всеми техниками синхронизации Распределенный массив: Решает проблему 84 Как отобразить массив на исполняемые модули и локальную нумерацию? Распределенный массив: Основные усилия Написать отдельные операторы – Пересчет индексов – Получение размета локальных данных В литературе часто предлагаются формулы пересчета индексов для стандартных разбиений – – – 85 Локальных Отображенных на исполняемые модули Одномерное блочное разбиение Разбиение на двумерные блоки (полосы) Разбиение на двумерные блоки Механизмы реализации Управление ИМ Синхронизация Коммуникация 86 Управление исполняемыми модулями Основные задачи, которые решает паттерн это: – – 87 Создание и удаление потоков Создание и удаление процессов Синхронизация Основная задача паттерна решить проблему некорректного доступа к данным В openMP, MPI и java есть встроенные средства синхронизации, такие как: – – 88 Барьеры И блокировка секций кода и данных Коммуникация 89 Основная задача этого паттерна обеспечение распределения исходных данных и сбора полученных данных В рассматриваемых технологиях есть встроенные средства коммуникаций В MPI программах особое место занимают коллективные операции Вопросы?