This commit is contained in:
2024-05-09 16:15:46 +03:00
parent ec20fbd897
commit b918cad647
25 changed files with 228 additions and 179 deletions

3
.gitignore vendored
View File

@@ -5,4 +5,5 @@
*.bbl
*.blg
main.synctex.gz
*.toc
*.toc
.vscode

BIN
main.pdf

Binary file not shown.

View File

@@ -1,3 +1,4 @@
В данной работе рассматривается решение задачи автоматического распараллеливания фортран-программ для случая целевой системы с общей оперативной памятью. Задача решается в рамках доработки системы SAPFOR с использьзованием модели DVMH в качестве технологии распараллеливания.
Во введении приводятся некоторые сведения о распараллеливании, как общепринятые, так и те, что относятся только к системам SAPFOR и DVM, приводится описание этих систем. Далее, во второй главе описывается проблема распараллеливания на общую память с точки зрения DVM и с точки зрения автоматизации, рассматриваюся подходы к её решению. В этой главе так же определяются основные цели работы, описываются основные сценарии использования разрабатываемого фунционала. В третьей главе подробно описывается ход решения поставленной задачи, который был разбит на три этапа -- теоретическую подготовку, реализацию и тестирование. В четвёртой главе приведено описание существовавших и добавленных алгоритмов, о которых шла речь в главе 3. В пятой главе приводятся результаты исследования эффективности получаемого распараллеливания на примере программ из пакета NAS Parallel Benchmarks.
В данной работе рассматривается решение задачи распараллеливания Фортран-программ для случая целевой системы с общей оперативной памятью. Задача решается в рамках доработки системы SAPFOR с использованием модели DVMH в качестве технологии распараллеливания.
Во введении приводятся некоторые сведения о распараллеливании, как общепринятые, так и те, что относятся только к системам SAPFOR и DVM, приводится описание этих систем. Далее, во второй главе описывается проблема распараллеливания на общую память с точки зрения DVM-системы и с точки зрения системы SAPFOR, рассматриваются подходы к её решению. В этой главе также определяются основные цели работы, описываются основные сценарии использования разрабатываемого функционала. В третьей главе подробно описывается ход решения поставленной задачи, который был разбит на три этапа -- теоретическую подготовку, реализацию и тестирование. В четвёртой главе приведено описание существовавших и добавленных алгоритмов, о которых шла речь в предыдущей главе. В пятой главе приводятся результаты исследования эффективности получаемого распараллеливания на примере программ из пакета NAS Parallel Benchmarks.

View File

@@ -1,15 +1,60 @@
@online{pthreads,
title = "Стандарт POSIX.1-2017, библиотека Pthreads",
url = "https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/nframe.html"
}
@online{cuda,
title = "Официальный сайт библиотеки CUDA",
url = "https://developer.nvidia.com/cuda-toolkit"
}
@online{hip,
title = "Официальный сайт библиотеки HIP",
url = "https://rocm.docs.amd.com/projects/HIP/en/latest"
}
@online{opencl,
title = "Официальный сайт библиотеки OpenCL",
url = "http://opencl.ru"
}
@online{openmp,
title = "Официальный сайт библиотеки OpenMP",
url = "https://www.openmp.org"
}
@online{openacc,
title = "Официальный сайт библиотеки OpenACC",
url = "https://www.openacc.org"
}
@online{mpi,
title = "Стадарт MPI",
url = "https://www.mpi-forum.org/docs"
}
@online{oscar,
title = "Официальный сайт проекта OSCAR",
url = "https://oscar-project.org/"
}
@online{cpp,
title = "Стадарт языка C++",
url = "https://isocpp.org/std/the-standard"
}
@online{keldysh,
title = "сайт Института прикладной математики им. М.В. Келдыша Российской академии наук",
url = "https://www.keldysh.ru/"
title = "Сайт Института прикладной математики им. М.В. Келдыша Российской академии наук",
url = "https://www.keldysh.ru"
}
@online{dvm-site,
title = "сайт DVM-системы",
url = "http://dvm-system.org/"
title = "Сайт DVM-системы",
url = "http://dvm-system.org"
}
@inproceedings{sapfor-1,
author = "Н.А. Катаев, С.А. Черных",
author = "Катаев Н.А., Черных С.А.",
title = "Автоматизация распараллеливания программ в системе SAPFOR",
booktitle = "Научный сервис в сети Интернет: труды XXII Всероссийской научной конференции",
year = "2020",
@@ -25,6 +70,16 @@
url = "https://num-meth.ru/index.php/journal/article/view/1246/1214"
}
@online{C99,
title = "Стандарт языка Си 99",
url = "https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf"
}
@online{F95,
title = "Стандарт языка Фортран 95",
url = "https://wg5-fortran.org/N1151-N1200/N1191.pdf"
}
@inproceedings{par-reg,
author = "Колганов А.С.",
title = "Опыт применения механизма областей для поэтапного распараллеливания программных комплексов с помощью системы SAPFOR",
@@ -35,29 +90,32 @@
}
@inproceedings{lom_readings,
author = "Крюков В. А., Колганов А. С., Кочармин М. Д.",
author = "Крюков В.А., Колганов А.С., Кочармин М.Д.",
title = "Автоматизированное распараллеливание Фортран-программ на общую память",
booktitle = "Ломоносовские чтения",
year = "2024",
url = "https://conf.msu.ru/file/event/8752/eid8752_attach_a7f03100cf01a40d0a1bc490c7691661e89e5edc.pdf"
}
@inproceedings{pri-var,
author = "А.C. Колганов and Н.Н. Королев",
title = "Статический анализ приватных переменных в системе автоматизированного распараллеливания Фортран-программ",
url = "http://omega.sp.susu.ru/pavt2018/short/018.pdf",
booktitle = {Параллельные вычислительные технологии (ПаВТ{}2018)},
}
@book{dragonbook,
title = {Компиляторы: принципы, технологии и инструментарий, 2-е изд.},
author = {Ахо, Альфред В. and Лам, Моника С. and Рави Сети and Джеффри Д. Ульман},
year = {2006}
}
@inproceedings{polaris,
author = "Blume W. and Doallo R. and Eigenmann R. and Grout J. and Hoeflinger J. and Lawrence T.",
title = "Parallel programming with Polaris",
booktitle = "Computer",
year = "December 1996",
number = "12",
volume = "29",
pages = {78-82}
}
@online{sage,
title = "Библиотека Sage++",
url = "http://www.extreme.indiana.edu/sage/"
url = "http://www.extreme.indiana.edu/sage"
}
@online{npb,
@@ -66,7 +124,17 @@
}
@inproceedings{disser,
author = "А.C. Колганов",
title = "Автоматизация распараллеливания Фортран-программ для гетерогенных кластеров",
url = "http://TODO"
author = "Колганов А.С.",
title = "Автоматизация распараллеливания Фортран-программ для гетерогенных кластеров: автореф. дисс. канд. физ.-мат. наук",
year = {2020}
}
@online{nvidia,
title = "Официальный сайт производителя графических ускорителей Nvidia",
url = "https://www.nvidia.com/ru-ru/geforce/graphics-cards"
}
@online{intel,
title = "Официальный сайт производителя процессоров Intel",
url = "https://www.intel.com"
}

View File

@@ -1,13 +1,11 @@
\section{Заключение}
Итак, была проведена работа по исследованию и улучшению системы автоматизированного распараллеливания SAPFOR. В качестве разультата в систему SAPFOR был добавлен новый режим работы распараллеливания на общую память, что позволило расширить класс распараллеливаемых программ.
Итак, была проведена работа по исследованию и улучшению системы автоматизированного распараллеливания SAPFOR. В качестве результата в систему SAPFOR был добавлен новый режим работы распараллеливания на общую память, что позволило расширить класс распараллеливаемых программ.
Разработанный проход был должным образом интегрирован в систему SAPFOR. Были поддержаны как директивы системе SAPFOR, так и взаимодействие с диалоговой оболочкой, в частности функция запуска прохода анализа кода. Добавленный проход использует как преобразованные версии уже существоваших алгоритмов, так и новые решения.
Разработанный проход был должным образом интегрирован в систему SAPFOR. Были поддержаны как директивы системе SAPFOR, так и взаимодействие с диалоговой оболочкой, в частности функция запуска прохода анализа кода. Добавленный проход использует как преобразованные версии уже существовавших алгоритмов, так и новые решения.
Добавленный код был тщательно протестирован. Было выполнено тестирование на большом множестве различных программ на предмет корректности получаемого параллельного DVMH-кода. Также с помощью нового прохода были распараллены тесты из пакета NAS Parallel Benchmarks.
Добавленный код был тщательно протестирован. Было выполнено тестирование на большом множестве различных программ на предмет корректности получаемого параллельного DVMH-кода. Также с помощью нового прохода были распараллелены тесты из пакета NAS Parallel Benchmarks.
Распараллеливание программ из пакета NAS Parallel Benchmarks вызвало некоторые трудности, большинство из которых удалось преодолеть с помощью графической оболочки системы SAPFOR. В результате для большей части тестов были получены эффективные параллельные версии на языке DVM, конкурирующие с эталонными версиями на OpenMP. В доказательство их эффективности были приведены результаты запусков на различных устройствах: на многопоточном процессоре и на графических ускорителях.
Распараллеливание программ из пакета NAS Parallel Benchmarks вызвало некоторые трудности, большинство из которых удалось преодолеть с помощью графической оболочки системы SAPFOR и с использованием других реализованных в системе проходов. В результате распараллеливания для большей части тестов были получены эффективные параллельные версии на языке DVMH, конкурирующие с эталонными версиями на OpenMP. Полученные параллельные версии могут успешно выполняться на графических ускорителях без изменений кода или набора вставленных директив.
Результаты работы были представлены на конференции \textit{<<Ломоносовские чтения 2024>>} и опубликованы в её сборнике тезисов \cite{lom_readings}.
Таким образом, все поставленные цели были выполнены, что дало решение исходной задачи автоматизации распараллеливания на общую память.
Результаты работы были представлены на конференции \textit{<<Ломоносовские чтения 2024>>} и опубликованы в её сборнике тезисов \cite{lom_readings}.

View File

@@ -1,8 +1,8 @@
\subsection{Алгоритмы распараллеливания с распределением данных}
Рассмотрим подробнее устройство проходов, отвечающих за построение схемы распределения данных и распараллеливании (см. Рис. \ref{fig:distr-alg}).
Рассмотрим подробнее устройство реализованных в системе SAPFOR проходов, отвечающих за построение схемы распределения данных и распараллеливание (см. Рис. \ref{fig:distr-alg}).
Начнём с прохода LOOP\_ANALYZER\_DATA\_DIST\_S0. На вход он получает АСД, заполненные структуры \texttt{FuncInfo} и \texttt{LoopGraph} для всей программы. Результатом данного прохода является заполненный граф измерений массивов. В проходе происходит итерация по всем структурам \texttt{FuncInfo}. Для каждой процедуры производятся следующие действия:
Начнём с прохода LOOP\_ANALYZER\_DATA\_DIST\_S0. На вход он получает АСД, множества заполненных структур \texttt{FuncInfo} и \texttt{LoopGraph} для всей программы, отражающих все её процедуры и циклы. Результатом данного прохода является заполненный граф измерений массивов. В проходе происходит итерация по всем процедурам входной программы. Для каждой процедуры производятся следующие действия:
\begin{itemize}
\item выполняется проход по всем операторам процедуры;
@@ -11,59 +11,52 @@
\item отображение заключается в сохранении записей вида \textit{<цикл, массив, тип операции, номер измерения, A, B>} во временную структуру. Такая запись создаётся для каждого измерения, обращение по которому в текущей операции имеет вид \textit{A*i+B}, где \textit{A} и \textit{B} - целые числа, \textit{i} - счётчик цикла;
\item далее происходит добавление полученных записей об обращениях к массив в специальную структура данных -- граф измерений массивов. Эта структура используется для построения схемы распределения данных и представляет собой граф, вершинами которого являются измерения массивов, в дугами -- связи между измерениями массивов согласно их использованию в циклах программы (см. пример на Рис. \ref{fig:array_graph}). Подробно построение графа массивов описано в \cite{disser};
\item далее происходит добавление полученных записей об обращениях к массивам в специальную структуру данных -- граф измерений массивов. Эта структура используется для построения схемы распределения данных и представляет собой граф, вершинами которого являются измерения массивов, в дугами -- связи между измерениями массивов согласно их использованию в циклах программы. Подробно построение графа массивов описано в \cite{disser};
\item после обработки всех функций проход завершает работу;
\item после обработки всех процедур проход завершает работу.
\end{itemize}
\begin{figure}[h]
\centering
\includegraphics[scale=0.5]{src/assets/array_graph.png}
\caption{пример графа измерений массивов.}
\label{fig:array_graph}
\end{figure}
Далее запускается проход LOOP\_ANALYZER\_DATA\_DIST\_S1. Входные данные у него такие же, как и у LOOP\_ANALYZER\_DATA\_DIST\_S0. Его цель -- собрать информацию о зависимостях по данным в циклах и записать её в поля структуры \texttt{LoopGraph}.
В этом проходе также происходит итерация по всем процедурам программы и производятся следующие действия:
\begin{itemize}
\item опять выполняется проход по всем операторам процедуры;
\item выполняется проход по всем операторам процедуры;
\item точно так же обрабатываются обращения к массивам с сохранением записей вида \textit{<цикл, массив, тип операции, номер измерения, A, B>};
\item обрабатываются обращения к массивам с сохранением записей вида \textit{<цикл, массив, тип операции, номер измерения, A, B>};
\item вместо добавления информации в граф измерений массивов, выявляются зависимости по данным внутри циклов путём построения специального графа зависимостей;
\item вместо добавления информации в граф измерений массивов выявляются зависимости по данным внутри циклов путём построения специального графа зависимостей;
\item для каждого цикла, который имеет зависимости по данным, заносится пометка в структуру \texttt{LoopGraph} о том, что цикл имеет зависимость по данным и не может быть распараллелен;
\item исключения составляют зависимости фиксированной длинны, то есть такие, что номера записывающих и читающих витков отличаются на фиксированную величину. Такие циклы могут быть распараллелены с помощью директивы ACROSS (см. пример на Рис. \ref{fig:hp} в главе \ref{sec:benchmark});
\item после обработки всех функций проход завершает работу;
\item после обработки всех процедур проход завершает работу.
\end{itemize}
Проход LOOP\_ANALYZER\_DATA\_DIST\_S2 получает на вход граф измерений массивов. Результатом прохода является усечённый граф измерений массивов (такой граф измерений массивов, который не содержит циклов, порождающих конфликтные ситуации) для последующего создания распределения данных. В основе лежат алгоритмы поиска простыв циклов в графе и построения минимального остовного дерева.
Проход LOOP\_ANALYZER\_DATA\_DIST\_S2 получает на вход граф измерений массивов. Результатом прохода является усечённый граф измерений массивов (такой граф измерений массивов, который не содержит циклов, порождающих конфликтные ситуации) для последующего создания распределения данных. В основе лежат алгоритмы поиска простых циклов в графе и построения минимального остовного дерева.
Проход CRATE\_TEMPLATE\_LINKS получает на вход оптимизированный граф измерений массивов, в котором отсутствуют циклы. Поскольку в этом графе нет циклов, все его компоненты связности представляют собой деревья. В каждом таком дереве находится массив с наибольшей размерностью и по нему создаётся служебный массив-шаблон, на который выравниваются все массивы рассматриваемого дерева. Таким образом, на вход этот проход принимает граф измерений массивов, а на выходе получаются директивы распределения и выравнивания данных, представленные структурой \texttt{DataDirective}, хранящей всю необходимую информацию.
После этого запускается проход LOOP\_ANALYZER\_COMP\_DIST распределения вычислений согласно построенному распределению данных. На вход он получает АСД программы, получает АСД, структуры \texttt{FuncInfo}, \texttt{LoopGraph}, граф измерений массивов и построенное распределение данных. Общая схема работы совпадает с LOOP\_ANALYZER\_DATA\_DIST\_S0 и LOOP\_ANALYZER\_DATA\_DIST\_S1: происходит итерация по всем функциям и заполнение кортежей \textit{<цикл, массив, тип операции, номер измерения, A, B>}. После заполнения этой информации, происходят следующие действия:
После этого запускается проход LOOP\_ANALYZER\_COMP\_DIST распределения вычислений согласно построенному распределению данных. На вход он получает АСД программы, множества структур \texttt{FuncInfo}, \texttt{LoopGraph}, граф измерений массивов и построенное распределение данных. Общая схема работы совпадает с LOOP\_ANALYZER\_DATA\_DIST\_S0 и LOOP\_ANALYZER\_DATA\_DIST\_S1: происходит итерация по всем процедурам и заполнение кортежей \textit{<цикл, массив, тип операции, номер измерения, A, B>}. После заполнения этой информации, происходят следующие действия:
\begin{itemize}
\item по отдельности рассматривается каждый цикл;
\item по группе флагов структуры \texttt{LoopNode} определяется, есть ли факторы, препятствующие распараллеливанию цикла;
\item если нет, среди всех массивов, используемых в цикле, выбирается лучший для того, чтобы относительно него распределить витки циклы. Предпочтение отдаётся массивам, в которые происходит запись и которые имеют наибольшее количество измерений. Если таких нет, выбираются массивы, из которых происходит чтение;
\item если нет, среди всех массивов, используемых в цикле, выбирается лучший для того, чтобы относительно него распределить витки цикла. Предпочтение отдаётся массивам, в которые происходит запись и которые имеют наибольшее количество измерений. Если таких нет, выбор происходит среди массивов, из которых происходит чтение;
\item для каждого цикла без ограничений на распараллеливание создаётся структура типа \texttt{ParallelDirective}, в которую записывается выбранный массив и другая информация, такая как ACROSS-зависимости и др., извлекаемая в том числе из графа измерений массивов;
\item полученные структуры \texttt{ParallelDirective} сохраняются в соответствующих структурах \texttt{LoopNode};
\item после создание всех директив, для каждого тесновложенного гнезда параллельных циклов происходит объединение \texttt{ParallelDirective} для того, чтобы распараллеливался не только самый верхний цикл, а всё гнездо;
\item после создание всех директив, для каждого тесновложенного гнезда параллельных циклов происходит объединение \texttt{ParallelDirective} для того, чтобы распараллеливался не только самый верхний цикл, а всё гнездо.
\end{itemize}
Следом вызывается проход CREATE\_PARALLEL\_DIRS. На вход он получает построенные директивы распределения данных и директивы распараллеливания циклов в виде структур \texttt{DataDirective} и \texttt{ParallelDirective}.
Затем вызывается проход CREATE\_PARALLEL\_DIRS. На вход он получает построенные директивы распределения данных и директивы распараллеливания циклов в виде структур \texttt{DataDirective} и \texttt{ParallelDirective}.
Сначала рассматриваются директивы распределения данных. Для каждой директивы, по информации из структуры, строится её текстовое представление: в виде строк конструируются DVM-директивы \texttt{ALIGN} и \texttt{DISTRIBUTE}. Далее аналогичный процесс происходит с директивами распараллеливания: формируются директивы \texttt{PARALLEL ON} и все нужные клаузы, такие как \texttt{PRIVATE}, \texttt{REDUCTION}, \texttt{ACROSS}, \texttt{SHADOW\_RENEW}, \texttt{REMOTE\_ACCESS}. Текстовые директивы DVM-системы сохраняются в виде множества структур \texttt{CreatedDirective}, которые хранят текст директивы и строку, перед которой её необходимо будет вставить.
Сначала рассматриваются директивы распределения данных. Для каждой директивы, по информации из структуры, строится её текстовое представление: в виде строк конструируются DVM-директивы \texttt{ALIGN} и \texttt{DISTRIBUTE}. Далее аналогичный процесс происходит с директивами распараллеливания: формируются директивы \texttt{PARALLEL ON} и все нужные клаузы, такие как \texttt{PRIVATE}, \texttt{REDUCTION}, \texttt{ACROSS}, \texttt{SHADOW\_RENEW}, \texttt{REMOTE\_ACCESS}. Текстовые директивы DVM-системы сохраняются в виде множества структур \texttt{CreatedDirective}, которые хранят текст директивы и номер строки, перед которой её необходимо вставить.
Наконец, проход INSERT\_PARALLEL\_DIRS, получающий множество созданных директив, производит их вставку в виде комментариев в АСД обрабатываемой программы перед соответствующими операторами.

View File

@@ -1,15 +1,15 @@
\section{Описание алгоритмов}
\section{Описание алгоритмов распараллеливания в системе SAPFOR}
В предыдущей главе поверхностно описывались функции проходов, работающих при распараллеливании с распределением данных и их аналогов для случая общей памяти. В этой главе приводится подробное описание алгоритмов, с помощью которых реализованы эти проходы.
В предыдущей главе было дано краткое описание проходов, работающих при распараллеливании с распределением данных и их аналогов для случая общей памяти. Далее приводится подробное описание алгоритмов, с помощью которых реализованы эти проходы.
Весь исходный код системы SAPFOR написан на языке C++. Программа, поступающая на вход системе, переводится в абстрактное синтаксическое дерево операторов (АСД). В качестве реализации абстрактного синтаксического дерева используется библиотека Sage++ \cite{sage}. С её помощью входную программу можно анализировать, модифицировать и переводить обратно в код на фортране.
Весь исходный код системы SAPFOR написан на языке C++ \cite{cpp}. Программа, поступающая на вход системе, переводится в абстрактное синтаксическое дерево операторов (АСД) \cite{dragonbook}. В качестве реализации абстрактного синтаксического дерева используется библиотека Sage++ \cite{sage}. С её помощью входную программу можно анализировать, модифицировать и переводить обратно в код на Фортране.
Помимо структур библиотеки Sage++, в системе SAPFOR введён ряд типов данных, упрощающих разработку. Среди них можно выделить следующие наиболее используемые:
\begin{itemize}
\item \texttt{Array} -- тип, отражающий массив входной программы. Помимо прочего, содержит информацию о его имени, размерности, определении, местах использования;
\item \texttt{FuncInfo} -- отражает процедуру входной программы. Содержит информацию о названии, определении, точках её вызова, подключенных common-блоков, именах её формальных аргументов, информацию о наличие побочных эффектов и т. д.;
\item \texttt{FuncInfo} -- отражает процедуру входной программы. Содержит информацию о названии, определении, точках её вызова, подключенных common-блоков, именах её формальных аргументов, информацию о наличии побочных эффектов и т. д.;
\item \texttt{LoopGraph} -- отражает цикл. Имеет информацию о месте расположения, вложенных циклах, вызовах функций внутри цикла, операциях над массивами внутри цикла. Если цикл находится в канонической форме, дополнительно содержит название итерационной переменной, границах и шаге итерирования, глубину гнезда тесновложенных циклов. Кроме этого структура содержит набор флагов, отмечающих интересующие с точки зрения распараллеливания свойства;

View File

@@ -1,28 +1,30 @@
\subsection{Алгоритмы распараллеливания на общую память}
В этом разделе приведено подробное описание всех изменений, внесённых в систему SAPFOR для поддержки режима распараллеливания на общую память.
Как было описано ранее, проходы LOOP\_ANALYZER\_DATA\_DIST\_S* и CREATE\_TEMPLATE\_LINKS отвечают сугубо за распределение данных, поэтому работа по распараллеливанию на общую память начинается сразу с аналога прохода LOOP\_ANALYZER\_COMP\_DIST, который получил название LOOP\_ANALYZER\_NODIST.
На вход он также принимает АСД программы, множество структур \texttt{LoopGraph} и \texttt{FuncInfo} (но без графа измерений массивов). Отличия в работе начинаются со способа построения кортежей \textit{<цикл, массив, тип операции, номер измерения, A, B>}: при распределении данных такие записи не сохранялись для массивов, которые являются приватными в каком либо цикле программы. При распараллеливании на общую память есть возможность снять это ограничение и отображать на цикл все его неприватные массивы, даже если для других циклов они являются приватными.
Далее, появилась возможность обойти отображение витков цикла на распределяемый массив. Преобразованный алгоритм не запускает поиск наилучшего распределённого массива для распределения вычислений и не заполняет соответствующее поле в структуре \texttt{ParallelDirective}, хотя заполнение других полей, таких как ACROSS-зависимости, остаёься актуальным.
Далее, появилась возможность обойти отображение витков цикла на распределяемый массив. Преобразованный алгоритм не запускает поиск наилучшего распределённого массива для распределения вычислений и не заполняет соответствующее поле в структуре \texttt{ParallelDirective}, хотя заполнение других полей, таких как ACROSS-зависимости, остаётся актуальным.
На следующем этапе работает новый проход SELECT\_ARRAY\_DIM\_CONF решающий проблему распараллеливания циклов, использующих секции массивов. Подробно проблема описывалась в предыдущей главе. На вход алгоритм принимает множество структур \texttt{LoopNode} с заполенными полями параллельных директив \texttt{ParallelDirective}. Так же передаётся \textit{граф связей между массивами}. Вершинами этого ориентированного графа являются структуры \texttt{Array}. Дуги строятся по следующему правилу: пусть массив \textit{B} является формальным аргументом процедуры \textit{F}. Тогда в графе существует дуга от массива \textit{A} к \textit{B} в том и только том случае, если есть вызов процедуры \textit{F} с предачей секции массива \textit{A} в качестве фактического аргумента для \textit{B}.
На следующем этапе работает новый проход SELECT\_ARRAY\_DIM\_CONF решающий проблему распараллеливания циклов, использующих секции массивов. Подробно проблема описывалась в предыдущей главе. На вход проход принимает множество структур \texttt{LoopNode} с заполненными полями параллельных директив \texttt{ParallelDirective}. Так же передаётся \textit{граф связей между массивами}. Вершинами этого ориентированного графа являются структуры \texttt{Array}. Дуги строятся по следующему правилу: пусть массив \textit{B} является формальным аргументом процедуры \textit{F}. Тогда в графе существует дуга от массива \textit{A} к \textit{B} в том и только том случае, если есть вызов процедуры \textit{F} с передачей секции массива \textit{A} в качестве фактического аргумента для \textit{B}.
Перед тем как рассматривать работу алгоритма, введём два понятия. Будем называть масив \textit{главным}, если он не является формальным аргументом функции, в которой он определён. Заметим, что в графе связей между массивами главными будут те и только те, которые не имеют входящих дуг. Также назовём \textit{конфигурацией} n-мерного массива кортеж из n чисел $a_{i}$, в котором $a_{i}$ является длинной i-го измерения.
Перед тем как рассматривать работу алгоритма, введём два понятия. Будем называть массив \textit{главным}, если он не является формальным аргументом функции, в которой он определён. Заметим, что в графе связей между массивами главными будут те и только те, которые не имеют входящих дуг. Также назовём \textit{конфигурацией} n-мерного массива кортеж из n чисел $a_{i}$, в котором $a_{i}$ является длинной i-го измерения.
Алгоритм работает следующим образом:
\begin{itemize}
\item для каждого главного массива строится множество конфигураций массивов, достижимых из главного в графе связей массивов;
\item для каждого главного массива выбирается лучшая конфигурация -- такая, которая соовтветствует наибольшему суммарному количеству элементов (суммарное кол-во элементов вычисляется как произведение элементов кортежа);
\item для каждого главного массива выбирается лучшая конфигурация -- такая, которая соответствует наибольшему суммарному количеству элементов (суммарное кол-во элементов вычисляется как произведение элементов кортежа);
\item рассматриваются все невыбранные конфигурации. Все циклы, которые используют хоть один массив, конфигурация которого не была выбрана на прошлом шаге, отстраняются от распараллеливания путём поднятия специального флага \texttt{hasAccessToSubArray} в структуре \texttt{LoopGraph} и удаления в ней директивы распараллеливания, если она была;
\item рассматриваются все невыбранные конфигурации. Все циклы, которые используют хоть один массив, конфигурация которого не была выбрана на прошлом шаге, отстраняются от распараллеливания путём поднятия специального флага \texttt{hasAccessToSubArray} в структуре \texttt{LoopGraph} и удаления в ней директивы распараллеливания, если она была.
\end{itemize}
Таким образом, после данного прохода от распараллеливания будут отстранены циклы, которые могут спровоцировать ошибку выполнения системы DVM.
Таким образом, после данного прохода из распараллеливания будут исключены циклы, которые могут вызвать ошибку при выполнении программы.
Далее в проходе INSERT\_PARALLEL\_DIRS\_NODIST запускается алгоритм получения текстового представления директив распараллеливания \texttt{ParallelDirective}, который имет следующие отличия от случая распараллеливания с распределением:
Далее в проходе INSERT\_PARALLEL\_DIRS\_NODIST запускается алгоритм получения текстового представления директив распараллеливания \texttt{ParallelDirective}, который имеет следующие отличия от случая распараллеливания с распределением данных:
\begin{itemize}
\item директивы распределения данных не используются проходом и не обрабатываются;
@@ -31,7 +33,7 @@
\item не происходит конструирование клауз \texttt{SHADOW\_RENEW} и \texttt{REMOTE\_ACCESS};
\item добавлено конструирование клауз \texttt{TIE}. Для заполнения списка отображаемых массивов используется сохранённая информация об обращениях к массивам с прохода LOOP\_ANALYZER\_NODIST;
\item добавлено конструирование клауз \texttt{TIE}. Для заполнения списка отображаемых массивов используется сохранённая информация об обращениях к массивам с прохода LOOP\_ANALYZER\_NODIST.
\end{itemize}
В результате получается множество созданных директив \texttt{CreatedDirective}, содержащее только директивы распараллеливания на общую память.

View File

@@ -3,13 +3,13 @@
DVM-система (Distributed Virtual Memory или Distributed Virtual Maсhine) представляет собой набор программных средств, которые позволяют пользователю производить следующие операции:
\begin{itemize}
\item компилировать параллельные программы на языках C-DVMH (расширение языка Си) и Fortran-DVMH (расширение языка фортран);
\item компилировать параллельные программы на языках C-DVMH (расширение языка Си) и Fortran-DVMH (расширение языка Фортран);
\item запускать скомпилированные программы;
\item отлаживать скомпилированные программы (на предмет производительности и корректности распараллеливания);
\item отлаживать скомпилированные программы (на предмет производительности и корректности распараллеливания).
\end{itemize}
DVM-система ведёт работу с программами, написанными на языках C-DVMH или Fortran-DVMH, которые представляют собой расширения для языков Си и фортран соответственно. Они позволяют распараллеливать последовательные программы при помощи добавления директив -- прагм (для языка Си) или спецкомментариев (для языка фортран). Похожий подход используется в технологиях OpenMP, OpenACC и др.
DVM-система ведёт работу с программами, написанными на языках C-DVMH или Fortran-DVMH, которые представляют собой расширения для языков Си 99 \cite{C99} и Фортран 95 \cite{F95} соответственно. Они позволяют распараллеливать последовательные программы при помощи добавления директив -- прагм (для языка Си) или спецкомментариев (для языка Фортран). Похожий подход используется в технологиях OpenMP, OpenACC и др.
Целевая вычислительная система модели DVMH рассматривается как совокупность узлов, каждый из которых имеет свою оперативную память. Чаще всего такие узлы состоят из процессора, к которому подключено несколько ускорителей.
При этом, DVMH-модель основана на параллелизме по данным. Это означает, что DVM, в соответствии с заданными пользователем директивами, распределяет данные (в данном случае элементы массивов) по доступным узлам вычислительной системы. После этого, по принципу собственных вычислений, согласно которому каждый узел выполняет те и только те вычисления, которые относятся к данным, расположенным в его оперативной памяти, происходит распределение вычислений.
При этом, DVMH-модель основана на параллелизме по данным. Это означает, что библиотека поддержки системы DVM распределяет данные (в данном случае элементы массивов) по доступным узлам вычислительной системы в соответствии с заданными пользователем директивами. После этого, по принципу собственных вычислений, согласно которому каждый узел выполняет те и только те вычисления, которые относятся к данным, расположенным в его оперативной памяти, происходит распределение вычислений.

View File

@@ -7,27 +7,24 @@
\item анализировать абстрактные последовательности операторов с точки зрения возможности их параллельного выполнения сложнее, чем анализировать зависимости между витками циклов;
\item явное указание распараллеливаемых частей кода влечёт за собой изменения в структуре кода, в то время как указание параллельного цикла обычно выглядит как директива перед его заголовком;
\item явное указание распараллеливаемых частей кода влечёт за собой изменения в структуре кода, в то время как указание параллельного цикла обычно выглядит как директива перед его заголовком.
\end{itemize}
Более того, принято рассматривать только циклы, находящиеся в \textit{канонической форме}, то есть циклы, у которых есть итерационная переменная, проходящая заданный диапазон значений с заданным шагом:
\begin{lstlisting}[style=FORT,caption={
пример цикла в канонической форме на языке фортран с итерационной переменной \texttt{i}, принимающая все значения от 1 до 10.
Пример цикла в канонической форме на языке Фортран с итерационной переменной \texttt{i}, принимающая все значения от 1 до 10.
}]
...
DO i = 1, 10
...
ENDDO
...
\end{lstlisting}
Иногда приходится иметь дело с вложенными циклами, у которых нет операторов между заголовками и концами циклов. Их совокупность называют \textit{гездом тесновложенных циклов}, или просто гнездом циклов. С точки зрения параллелизма, в общем случае выгоднее распараллеливать не только самый верхний цикл в гнезде, а гездо целиком, увеличивая тем самым итерационное пространство.
Иногда приходится иметь дело с вложенными циклами, у которых нет операторов между заголовками и концами циклов. Их совокупность называют \textit{гнездом тесновложенных циклов}, или просто гнездом циклов. С точки зрения параллелизма, в общем случае выгоднее распараллеливать не только самый верхний цикл в гнезде, а гнездо целиком, увеличивая тем самым итерационное пространство.
\begin{lstlisting}[style=FORT,caption={
пример гнезда из трёх тесновложенных циклов.
Пример гнезда из трёх тесновложенных циклов.
}]
...
DO i = 1, 10
DO j = 2, 20
DO k = 3, 30
@@ -35,51 +32,45 @@
ENDDO
ENDDO
ENDDO
...
\end{lstlisting}
Будем говорить, что витки цикла (или гнезда циклов) имеют \textit{зависимость по данным}, если в нём существуют два витка $i_0$ и $i_1$ такие, что в последовательной программе виток $i_0$ записывает какие-либо данные, а виток $i_1$ их считывает.
Будем говорить, что витки цикла (или гнезда циклов) имеют \textit{зависимость по данным}, если в нём существуют два витка $i_0$ и $i_1$ такие, что в последовательной программе виток $i_0$ записывает какие-либо данные, а виток $i_1$ их считывает.
\pagebreak
\begin{lstlisting}[style=FORT,caption={
пример цикла с зависимостью по данным, где каждый виток с номером $i$ записывает данные, которые читают витки $i+1$ и $i+2$.
Пример цикла с зависимостью по данным, где каждый виток с номером $i$ записывает данные, которые читают витки $i+1$ и $i+2$.
}]
...
DO i = 3, 10
A(i) = A(i - 1) + A(i - 2)
ENDDO
...
\end{lstlisting}
В общем случае такие циклы нельзя распараллеливать, так как в них важен порядок итераций, но существует несколько разных приёмов, позволяющих в некоторых случаях избегать зависимости по данным.
В общем случае такие циклы нельзя распараллеливать, так как в них важен порядок итераций, но существует несколько разных приёмов, позволяющих в некоторых случаях устранить зависимости по данным.
Важным этапом распараллеливания явлется определение того, какие данные являются локальными или общими по отношению к виткам циклов. Если скалярная переменная или массив перед использованием переопределяется (перезаписываются значения элементов соответственно) на той же самой итерации, то говорят, что такая переменная является \textit{приватной переменной} или \textit{приватным массивом} соответственно. Из определения следует, что счётчик цикла всегда приватен.
\begin{lstlisting}[style=FORT,caption={
пример цикла по \texttt{i} с приватным массивом \texttt{TMP} и приватными переменными \texttt{i} (счётчик), \texttt{j}, \texttt{t}.
Пример цикла по \texttt{i} с приватным массивом \texttt{TMP} и приватными переменными \texttt{i} (счётчик), \texttt{j}, \texttt{t}.
}]
...
DO i = 1, 10
DO j = 1, 100
TMP(j) = j
ENDDO
t = TMP(100)
...
ENDDO
...
\end{lstlisting}
Похожим является класс \textit{редукционных переменных}. Он состоит из переменных, значения которых после цикла зависят от каждой итерации цикла, но не зависят от порядка их выполнения. При этом бинарная операция, с помощью которых объединяются частичные значения, называется \textit{редукционной}.
\begin{lstlisting}[style=FORT,caption={
пример цикла с редукционной переменной \texttt{sum} (редукционная операция -- сложение).
Пример цикла с редукционной переменной \texttt{sum} (редукционная операция -- сложение).
}]
...
sum = 0
DO i = 1, 10
sum = sum + A(i)
ENDDO
write(*, *) sum
...
\end{lstlisting}

View File

@@ -2,15 +2,15 @@
В современном мире спрос на вычисления растёт быстрее, чем тактовая частота работы процессоров, что обусловлено физическими проблемами и ограничениями. Из-за этого вычислительные системы наращивают свою мощь за счёт увеличения числа вычислительных ядер. Это привело к тому, что в настоящее время стала актуальна тема параллельных вычислений. Различные технологии параллельного программирования дают людям возможность эффективно использовать многоядерные процессоры и графические ускорители.
Создание параллельного кода -- задача, требующая больших трудозатрат и высокой квалификации. Есть технологии, которые требуют от разработчиков большого внимания к деталям распараллеливания. Они интегрируются в логику программ, что позволяет писать максимально эффективный код, что, в свою очередь, ведёт к дополнительному, иногда огромному, усложнению структур программ. Примерами таких технологий являются библиотеки параллельного программирования pthreads, CUDA, HIP, OpenCL.
Создание параллельного кода -- задача, требующая больших трудозатрат и высокой квалификации. Есть технологии, которые требуют от разработчиков большого внимания к деталям распараллеливания. Они интегрируются в логику программ, что позволяет писать максимально эффективный код, что, в свою очередь, ведёт к дополнительному, иногда огромному, усложнению структур программ. Примерами таких технологий являются pthreads \cite{pthreads}, CUDA \cite{cuda}, HIP \cite{hip}, OpenCL \cite{opencl} и др.
Для борьбы со сложностью разработки параллельного кода, были созданы средства, с помощью которых можно добиться распараллеливания не изменяя логику работы программ. При таком подходе можно потерять в эффективности по сравнению с предыдущими технологиями, но сэкономить человеческие ресурсы. Такие технологии обычно предоставляют программисту лёгкий у удобный интерфейс, оформленный в виде специальных директив компилятору. Сюда можно отнести технологии OpenMP, OpenACC, DVM.
Для борьбы со сложностью разработки параллельного кода были созданы средства, с помощью которых можно добиться распараллеливания не изменяя логику работы программ. При таком подходе можно потерять в эффективности по сравнению с предыдущими технологиями, но сэкономить человеческие ресурсы. Такие технологии обычно предоставляют программисту лёгкий и удобный интерфейс, оформленный в виде специальных директив компилятору. Сюда можно отнести технологии OpenMP \cite{openmp}, OpenACC \cite{openacc}, DVM \cite{dvm-site}.
Наконец, существуют инструменты, которые ещё сильнее снижают трудозатраты процесса распараллеливания. С помощью них можно в автоматизированном режиме получать параллельные программы из последовательных. Часто это накладывает ограничения на возможности распараллеливания, но ввиду нехватки человеческих ресурсов такой подход в определённых случаях может быть оправдан. К этому классу относятся инструменты такие как CAPTools/Parawise, FORGE Magic/DM, ParalWare Trainer, SAPFOR.
Наконец, существуют инструменты, которые ещё сильнее снижают трудозатраты процесса распараллеливания. С помощью них можно в автоматизированном режиме получать параллельные программы из последовательных. Часто это накладывает ограничения на возможности распараллеливания, но ввиду нехватки человеческих ресурсов такой подход в определённых случаях может быть оправдан. К этому классу относятся инструменты такие как CAPTools/Parawise, FORGE Magic/DM, ParalWare Trainer, SAPFOR \cite{sapfor-1}.
Больших успехов в направлении экономии человеческих ресурсов достигли учёные из Института прикладной математики им. М.В. Келдыша Российской академии наук \cite{keldysh}. В Институте были разработаны и активно поддерживаются два средства параллельного программирования: это DVM-система \cite{dvm-site} -- программный комплекс для компиляции, выполнения и отладки параллельного кода, а также инструмент для автоматизированного распараллеливания программ -- система SAPFOR \cite{sapfor-1}, \cite{sapfor-2}.
Перед тем, как перейти к основной теме данной работы, в этой главе будут описаны некоторые сведения о параллельном программированнии, как общеизвестные, так и относящиеся исключительно к DVM и SAPFOR, на базе которых и проводилась работа.
Перед тем, как перейти к основной теме данной работы, в этой главе будут описаны некоторые сведения о параллельном программировании, как общеизвестные, так и относящиеся исключительно к DVM и SAPFOR, на базе которых и проводилась работа.
\input{src/sections/intro/general}
\input{src/sections/intro/dvm}

View File

@@ -1,17 +1,16 @@
\subsection{SAPFOR}
Система SAPFOR (System FOR Automated Parallelization) предназначена для автоматизации процесса распараллеливания программ с использованием технологии DVMH. Она, так же как и DVM система, поддерживает языки Си и фортран. Система SAPFOR разделена на два проекта, каждый их которых отвечает за свой язык. В данной работе рассматривается только часть, связанная с языком фортран.
Система SAPFOR (System FOR Automated Parallelization) предназначена для автоматизации процесса распараллеливания программ с использованием технологии DVMH. Она, так же как и DVM-система, поддерживает языки Си и Фортран. Система SAPFOR разделена на два проекта, каждый их которых отвечает за свой язык. В данной работе рассматривается только часть, связанная с языком Фортран.
С помощью системы SAPFOR можно производить не только само распараллеливание, но и множество других преобразований, позволяющих приводить программы к \textit{потенциально параллельному виду} -- к форме, в которой она может быть автоматически переведена в параллельную без участия пользователя. Для удобства проведения таких манипуляций была создана графическая оболочка, которая предоставляет пользователям системы удобный интерфейс для использования системы SAPFOR.
С помощью системы SAPFOR можно производить не только само распараллеливание, но и множество других преобразований, позволяющих приводить программы к \textit{потенциально параллельному виду} -- к форме, в которой она может быть автоматически переведена в параллельную без участия пользователя. Для удобства проведения таких манипуляций была создана графическая оболочка, которая предоставляет пользователям системы удобный интерфейс для её использования.
Также система SAPFOR предоставляет набор директив, с помощью которых пользователь может управлять поведением системы при обработке программы. Например, с помощью таких директив можно задавать различные свойства программы, давать указания на расстановку контрольных точек, ограничивать распараллеливание. Сейчас системой поддерживается около десяти различных директив.
Рассмотрим подробнее две из них, которые будут упомянаться далее в работе, более пристально. Это директивы приватизации и редукции. Директива приватизации, как и все директивы системе SAPFOR, представлена в виде комментария, начинающегося с префикса \texttt{\$SPF}. Далее идёт тело директивы, которое имеет вид \texttt{ANALYSIS (PRIVATE(...))}, где вместо троеточия должен быть указан список приватных переменных (скаляров или массивов) через запятую. Следующий пример демонстрирует использование директивы \texttt{PRIVATE} системы SAPFOR:
Рассмотрим подробнее директивы приватизации и редукции, которые будут упомянаться далее в работе. Директива приватизации, как и все директивы системе SAPFOR, представлена в виде комментария, начинающегося с префикса \texttt{\$SPF}. Далее идёт тело директивы, которое имеет вид \texttt{ANALYSIS (PRIVATE(...))}, где вместо троеточия должен быть указан список приватных переменных (скаляров или массивов) через запятую. Следующий пример демонстрирует использование директивы \texttt{PRIVATE} системы SAPFOR:
\begin{lstlisting}[style=FORT,caption={
пример задания приватного массива \texttt{B} для цикла на строке 3 с помощью директивы системе SAPFOR.
Пример задания приватного массива \texttt{B} для цикла на строке 2 с помощью директивы системе SAPFOR.
}]
...
!$SPF ANALYSIS(PRIVATE(B))
DO I = 1, N
DO J = 1, N
@@ -20,16 +19,17 @@
A(I) = B(A(I))
END DO
...
\end{lstlisting}
Хотя скаляры и можно объявлять в директиве приватизации, на практике обычно это не используется, потому что в системе SAPFOR при распараллеливании автоматически производится анализ приватных скалярных переменных.
Аналогично устроена директива \texttt{!\$SPF ANALYSIS (REDUCTION(OP(...)))}, задающая редукцию по переменным из списка, стоящем вместо троеточия. \texttt{OP} в директиве задаёт редукционную операцию. Далее приведён приведён пример использования этой директивы:
Аналогично устроена директива \texttt{!\$SPF ANALYSIS (REDUCTION(OP(...)))}, задающая редукцию по переменным из списка, стоящем вместо троеточия. \texttt{OP} в директиве задаёт редукционную операцию. Далее приведён пример использования этой директивы:
\pagebreak
\begin{lstlisting}[style=FORT,caption={
пример задания редукции по переменной \texttt{EPS} с редукционной операцией взятия максимума.
Пример задания редукции по переменной \texttt{EPS} с редукционной операцией взятия максимума.
}]
...
!$SPF ANALYSIS(REDUCTION (MAX(EPS)))
DO I = 1, N
DO J = 1, N
@@ -37,5 +37,4 @@
A(I, J) = B(I, J)
END DO
END DO
...
\end{lstlisting}

View File

@@ -1,11 +1,11 @@
\subsection{Второй этап -- реализация}
Новый режим работы распараллеливания на общую память был оформлен как отдельных проход. По аналогии этот проход был назван \\ INSERT\_PARALLEL\_DIRS\_NODIST, что подчёркивает отсутвие построения распределения данных. Поскольку INSERT\_PARALLEL\_DIRS осуществляет только вставку созданных заранее директив, его функционал менять не пришлось, поэтому внутри INSERT\_PARALLEL\_DIRS\_NODIST вызывается код прохода INSERT\_PARALLEL\_DIRS.
Новый режим работы распараллеливания на общую память был оформлен как отдельных проход. По аналогии этот проход был назван \\ INSERT\_PARALLEL\_DIRS\_NODIST, что подчёркивает отсутствие построения распределения данных. Поскольку INSERT\_PARALLEL\_DIRS осуществляет только вставку созданных заранее директив, его функционал менять не пришлось, поэтому внутри INSERT\_PARALLEL\_DIRS\_NODIST вызывается код прохода INSERT\_PARALLEL\_DIRS.
Само создание текста параллельных директив, которое происходило в проходе CREATE\_PARALLEL\_DIRS, подверглось правкам. Оттуда полностью убран код, отвечающий за директивы распределения данных. Также изменён код для конструирования параллельных директив: убрано создание приставки ON в директиве и клауз удалённого доступа к данным, среди которых \texttt{SHADOW\_RENEW} и \texttt{REMOTE\_ACCESS}. Также был добавлен алгоритм заполнения клауз \texttt{TIE}. Оказалось, что новая версия CREATE\_PARALLEL\_DIRS стала намного компактнее и было решено не создавать для неё отдельный проход и сделать частью INSERT\_PARALLEL\_DIRS\_NODIST.
Само создание текста параллельных директив, которое происходило в проходе CREATE\_PARALLEL\_DIRS, подверглось изменениям. Оттуда полностью убран код, отвечающий за директивы распределения данных. Также изменён код для конструирования параллельных директив: убрано создание приставки ON в директиве и клауз удалённого доступа к данным, среди которых \texttt{SHADOW\_RENEW} и \texttt{REMOTE\_ACCESS}. Также был добавлен алгоритм заполнения клауз \texttt{TIE}. Оказалось, что новая версия CREATE\_PARALLEL\_DIRS стала намного компактнее и было решено не создавать для неё отдельный проход и сделать частью INSERT\_PARALLEL\_DIRS\_NODIST.
Также, новый проход не унаследовал зависимости от проходов \\ CREATE\_TEMPLATE\_LINKS и LOOP\_ANALYZER\_DATA\_DIST\_S*, посколько они отвечали только за распределение данных.
Также, новый проход не унаследовал зависимости от проходов \\ CREATE\_TEMPLATE\_LINKS и LOOP\_ANALYZER\_DATA\_DIST\_S*, поскольку они отвечали только за распределение данных.
Проход LOOP\_ANALYZER\_COMP\_DIST пришлось переработать. Он отвечал за анализ обращений к массивам внутри цикла и распараллеливание на основе этой информации. Преобразованный проход получил название LOOP\_ANALYZER\_NODIST.
@@ -13,7 +13,7 @@
\begin{figure}[h]
\centering
\includegraphics[scale=0.5]{src/assets/pass_deps_nodist_0.png}
\caption{сравнение схемы работы проходов режима распараллеливания с распределением данных (слева) с новым режимом распараллеливания на общую память (справа).}
\caption{Сравнение схемы работы проходов режима распараллеливания с распределением данных (слева) с новым режимом распараллеливания на общую память (справа).}
\end{figure}
Далее, следует сказать о ещё одной немаловажной части работы -- интеграции с инструментом для визуализации (диалоговой оболочкой) системы SAPFOR. Здесь требовалось реализовать два основных сценария работы. Первый основной сценарий -- запуск распараллеливания на общую память. Требовалось предоставить интерфейс для вызова прохода визуализатором. С этим не возникло сложностей, так как для этого потребовалось написать простую функцию \texttt{SPF\_SharedMemoryParallelization}, которую вызывает диалоговая оболочка и которая в свою очередь запускает проход INSERT\_PARALLEL\_DIRS\_NODIST. Второй сценарий работы предполагал запуск анализа распараллеливания без фактической вставки директив. Аналгично запуску распараллеливания, была добавлена возможность вызывать из визуализатора проход LOOP\_ANALYZER\_NODIST.
Далее, следует сказать о ещё одной немаловажной части работы -- интеграции с инструментом для визуализации (диалоговой оболочкой) системы SAPFOR. Здесь требовалось реализовать два основных сценария работы. Первый основной сценарий -- запуск распараллеливания на общую память. Требовалось предоставить интерфейс для вызова прохода визуализатором. С этим не возникло сложностей, так как для этого потребовалось написать простую функцию \texttt{SPF\_SharedMemoryParallelization}, которую вызывает диалоговая оболочка и которая в свою очередь запускает проход INSERT\_PARALLEL\_DIRS\_NODIST. Второй сценарий работы предполагал запуск анализа распараллеливания без фактической вставки директив. Аналогично запуску распараллеливания, была добавлена возможность вызывать из визуализатора проход LOOP\_ANALYZER\_NODIST.

View File

@@ -11,5 +11,5 @@
\item ошибки при создании кода для CUDA-устройств связанные со встроенными битовыми операциями (DVM)
\item ошибки при создании кода для CUDA-устройств связанные с использованием в фортране ключевых слов языка Си (DVM)
\item ошибки при создании кода для CUDA-устройств связанные с использованием в Фортране ключевых слов языка Си (DVM)
\end{itemize}

View File

@@ -5,22 +5,22 @@
\begin{itemize}
\item как происходит запуск распараллеливания с распределением данных;
\item какой код и в какой последовательни работает при распараллеливании с распределением данных;
\item какой код и в какой последовательности работает при распараллеливании с распределением данных;
\item какие органичивающие проверки планируется убрать в проходе распараллеливания на общую память;
\item какие ограничивающие проверки планируется убрать в проходе распараллеливания на общую память;
\item какие структуры данных используются;
\item использование каких структур данных нужно избежать;
\item какие существующие алгоритмы (с можификациями или без) можно (и нужно) переиспользовать в добавляемом режиме;
\item какие существующие алгоритмы (с модификациями или без) можно (и нужно) переиспользовать в добавляемом режиме.
\end{itemize}
Путём чтения исходного кода, документации и общения с авторами системы все эти вопросы были разрешены. Далее излагаются основные полученные сведения.
Как уже упомяналось ранее, структурно система SAPFOR состоит из множества алгоритмов, которые логически разделены на отдельные блоки -- проходы. Каждый проход выполняет свою функцию и может зависеть от других проходов. При запуске прохода перед ним запускаются все проходы, от которых он зависит непосредственно или транзитивно, при чём каждый проход запускается не больше одного раза. Таким образом в системе выстраивается дерево зависимостей проходов.
Как уже упоминалось ранее, структурно система SAPFOR состоит из множества алгоритмов, которые логически разделены на отдельные блоки -- проходы. Каждый проход выполняет свою функцию и может зависеть от других проходов. При запуске прохода перед ним запускаются все проходы, от которых он зависит непосредственно или транзитивно, при чём каждый проход запускается не больше одного раза. Таким образом в системе выстраивается дерево зависимостей проходов.
Конечным проходом при распараллеливании с распределением данных явлется проход с названием INSERT\_PARALLEL\_DIRS, который производит вставку созданных директив в код. Главные его зависимости -- проход CREATE\_PARALLEL\_DIRS создания параллельных директив (без вставки) по полученной информации из анализа циклов. Анализ циклов производится следующей группой проходов:
Конечным проходом при распараллеливании с распределением данных является проход с названием INSERT\_PARALLEL\_DIRS, который производит вставку созданных директив в код. Главная его зависимость -- проход CREATE\_PARALLEL\_DIRS создания параллельных директив (без вставки) по полученной информации из анализа циклов. Анализ циклов производится следующей группой проходов:
\begin{itemize}
\item LOOP\_ANALYZER\_COMP\_DIST;
@@ -32,14 +32,14 @@
\item LOOP\_ANALYZER\_DATA\_DIST\_S0;
\end{itemize}
Они заполняют структуры, описывающие циклы, анализируют обращения к массивам внутри циклов, отображают обращения к массивам на циклы. Также они создают и заполняют структуру данных, позволяющую строить распределение данных -- \textit{граф измерений массивов}. Вместе с этим происходит вызов прохода CREATE\_TEMPLATE\_LINKS, который по построенному графу создаёт схему распределения данных. До них в работает ещё множество других проходов (всего порядка семидесяти), которые не относятся к распараллеливанию напрямую. Эти проходы не касаются распределения данных, поэтому они пристально не рассматривались. Часть дерева зависимостей прохода вставки параллельных директив изображена на Рис. \ref{fig:distr-alg}:
Они заполняют структуры, описывающие циклы, анализируют обращения к массивам внутри циклов, отображают обращения к массивам на циклы. Также они создают и заполняют структуру данных, позволяющую строить распределение данных -- \textit{граф измерений массивов}. Вместе с этим происходит вызов прохода CREATE\_TEMPLATE\_LINKS, который по построенному графу создаёт схему распределения данных. До них работает ещё множество других проходов (всего порядка семидесяти), которые не относятся к распараллеливанию напрямую. Эти проходы не касаются распределения данных, поэтому они детально не рассматривались. Часть дерева зависимостей прохода вставки параллельных директив изображена на Рис. \ref{fig:distr-alg}:
\pagebreak
\begin{figure}[h]
\centering
\includegraphics[scale=0.5]{src/assets/pass_deps_dist.png}
\caption{упрощённая схема работы проходов при распараллеливании с распределением данных.}
\caption{Упрощённая схема работы проходов при распараллеливании с распределением данных.}
\label{fig:distr-alg}
\end{figure}

View File

@@ -1,6 +1,6 @@
\section{Построение решения}
Весь процесс построения решения можно разделить на три основных этапа -- исследование кодовой базы системы SAPFOR, внесение необходимых правок и тестирование реализованного функционала.
Весь процесс построения решения можно разделить на три основных этапа -- исследование кодовой базы системы SAPFOR, внесение необходимых изменений и тестирование реализованного функционала.
\input{src/sections/solution/prep}
\input{src/sections/solution/impl}

View File

@@ -1,10 +1,10 @@
\subsection{Третий этап -- тестирование и решение возникших проблем}
Поскольку работа ведётся с исходным кодом фортран-программ, множество возможных вариантов входных программ слишком велико, чтобы предусмотреть абсолютно все ситуации на этапе реализации. Из-за этого было необходимо произвести тщательное тестирование, чтобы выявить основные случаи некорректного поведения системы SAPFOR.
Поскольку работа ведётся с исходным кодом Фортран-программ, множество возможных вариантов входных программ слишком велико, чтобы предусмотреть абсолютно все ситуации на этапе реализации. Из-за этого было необходимо произвести тщательное тестирование, чтобы выявить основные случаи некорректного поведения системы SAPFOR.
Тестирование проводилось как на небольших модельных примерах, так и на больших примерах практически используемых программ. Суммарно за всё тестирование было обнаружено порядка тридцати различных примеров некорректного поведения добавленного режима. Далее описаны наиболее содержательные из найденных ошибок и то, как они были исправлены.
Тестирование проводилось как на небольших модельных примерах, так и на больших примерах практически используемых программ. Суммарно за всё тестирование было обнаружено порядка тридцати различных примеров некорректного поведения реализованного режима. Далее описаны наиболее содержательные из найденных ошибок и то, как они были исправлены.
Первая из них касалась обработки приватных массивов. При распределении данных в DVM-системе запрещается распределять массивы, которые являются приватными хотябы для одного цикла. Поэтому в системе SAPFOR такие массивы не отображаются на циклы при построении схемы распределения данных. При распараллеливании на общую память DVM система допускает использование одного массива в качестве приватного и неприватного для разных циклов. Поэтому для режима распараллеливания на общую память было добавлено отображение на цикл всех неприватных для него массивов (в частности, это нужно для заполнения клаузы \texttt{TIE}). Это привело к правкам в проходе LOOP\_ANALYZER\_NODIST.
Первая из них касалась обработки приватных массивов. При распределении данных в DVM-системе запрещается распределять массивы, которые являются приватными хотя бы для одного цикла. Поэтому в системе SAPFOR такие массивы не отображаются на циклы при построении схемы распределения данных. При распараллеливании на общую память DVM-система допускает использование одного массива в качестве приватного и неприватного для разных циклов. Поэтому для режима распараллеливания на общую память было добавлено отображение на цикл всех неприватных для него массивов (в частности, это нужно для заполнения клаузы \texttt{TIE}). Это привело к изменениям в проходе LOOP\_ANALYZER\_NODIST.
Ещё одна проблема связана с обработкой передаваемых в процедуры секций массивов. Дело в том, что в DVM-системе запрещено использование в разных циклах пересекающихся по памяти различных секций массивов. Рассмотрим следующий пример:
@@ -34,9 +34,9 @@ subroutine foo(A)
end
\end{lstlisting}
В нём нём есть два параллельных цикла (строки 8 и 19). Один из них использует полный массив A (который объявлен на строке 3). Другой же использует секцию массива A, которая содержит его первые 50 элементов (объявление на строке 15). Запуск этого примера приводит к ошибке выполнения системы DVM. При этом если бы в подпрограмме \texttt{foo} было объявлено, что массив имеет размер 100 (то есть фактически передавался бы массив целиком), то ошибки бы не было.
В нём нём есть два параллельных цикла (строки 8 и 19). Один из них использует полный массив A (который объявлен на строке 3). Другой же использует секцию массива A, которая содержит его первые 50 элементов (объявление на строке 15). Запуск этого примера приводит к ошибке выполнения. При этом если бы в подпрограмме \texttt{foo} было объявлено, что массив имеет размер 100 (то есть фактически передавался бы массив целиком), то ошибки бы не было.
В случае аналогичного распараллеливания с распределением, ошибок выполнения DVM не возникает. Из-за этого в цепь проходов распараллеливания на общую память был добавлен новый проход, который получил название SELECT\_ARRAY\_DIM\_CONF. Он запускается после анализа циклов и фильтрует параллельные циклы так, чтобы в них не было пересечений по памяти используемых массивов.
В случае аналогичного распараллеливания с распределением данных ошибок выполнения не возникает. Из-за этого в цепь проходов распараллеливания на общую память был добавлен новый проход, который получил название SELECT\_ARRAY\_DIM\_CONF. Он запускается после анализа циклов и выполняет фильтрацию параллельных циклов так, чтобы в них не было пересечений по памяти используемых массивов.
Таким образом схема проходов нового режима получила окончательный вид, представленный на Рис. \ref{fig:deps-final}:

View File

@@ -1,10 +1,10 @@
\subsection{Постановка задачи, определение целей работы}
Так возникает задача добавления в систему SAPFOR дополнительного сценария работы -- распараллеливания фортран-программ без построения схемы распределения данных и с использованием директив \texttt{PARALLEL} без клаузы \texttt{ON}.
Так возникает задача добавления в систему SAPFOR дополнительного сценария работы -- распараллеливания Фортран-программ без построения схемы распределения данных и с использованием директивы \texttt{PARALLEL} без клаузы \texttt{ON}.
Требуется, чтобы новый режим мог обходить ограничения, накладываемые распределением данных, тем самым расширяя класс распараллеливаемых программ на общую память по сравнению со стандартным распараллеливанием на кластер. В частности, вставляемые директивы должны корректно описывать все данные, используемые в цикле, их область хранения в памяти и зависимости типа ACROSS, если они есть.
Также от добавляемого функционала естественно потребовать его \textit{корректность}: при условии, если входная программа корректная, то система SAPFOR должна выдавать правильную параллельную программу, которая должен успешно компилироваться и выполняться.
Также от добавляемого функционала естественно потребовать его \textit{корректность}: если входная программа корректная, то система SAPFOR должна выдавать правильную параллельную программу, которая будет успешно компилироваться и выполняться.
Помимо этого, результирующее распараллеливание должно быть эффективным, то есть давать приемлемый прирост производительности за счёт многопоточного выполнения: не замедлять программу существенно в худших случаях и получать распараллеливание, конкурирующие с ручным в лучших случаях. В это требование дополнительно входит расстановка оптимизирующих клауз \texttt{TIE} в директивы \texttt{PARALLEL} везде, где это возможно.
@@ -17,16 +17,17 @@
\item должна быть добавлена возможность вызова этого режима через диалоговую графическую оболочку;
\item вместе с самим распараллеливанием должен быть добавлен функционал анализа входного кода, который выдавал бы информацию по распараллеливанию без фактической вставки директив. Аналогичный анализ в системе SAPFOR есть и для режима распараллеливания на кластер. Он служит для выявления проблем при автоматизированном распараллеливании;
\item вместе с самим распараллеливанием должен быть добавлен функционал анализа входного кода, который выдавал бы информацию по распараллеливанию без фактической вставки директив. Аналогичный анализ в системе SAPFOR есть и для режима распараллеливания на кластер. Он помогает пользователю выявлять проблемы при автоматизированном распараллеливании.
\end{itemize}
Ещё одной подцелью работы является проверка выполнения этих требований путём проведения тестирования на выбранном множестве программ, которые должны содержать достаточное количество распараллеливаемых циклов разных видов.
Ещё одной подзадачей работы является проверка выполнения этих требований путём проведения тестирования на множестве программ, которые должны содержать достаточное количество распараллеливаемых циклов разных видов.
Рассмотрим небольшой пример ожидаемого распараллеливания на общую память на отрывке программы, реализующей алгоритм Якоби (см. Рис). Система SAPFOR должна успешно вставить все присутствующие директивы DVM-системы. При запуске анализа кода диалоговая система должна сообщить, что внешний цикл распараллелить нельзя (и указать причину), и что внутренние циклы распараллеливаются без препятствий.
Рассмотрим небольшой пример распараллеливания на общую память на части программы, реализующей алгоритм Якоби (см. Листинг \ref{lst:jac}). Система SAPFOR должна успешно вставить все присутствующие директивы DVM-системы. При запуске анализа кода диалоговая система должна сообщить, что внешний цикл распараллелить нельзя (и указать причину), и что внутренние циклы могут быть распараллелены без препятствий.
\pagebreak
\begin{lstlisting}[style=FORT,caption={
пример ожидаемого распараллеливания.}]
...
Пример распараллеливания на общую память.},label={lst:jac}]
do it = 1,itmax
eps = 0.
!DVM$ REGION
@@ -46,8 +47,7 @@
!DVM$ END REGION
if (eps .lt. maxeps) goto 3
enddo
3 continue
...
3 continue
\end{lstlisting}
В дополнение к описанному, существует ещё несколько сценариев использования системы SAPFOR, при котором может пригодиться новый функционал. Во-первых, с помощью режима распараллеливания на общую память можно будет распараллеливать программы, написаные на технологии MPI, что может дать дополнительное ускорение. Во-вторых, данный режим может быть полезен и при обычном распараллеливании с распределением данных: с его помощью можно предварительно оценивать программы на предмет потенциала к распараллеливанию, например заранее узнавать, какие циклы могут быть распараллелены, а какие нет. Используя полученную информацию, можно оценивать вероятность того, что распараллеливание даст положительный эффект ещё до создания схемы распределения данных.
В дополнение к описанному, существует ещё несколько сценариев использования системы SAPFOR, при котором может пригодиться новый функционал. Во-первых, с помощью режима распараллеливания на общую память можно будет распараллеливать программы, написаные с использованием технологии MPI \cite{mpi}, что может дать дополнительное ускорение. Во-вторых, данный режим может быть полезен и при обычном распараллеливании с распределением данных: с его помощью можно предварительно оценивать программы на предмет потенциала к распараллеливанию, например заранее узнавать, какие циклы могут быть распараллелены, а какие нет. Используя полученную информацию, можно оценивать вероятность того, что распараллеливание даст положительный эффект ещё до создания схемы распределения данных.

View File

@@ -9,14 +9,13 @@
\item \texttt{REGION} -- определяет область кода, которую следует выполнять параллельно;
\item \texttt{PARALLEL ... ON} -- определяет цикл, витки которого следует выполнять параллельно, при этом задавая отображение пространства витков цикла на распределённый массив;
\item \texttt{PARALLEL ... ON} -- определяет цикл, витки которого следует выполнять параллельно, при этом задавая отображение пространства витков цикла на распределённый массив.
\end{itemize}
\begin{lstlisting}[style=FORT,caption={
пример распараллеленного в модели DVM гнезда циклов. Здесь происходит отображение элементов массива B на элементы массива A, распределение массива A и распараллеливание гнезда циклов. При запуске на кластере каждый узел получит непрерывные и примерно равные секции массива A, точно такие же секции B и соответствующие этим элементам итерации цикла.
Пример распараллеленного в модели DVM гнезда циклов. Здесь происходит отображение элементов массива B на элементы массива A, распределение массива A и распараллеливание гнезда циклов. При запуске на кластере каждый узел получит непрерывные и примерно равные секции массива A, точно такие же секции массива B и соответствующие этим секциям итерации цикла.
}]
...
!DVM$ DISTRIBUTE (BLOCK,BLOCK) :: A
!DVM$ ALIGN B(I,J) WITH A(I,J)
@@ -29,17 +28,15 @@
END DO
END DO
!DVM$ END REGION
...
\end{lstlisting}
Чтобы дать пользователю возможность распараллеливать программы на общую память, в синтаксис языка DVM-системы была добавлена новая форма директивы \texttt{PARALLEL} для распараллеливания без распределения данных.
Чтобы дать пользователю возможность распараллеливать программы на общую память, в синтаксис языка модели DVMH была добавлена новая форма директивы \texttt{PARALLEL} для распараллеливания без распределения данных.
Новый вариант директивы \texttt{PARALLEL} отличается от исходного тем, что в ней отсутствует клауза \texttt{ON}. При использовании таких директив не надо указывать распределённые массивы. Сами директивы распределения данных также не нужны в таких программах. Более того, в таких директивах \texttt{PARALLEL} не должны присутствовать клаузы доступа к удалённым данных, такие как \texttt{SHADOW\_RENEW}, \texttt{SHADOW\_COMPUTE} и \texttt{REMOTE\_ACCESS}.
Новый вариант директивы \texttt{PARALLEL} отличается от исходного тем, что в ней отсутствует клауза \texttt{ON}. При использовании таких директив не надо указывать распределённые массивы при отображении витков параллельных циклов. Сами директивы распределения данных также не нужны в таких программах. Более того, в таких директивах \texttt{PARALLEL} не должны присутствовать клаузы доступа к удалённым данным, такие как \texttt{SHADOW\_RENEW}, \texttt{SHADOW\_COMPUTE} и \texttt{REMOTE\_ACCESS}.
\begin{lstlisting}[style=FORT,caption={
пример распарараллеливания гнезда циклов на общую память.
Пример распарараллеливания гнезда циклов на общую память.
}]
...
!DVM$ REGION
!DVM$ PARALLEL (I,J), REDUCTION (MAX(EPS)), TIE(A(I, J), B(I, J))
DO I = 1, N
@@ -49,7 +46,6 @@
END DO
END DO
!DVM$ END REGION
...
\end{lstlisting}
Также в таком варианте директивы \texttt{PARALLEL} может присутствовать клауза \texttt{TIE}, сопоставляющая итерации цикла с массивом. Она используется в DVM-системе для улучшения производительности выходного исполняемого кода.
В таком варианте директивы \texttt{PARALLEL} может присутствовать клауза \texttt{TIE}, сопоставляющая итерации цикла с массивом. Она используется в DVM-системе для улучшения производительности выходного исполняемого кода.

View File

@@ -1,5 +1,5 @@
\subsection{Обзор существующих решений}
Исследования по теме автоматизированного распараллеливания программ ведутся достаточно давно. На данный момент существует не так много широко используемых средств, позволяющих получать параллельный код. Среди средств, которые в той или иной степени помогают в процессе распараллеливания программ можно выделить следующие: Polaris, CAPO, WPP, SUIF, VAST/Parallel, OSCAR, ParallelWare, Intel Parallel Studio XE.
Исследования по теме автоматизированного распараллеливания программ ведутся достаточно давно. На данный момент существует не так много широко используемых средств, позволяющих получать параллельный код. Среди средств, которые в той или иной степени помогают в процессе распараллеливания программ можно выделить следующие: Polaris \cite{polaris}, CAPO, WPP, SUIF, VAST/Parallel, OSCAR \cite{oscar}, ParallelWare, Intel Parallel Studio XE \cite{intel}.
Однако, открытых реализаций алгоритмов распараллеливания почти нет, поэтому за основу решения был взят уже существующий в системе SAPFOR режим распараллеливания с распределением данных. Этот подход не только помог учесть спицифику языков фортран и DVM, но и позволил минимизировать объём внесённых в систему SAPFOR изменений.
Однако, открытых реализаций алгоритмов распараллеливания почти нет, поэтому за основу решения был взят уже существующий в системе SAPFOR режим распараллеливания с распределением данных. Этот подход не только помог учесть специфику языков Фортран и DVMH, но и позволил минимизировать объём внесённых в систему SAPFOR изменений.

View File

@@ -1,3 +1,3 @@
\subsection{Мотивация поддержки режима распараллеливания на общую память в системе SAPFOR}
\subsection{Мотивация поддержки в системе SAPFOR}
Поскольку система SAPFOR не способна проанализировать все тонкости логики работы программы, процесс построения оптимальной схемы распределения данных затрудняется. Поэтому аналогичная потребность в функционале распараллеливания на общую память возникает и в системе SAPFOR. Таким образом, реализация нового режима работы системы SAPFOR для распараллеливания на общую память стала для данной работы основной целью, которая детально описывается в последующих параграфах.
Как было отмечено выше, разные циклы могут требовать разных схем распределения данных. Из-за этого возникает проблема поиска оптимального варианта распределения данных при распараллеливании таких программ через систему SAPFOR. Поэтому аналогичная потребность в функционале распараллеливания на общую память возникает и в системе SAPFOR. Таким образом, реализация нового режима работы системы SAPFOR для распараллеливания на общую память стала для данной работы основной целью, которая детально описывается в последующих разделах.

View File

@@ -2,11 +2,11 @@
При написании параллельных DVMH-программ пользователь решает две задачи: он должен найти оптимальный способ распределения данных и обозначить циклы, которые могут выполняться параллельно. На практике нередко возникают ситуации, когда для рассматриваемой программы решить первую задачу трудно или невозможно, но вторая задача решается успешно, то есть программа обладает хорошим потенциалом для распараллеливания.
Основной проблемой, возникающей при попытке построить схему распределения данных, является то, что разные циклы для их распараллеливания могут требовать разных, конфликтующих, схем распределения данных. При распараллеливании практически значимых программ, в силу их объёмности, такие конфликты возникают повсеместно. Эта проблема подробно рассматривается в \cite{par-reg}.
Основной проблемой, возникающей при попытке построить схему распределения данных, является то, что разные циклы для их распараллеливания могут требовать разных, конфликтующих схем распределения данных. В силу объёмности практически значимых программ при их распараллеливании такие конфликты возникают повсеместно. Эта проблема подробно рассматривается в \cite{par-reg}.
Выходом из такой ситуации является рассмотрение частного случая -- распараллеливания на общую память. При таком распараллеливании предполагается, что целевая вычислительная система состоит из единственного устройства. Это ограничение позволяет обойти потребность в распределении данных, так как все данные располагаются в общей оперативной памяти устройства.
Выходом из такой ситуации является рассмотрение частного случая -- распараллеливания на общую память. При таком распараллеливании предполагается, что целевая вычислительная система состоит из единственного устройства. Это ограничение позволяет убрать необходимость в распределении данных, так как все данные располагаются в общей оперативной памяти устройства.
В качестве устройства для запуска программы, распараллеленной на общую память, можно рассматривать многопоточный процссор или графический ускоритель (видеокарту).
В качестве устройства для запуска программы, распараллеленной на общую память, можно рассматривать многопоточный процeссор или графический ускоритель.
\input{src/sections/task/dvm_shared}
\input{src/sections/task/sapfor_shared}

View File

@@ -1,6 +1,6 @@
\subsection{NAS Parallel Benchmarks}
NAS Parallel Benchmarks -- это пакет из десяти программ, разработанных для тестирования производительности многопоточных вычислительных систем, восемь из них написаны на фортране, остальные -- на языке Си. Тесты на фортране включают следующие программы:
NAS Parallel Benchmarks -- это пакет из десяти программ, разработанных для тестирования производительности многопоточных вычислительных систем, восемь из них написаны на Фортране, остальные -- на языке Си. Тесты на Фортране включают следующие программы:
\begin{itemize}
\item BT, SP, LU --
@@ -11,10 +11,12 @@ NAS Parallel Benchmarks -- это пакет из десяти программ,
\item EP -- \textbf{E}mbarrassingly \textbf{P}arallel. Генерация независимых нормально распределённых случайных величин;
\item FT -- \textbf{F}ourier \textbf{T}ransform. Решение трёхмерного уравнения в частных производных при помощи быстрого преобразования Фурье;
\item MG -- \textbf{M}ulti-\textbf{G}rid. Аппроксимация решения трёхмерного дискретного уравнения Пуассона при помощи V-циклового многосеточного метода;
\item UA -- \textbf{U}nstructured \textbf{A}daptive mesh. Решение уравнения теплопроводности с учётом диффузии и конвекции в кубе. Источник тепла подвижен, сетка нерегулярна и меняется каждые 5 шагов;
\item UA -- \textbf{U}nstructured \textbf{A}daptive mesh. Решение уравнения теплопроводности с учётом диффузии и конвекции в кубе. Источник тепла подвижен, сетка нерегулярна и меняется каждые 5 шагов.
\end{itemize}
Каждая программа пакета имеет параллельные версии на OpenMP и на MPI. Кроме того, некоторые тесты имеют также несколько вариантов распараллеливания. Так, например, для теста LU можно выбрать конвеерное распараллеливание, распараллеливание по гиперплоскостям и DO-ACROSS версию. Это распараллеливание было произведено создателями пакета, профессионалами в области параллельных вычислений, поэтому было принято решение взять эти версии за эталон распараллеливания.
Каждая программа пакета имеет параллельные версии на OpenMP и на MPI, созданные разработчиками этого пакета. Кроме того, некоторые тесты имеют несколько вариантов распараллеливания. Так, например, для теста LU можно выбрать конвейерное распараллеливание, распараллеливание по гиперплоскостям или DO-ACROSS версию.
Также этот пакет позволяет запускать все тесты на разных \textit{классах}, что даёт возможность подбирать для конкретной вычислительной системы оптимальный размер задачи, чтобы тест работал не слишком быстро и не слишком долго. Для удобства в каждую программу встроены средства для замера времени работы теста и самопроверка результатов вычислений.
Поскольку распараллеливание произведено разработчиками пакета, профессионалами в области параллельных вычислений, было принято решение взять эти версии за эталон распараллеливания.
Пакет позволяет запускать все тесты на разных \textit{классах данных}, что даёт возможность подбирать для конкретной вычислительной системы оптимальный размер задачи, чтобы тест работал не слишком быстро и не слишком долго. Для удобства в каждую программу встроены средства для замера времени работы теста и самопроверка результатов вычислений.

View File

@@ -1,36 +1,37 @@
\subsection{Процесс распараллеливания}
Часто для того, чтобы получить эффективный параллельный вариант программы с помощью системы SAPFOR, требуется провести ряд преобразований исходного кода. При распараллеливании тестов NAS приходилось совершать много преобразований трёх видов: слияние файлов, подстановка процедур, указание приватных и редукционных массивов.
Часто для того, чтобы получить эффективный параллельный вариант программы с помощью системы SAPFOR, требуется провести ряд преобразований исходного кода. При распараллеливании тестов NAS приходилось совершать много преобразований двух видов: подстановка процедур, указание приватных и редукционных массивов.
Слияние файлов представляет собой несложное преобразование, объединяющие все файлы программы в один. Это преобразование нужно из-за проблем при раздельной компиляции фортран-файлов системой DVM. При помощи диалоговой оболочки это преобразование можно легко делать <<в один клик>>.
В некоторых местах распараллеливание циклов затруднено наличием в теле цикла вызовов процедур. Чтобы распараллелить такие циклы, можно попытаться подставить тело процедуры вместо её вызова. Так как в диалоговой оболочке есть проходы анализа кода и подстановки процедур, можно также без больших усилий найти циклы, которые не распараллеливаются из-за вызовов процедур и произвести подстановку в нужных местах.
В некоторых местах распараллеливание циклов осложнено наличием в теле цикла вызовов процедур. Чтобы распараллелить такие циклы, можно попытаться подставить тело процедуры вместо её вызова. Так как в диалоговой оболочке есть проходы анализа кода и подстановки процедур, можно также без больших усилий найти циклы, которые не распараллеливаются из-за вызовов процедур и произвести подстановку в нужных местах.
Нередко в коде встречаются приватные и редукционные массивы. Так как система SAPFOR в данный момент не поддерживает автоматическое обнаружение таких массивов с помощью методов статического анализа, их приходится вручную указывать при помощи директив \texttt{!\$SPF ANALYSIS (PRIVATE)} и \texttt{!\$SPF ANALYSIS (REDUCTION)}.
Нередко в коде встречаются приватные и редукционные массивы. Так как система SAPFOR в данный момент не поддерживает автоматическое обнаружение таких массивов, их приходится вручную указывать при помощи директив \texttt{!\$SPF ANALYSIS (PRIVATE)} и \texttt{!\$SPF ANALYSIS (REDUCTION)}.
Отдельного внимания потребовала программа LU. Основная вычислительная нагрузка программы приходится на алгоритм SSOR (метод симмтричной последовательной верхней релаксации). Он представляет собой пару гнёзд циклов глубины два. Рассмотрим только первое из этих гнёзд, так как второе распараллеливается полностью аналогично. Возможности параллельного выполнения витков этого цикла мешает только зависимость по данным массива \texttt{rsd}: каждая итерация с номером \textit{(i, j)} использует элементы, которые вычисляются витками \textit{(i - 1, j)}, \textit{(i, j - 1)}. В такой ситуации витки имеют частичный порядок и некоторые группы витков могут выполняться параллельно. В пакете есть три реализации такого распараллеливания:
Отдельного внимания потребовала программа LU. Основная вычислительная нагрузка программы приходится на алгоритм SSOR (метод симметричной последовательной верхней релаксации). Он представляет собой пару гнёзд циклов тесной вложенности два. Рассмотрим только первое из этих гнёзд, так как второе распараллеливается аналогично. Возможности параллельного выполнения витков этого цикла мешает только зависимость по данным массива \texttt{rsd}: каждая итерация с номером \textit{(i, j)} использует элементы, которые вычисляются витками \textit{(i - 1, j)}, \textit{(i, j - 1)}. В такой ситуации витки имеют частичный порядок и некоторые группы витков могут выполняться параллельно. В пакете есть три реализации такого распараллеливания:
\begin{itemize}
\item версия с использованием так называемого \textit{конвейерного параллелизма}. В ней поддержание корректной последовательности витков цикла осуществляется за счёт использования служебного синхронизационного массива и примитивов синхронизации OpenMP \texttt{atomic read} и \texttt{atomic write};
\item в другой версии, которая называется DO-ACROSS, используется похожая схема, только синхронизация реализована механизмом упорядоченного выполнения витков цикла. Для этого в OpenMP есть специальная директива ORDERED;
\item в другой версии, которая называется DO-ACROSS, используется похожая схема, только синхронизация реализована механизмом упорядоченного выполнения витков цикла. Для этого в OpenMP есть специальная директива \texttt{ORDERED};
\item последняя версия использует \textit{параллелизм по гиперплоскостям}. При наличии такой зависимости, витки с номерами \textit{(i, j)}, у которых сумма \textit{i + j} совпадает, образуют гиперплоскости и могут выполняться параллельно (см. Рис. \ref{fig:hp});
\item последняя версия использует \textit{параллелизм по гиперплоскостям}. При наличии такой зависимости, витки с номерами \textit{(i, j)}, у которых сумма \textit{i + j} совпадает, образуют гиперплоскости и могут выполняться параллельно (см. Рис. \ref{fig:hp}).
\end{itemize}
\begin{figure}[h]
\centering
\includegraphics[scale=1]{src/assets/hp.png}
\caption{разделение итерационного пространства на гиперплоскости. Внутри одной гиперплоскости элементы могут считаться параллельно.}
\caption{Разделение итерационного пространства на гиперплоскости. Внутри одной гиперплоскости элементы могут считаться параллельно.}
\label{fig:hp}
\end{figure}
В силу того, что SAPFOR не способен проанализировать логику синхронизаций и зависимости между разными гиперплоскостями, первый и третий варинты распараллелить не удалось. Однако во втором варианте система SAPFOR успешно распознала зависимость по данным и распараллелила цикл с использованием клаузы \texttt{ACROSS}:
\pagebreak
В силу того, что SAPFOR не способен проанализировать логику синхронизаций и зависимости между разными гиперплоскостями, первый и третий варианты распараллелить не удалось. Однако, во втором варианте система SAPFOR успешно распознала зависимость по данным и распараллелила цикл с использованием клаузы \texttt{ACROSS}:
\pagebreak
\begin{lstlisting}[style=FORT,caption={
пример вставленной клаузы ACROSS, задающую зависимость размера 1 по последним двум измерениям массива \texttt{rsd}. В теле цикла происходит чтение элементов массива \texttt{rsd(*,*,j-1,k)}, \texttt{rsd(*,*,j,k-1)}, \texttt{rsd(*,*,j-1,k-1)} и запись в элементы массива \texttt{rsd(*,*,j,k)}.
Пример вставленной клаузы ACROSS, задающую зависимость размера 1 по последним двум измерениям массива \texttt{rsd}. В теле цикла происходит чтение элементов массива \texttt{rsd(*,*,j-1,k)}, \texttt{rsd(*,*,j,k-1)} и запись в элементы массива \texttt{rsd(*,*,j,k)}.
}]
...
!DVM$ REGION
!DVM$ PARALLEL (k,j), PRIVATE (...), TIE(..., rsd(*,*,j,k)), ACROSS (rsd(0:0,0:0,1:0,1:0))
do k = 2,nz - 1
@@ -39,7 +40,6 @@
enddo
enddo
!DVM$ END REGION
...
\end{lstlisting}
Таким образом, в результате автоматизированного распараллеливания были получены параллельные версии тестов BT, CG, EP, FT, SP, LU. Остальные тесты (то есть MG и UA) распараллелить не удалось, даже при помощи преобразований. Причиной этому служит наличие в этих тестах нетривиальной логики, которая не позволяет системе SAPFOR производить распараллеливание.
В результате автоматизированного распараллеливания с помощью системы SAPFOR были получены параллельные версии тестов BT, CG, EP, FT, SP, LU. Остальные тесты (то есть MG и UA) распараллелить не удалось даже при помощи преобразований. Причиной этому служит наличие в этих тестах нетривиальной логики, которая не позволяет системе SAPFOR производить распараллеливание.

View File

@@ -1,6 +1,6 @@
\subsection{Результаты запусков}
После получения распараллеленных на общую память версий тестов был проведен их запуск на различных вычислительных устройствах. Произведено сравнение полученных версий с параллельными версиями на OpenMP. Запуск на процессоре Intel Core i7 980x (6 ядер, 12 потоков, компилятор mpiifort с уровнем оптимизации -O3) показал следующие результаты (см. Рис. \ref{fig:titan_12_all_classes} и \ref{fig:titan_c_all}):
После получения распараллеленных на общую память версий тестов был проведен их запуск на различных вычислительных устройствах. Произведено сравнение полученных версий с параллельными версиями на OpenMP. Запуск на процессоре Intel Core i7 980x \cite{intel} (6 ядер, 12 потоков, компилятор mpiifort с уровнем оптимизации -O3) показал следующие результаты (см. Рис. \ref{fig:titan_12_all_classes} и \ref{fig:titan_c_all}):
\pagebreak
\begin{figure}[hbt!]
@@ -17,26 +17,24 @@
\label{fig:titan_c_all}
\end{figure}
Исследуя данные графики, можно сделать следующие выводы:
На основе полученных результатов можно сделать следующие выводы:
\begin{itemize}
\item сами по себе тесты ускоряются не одинаково: тесты CG, FT, SP дают максимальное ускорение примернов два раза, BT и LU -- в четыре с половиной, EP -- в восемь с половиной;
\item рассматриваемые программы ускоряются не одинаково: тесты CG, FT, SP дают максимальное ускорение примернов два раза, BT и LU -- в четыре с половиной, EP -- в восемь с половиной при запуске на 6-ти ядерном процессоре;
\item на одном и том же классе разные тесты сильно отличаются по времени работы (например, тест BT на 12 потоках работает около 400 секунд, а EP - около 20ти секунд);
\item разрыв между DVM-версиями и OpenMP-версиями на классе A составляет около 10-20\% в пользу OpenMP; на тесте FT разрыва нет вовсе;
\item разница между DVMH-версиями и OpenMP-версиями на классе A составляет около 10-20\% в пользу OpenMP; на тесте FT разницы нет вовсе; с ростом размера задач разрыв уменьшается до 0-5\% на классе C;
\item с ростом размера задач разрыв уменьшается до 0-5\% на классе C;
\item на классе C тесты FT, LU, SP показывают одинаковое ускорение, на BT и CG сохраняется замедление DVMH-версий, DVMH-версия EP ускоряется немного лучше, чем OpenMP-версия;
\item на классе C тесты FT, LU, SP показывают одинаковое ускорение, на BT и CG сохраняется замедление DVM-версий, DVM-версия EP ускоряется немного лучше, чем OpenMP-версия;
\item время работы DVMH-версий и OpenMP-версий на различном количестве используемых потоков также отличается несущественно, с ростом количества потоков это различие уменьшается;
\item время работы DVM-версий и OpenMP-версий на различном количестве используемых потоков также отличается несущественно, с ростом количества потоков это различие уменьшается;
\item есть примеры, на которых DVM-версии быстрее, чем версии на OpenMP и наоборот;
\item есть примеры, на которых DVMH-версии быстрее (EP, класс C), чем версии на OpenMP и наоборот (BT и LU, класс C);
\end{itemize}
Дополнительно были получены результаты работы на графических ускорителях. При тестировании использовались видеокарты Nvidia GeForce GTX 1660 Ti и Nvidia GeForce GTX 1050 Ti.
Дополнительно были получены результаты работы на графических ускорителях. При тестировании использовались видеокарты Nvidia GeForce GTX 1660 Ti и Nvidia GeForce GTX 1050 Ti \cite{nvidia}.
В процессе запусков возникли проблемы с тестом FT. Параллельная версия этого теста содержит приватные массивы больших размеров, что приводило к переполнению памяти видеокарты. Поэтому было принято решение отказаться от запуска программы FT на ускорителях.
@@ -49,18 +47,18 @@
\label{fig:gpu}
\end{figure}
Относительно результатов работы полученных версий на видеокартах спаведливы следующие факты:
Относительно результатов работы полученных версий на видеокартах справедливы следующие факты:
\begin{itemize}
\item тест BT на видеокарте ускорился в 15,3 раз (против 3,6 раз на 12ти потоках на классе C);
\item тест BT на видеокарте ускорился в 15.3 раз (против 3.6 раз на 12ти потоках на классе C);
\item CG -- ускорение в 8,6 раз против 2,7;
\item CG -- ускорение в 8.6 раз против 2.7;
\item EP -- ускорение в 39,7 раз против 8,5 -- самое высокое ускорение;
\item EP -- ускорение в 39.7 раз против 8.5 -- самое высокое ускорение;
\item LU -- ускорение в 5,4 раз против 3,8 -- видеокарта почти не даёт выигрыш по сравнению с многопоточным процессором;
\item LU -- ускорение в 5.4 раз против 3.8 -- видеокарта почти не даёт выигрыш по сравнению с многопоточным процессором;
\item SP -- ускорение в 10,4 раз против 2,5;
\item SP -- ускорение в 10.4 раз против 2.5;
\item с ростом мощности видеокарты растёт и ускорение (модель GeForce GTX 1660 Ti современней и мощней чем GeForce GTX 1050 Ti);
\item с ростом мощности видеокарты растёт и ускорение (модель GeForce GTX 1660 Ti современней и мощней чем GeForce GTX 1050 Ti).
\end{itemize}