Научная статья на тему 'АВТОМАТИЗАЦИЯ ОТЛАДКИ И БАЛАНСИРОВКИ НАГРУЗКИ ВО ФРАГМЕНТИРОВАННЫХ ПРОГРАММАХ'

АВТОМАТИЗАЦИЯ ОТЛАДКИ И БАЛАНСИРОВКИ НАГРУЗКИ ВО ФРАГМЕНТИРОВАННЫХ ПРОГРАММАХ Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
3
0
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
фрагментированное программирование / система LuNA / автоматизированная отладка / динамическая балансировка нагрузки / fragmented programming / LuNA system / automated debugging / dynamic load balancing

Аннотация научной статьи по компьютерным и информационным наукам, автор научной работы — Власенко Андрей Юрьевич, Мичуров Михаил Антонович, Мустафин Дамир Эркинович

Описываются основные принципы, на которых базируется система фрагментированного программирования LuNA и одноименный язык. Даются значения основных терминов, принятых в системе. Приводятся наиболее типичные для фрагментированных программ логические ошибки. Обосновывается важность решения проблемы динамической балансировки нагрузки между процессами, разделяющими работу по исполнению фрагментов вычислений, совокупность которых и составляет фрагментированную программу на этапе исполнения. Поскольку LuNA относится к высокоуровневым средствам создания параллельных программ, то решение проблем отладки и динамической балансировки нагрузки очень затруднительно для пользователя. В связи с этим для системы разрабатываются модуль автоматизированной отладки на основе метода анализа по трассе и модуль автоматической централизованной динамической балансировки нагрузки. Модуль автоматизированной отладки по ходу исполнения фрагментированной программы на каждом процессе собирает файлы трассы в JSON-формате, куда вносится информация об обрабатываемых фрагментах вычислений, а также об их входных и выходных фрагментах данных. После нормального или аварийного завершения работы программы пользователь может вызвать специальное программное средство, анализирующее собранные трассы и выводящее подробную информацию об обнаруженных ошибках. При подключении модуля централизованной динамической балансировки нагрузки порождается служебный процесс, который собирает с рабочих процессов информацию о готовых к исполнению и выполнившихся фрагментах вычислений с целью их перераспределения и минимизации дисбаланса. Изложены результаты тестирования модулей на вычислительном кластере НГУ на задаче блочного умножения матриц, продемонстрировавшие эффективность модуля централизованной балансировки нагрузки и приемлемые накладные расходы модуля автоматизированной отладки.

i Надоели баннеры? Вы всегда можете отключить рекламу.

Похожие темы научных работ по компьютерным и информационным наукам , автор научной работы — Власенко Андрей Юрьевич, Мичуров Михаил Антонович, Мустафин Дамир Эркинович

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

AUTOMATING DEBUGGING AND LOAD BALANCING IN FRAGMENTED PROGRAMS

The LuNA (Language for Numerical Algorithms) fragmented programming system is a high-level tool for creating parallel applications. Programs created using the LuNA can be run on computing systems with shared or distributed memory. The users create their program using a language resembling the standard imperative programming languages (C/C++, Fortran, Pascal, etc.), but does not specify any constructions regarding parallelism. Each operator of the LuNA language causes the generation of a new calculation fragment (CF) at runtime, which accepts objects called data fragments (DF) as its input and output. The totality of CFs makes up a fragmented program at the execution stage. Thus, the algorithm of a fragmented program is represented as a bipartite oriented graph with vertices of types CF and DF. The paper explains the important properties of fragmented programs: the non-deterministic order of operators execution in procedures, the uniqueness of assigning DF values and the absence of arrays in the programmer’s usual understanding. The most typical logical errors for fragmented programs are described, which include an attempt to use uninitialized data, repeated initialization of the same data and a mismatch of data types during initialization and during use. In the case of running a fragmented program on a distributed memory computing system, the processes share the work of executing fragments of calculations. During this work, a situation of computational load imbalance may occur. The paper substantiates the importance of solving this problem. Since LuNA is a high-level parallel programming tool, it is very difficult for the user to solve debugging and load balancing problems. In this regard, the authors of paper develop an automated debugging module based on the "post-mortem" analysis method and an automatic centralized load balancing module for the system. The automated debugging module collects trace files in JSON format during the execution of a fragmented program on each process. These files record information about the processed CFs, as well as their input and output DFs. After the normal or emergency shutdown of the program, the user can call a special software tool (luna_trace) that analyzes the collected traces. The result of its work is the output of detailed information about the detected errors, including a verbal description of the problem, a program statement indicating the string and file name of the source code, a stack of procedure calls and the names of the DFs with which the error is associated. In addition, information specific to a particular error is displayed, for example, for uninitialized DFs — the places of their possible initialization. Another important part of this module functionality is the automatic detection of program hangs. The implementation of hang detection is based on a modification of the distributed Dijkstra-Scholten algorithm. A hang-up situation occurs when one or more errors from frequently occurring classes are made in the LuNA program. In this regard, in the environment of a supercomputer center, where the user loses the ability to interact with the program after queuing the task, this functionality becomes particularly important. The paper explains the fundamental difference between dynamic and static load balancing approaches and outlines the applicability of both approaches for different cases. The importance of developing a dynamic load balancing module in the LuNA system is explained. There are 2 methods of organizing dynamic balancing: based on centralized and distributed algorithms. The module being created implements the first method. The centralized load balancing module launches a service load balancer process along with the "worker processes" that execute CFs. The role of this service process is to collect information from worker processes about executed and readv-to-execute CFs in order to redistribute them and minimize the imbalance. By collecting this information, the load balancer monitors the relative value of the imbalance between the most and the least loaded processes. When this imbalance reaches the threshold value (this threshold is setting by the parameter), the load balancer generates a „balancing plan“ deciding which CFs should be transferred from one process to another. The balancing plan is based on the fragment’s "weights". The execution time of the fragment is taken as the weight. At the same time, if a fragment is transferred from one process to another, then its weight increases by the time of transferring. The paper shows the results of modules testing on the computing cluster of Novosibirsk State University (NSU). Tests were performed on the problem of block matrix multiplication. The presented results demonstrate the effectiveness of the centralized load balancing module and acceptable overhead costs of the automated debugging module. Further development plans regarding the functionality of the modules are given at the end.

Текст научной работы на тему «АВТОМАТИЗАЦИЯ ОТЛАДКИ И БАЛАНСИРОВКИ НАГРУЗКИ ВО ФРАГМЕНТИРОВАННЫХ ПРОГРАММАХ»

AUTOMATING DEBUGGING AND LOAD BALANCING IN

FRAGMENTED PROGRAMS

A. Vlasenko, M. Michurov*, D. Mustafin*

Institute of Computational Mathematics and Mathematical Geophysics of SB RAS,

630090, Novosibirsk, Russia *Novosibirsk State University,

630090, Novosibirsk, Russia

DOI: 10.24412/2073-0667-2022-3-61-76 EDN: NBFMPU

The LuNA (Language for Numerical Algorithms) fragmented programming system is a high-level tool for creating parallel applications. Programs created using the LuNA can be run on computing systems with shared or distributed memory. The users create their program using a language resembling the standard imperative programming languages (C/C++, Fortran, Pascal, etc.), but docs not specify any constructions regarding parallelism. Each operator of the LuNA language causes the generation of a new calculation fragment (CF) at runtime, which accepts objects called data fragments (DF) as its input and output. The totality of CFs makes up a fragmented program at the execution stage. Thus, the algorithm of a fragmented program is represented as a bipartite oriented graph with vertices of types CF and DF. The paper explains the important properties of fragmented programs: the non-dctcrministic order of operators execution in procedures, the uniqueness of assigning DF values and the absence of arrays in the programmer’s usual understanding.

The most typical logical errors for fragmented programs arc described, which include an attempt to use uninitialized data, repeated initialization of the same data and a mismatch of data types during initialization and during use. In the ease of running a fragmented program on a distributed memory computing system, the processes share the work of executing fragments of calculations. During this work, a situation of computational load imbalance may occur. The paper substantiates the importance of solving this problem.

Since LuNA is a high-level parallel programming tool, it is very difficult for the user to solve debugging and load balancing problems. In this regard, the authors of paper develop an automated debugging module based on the ,,post-mortem“ analysis method and an automatic centralized load balancing module for the system.

The automated debugging module collects trace files in .JSON format during the execution of a fragmented program on each process. These files record information about the processed CFs, as well as their input and output DFs. After the normal or emergency shutdown of the program, the user can call a special software tool (luna_traee) that analyzes the collected traces. The result of its work is the output of detailed information about the detected errors, including a verbal description of the problem, a program statement indicating the string and file name of the source code, a stack of procedure calls and the names of the DFs with which the error is associated. In addition, information specific to a particular error is displayed, for example, for uninitialized DFs the places of their possible initialization.

Another important part of this module functionality is the automatic detection of program hangs. The implementation of hang detection is based on a modification of the distributed Dijkstra-Scholtcn

(q) A. Vlasenko, M. Michurov, D. Mustafin, 2022

algorithm. A hang-up situation occurs when one or more errors from frequently occurring classes are made in the LuNA program. In this regard, in the environment of a supercomputer center, where the user loses the ability to interact with the program after queuing the task, this functionality becomes particularly important.

The paper explains the fundamental difference between dynamic and static load balancing approaches and outlines the applicability of both approaches for different cases. The importance of developing a dynamic load balancing module in the LuNA system is explained. There are 2 methods of organizing dynamic balancing: based on centralized and distributed algorithms. The module being created implements the first method. The centralized load balancing module launches a service load balancer process along with the „worker processes11 that execute CFs. The role of this service process is to collect information from worker processes about executed and readv-to-execute CFs in order to redistribute them and minimize the imbalance. By collecting this information, the load balancer monitors the relative value of the imbalance between the most and the least loaded processes. When this imbalance reaches the threshold value (this threshold is setting by the parameter), the load balancer generates a „balancing plan“ deciding which CFs should be transferred from one process to another. The balancing plan is based on the fragment’s „weights11. The execution time of the fragment is taken as the weight. At the same time, if a fragment is transferred from one process to another, then its weight increases by the time of transferring.

The paper shows the results of modules testing on the computing cluster of Novosibirsk State University (NSU). Tests were performed on the problem of block matrix multiplication. The presented results demonstrate the effectiveness of the centralized load balancing module and acceptable overhead costs of the automated debugging module.

Further development plans regarding the functionality of the modules are given at the end.

Key words: fragmented programming, LuNA system, automated debugging, dynamic load balancing.

References

1. Vlasenko, A., Gudov, A. The Use of Erratic Behavior Templates in Debugging Parallel Programs by the Automated Validity Verification Method // Journal of Computer and Systems Sciences International. 2017. V. 56. N 4. P. 708-720.

2. Voevodin, V. V., Voevodin, VI. V. Parallelnie vichisleniva // Spb: BHV-Peterburg, 2002.

3. Akhmed-Zaki, D., Lebedev, D., Malvshkin, V., Perepelkin, V. Automated Construction of High Performance Distibuted Programs in LuNA System // Malvshkin, V. (ed.) 15th International Conference, PaCT 2019, Almaty, Kazakhstan. August 19-23, 2019. P. 3-9.

4. Malvshkin, V. E. Tehnologiva fragmentirovannogo programmirovaniva // Vestnik YUrGU. Seriva: Vichislitelnava matematika i informatika. 2012. N 46 (305). S. 45-55.

5. Mustafin, D. E. Modul centralizovannov dinamicheskov balancirovki nagruzki LuNA-programm // Innovacivi. Nauka. Obrazovanie. 2021. N 40. S. 365-373.

6. Protze, J., Hilbrich, T., Schulz, M., de Supinski, B. R. MPI Runtime Error Detection with MUST: A Scalable and Crash-Safe Approach // 43rd Intern. Conf. on Parallel Processing Workshops. Minneapolis, MN, USA. 2014. P. 206-215.

7. Michurov, M. A. Sredstvo analiza prichin zavisaniv fragmentirovannih programm v sisteme LuNA // Innovacivi. Nauka. Obrazovanie. 2021. N 40. S. 354-364.

8. Fokkink, W. Distributed Algorithms: An Intuitive Approach // MIT Press. 2013. P. 38.

9. Irtegov, D. V. Vvedenie v operacionnie sistemi // Izd. 2. — Sankt-Peterburg: BHV-Peterburg. 2008.

10. Cvbenko, G., Dynamic Load Balancing for Distributed Memory Multiprocessors // J. Parallel and Distributed Comp. 1989.

11. Zaki, М. J., Li, W., Parthasarathv, S. Customized Dynamic Load Balancing for a Network of Workstations // J. Parallel and Distributed Computing. 1997. V. 43. N 2. P. 156-162.

12. Ob IVC NGU // Informacionno-vichislitelniv centr Novosibirskogo gosudarstvennogo universiteta. [Electron. Res.]: http://nusc.nsu.ru/wiki/doku.php/doc/nusc/about (data obrasheniva: 13.02.2022).

13. El-Zoghdv, S. F. A Load Balancing Policy for Heterogeneous Computational Grids // International Journal of Advanced Computer Science and Applications. 2011. V. 2. N 5. P. 93-100.

АВТОМАТИЗАЦИЯ ОТЛАДКИ И БАЛАНСИРОВКИ НАГРУЗКИ ВО ФРАГМЕНТИРОВАННЫХ ПРОГРАММАХ

А. Ю. Власенко, М.А. Мичуров*, Д. Э. Мустафин*

Институт вычислительной математики и математической геофизики СО РАН,

630090, Новосибирск, Россия

* Новосибирский национальный исследовательский государственный университет,

630090, Новосибирск, Россия

УДК 004.Р233; 004.052.42; 004.051 DOI: 10.24412/2073-0667-2022-3-61-76 EDX: XBFMPU

Описываются основные принципы, на которых базируется система фрагментированного программирования LuNA и одноименный язык. Даются значения основных терминов, принятых в системе.

Приводятся наиболее типичные для фрагментированных программ логические ошибки. Обосновывается важность решения проблемы динамической балансировки нагрузки между процессами, разделяющими работу но исполнению фрагментов вычислений, совокупность которых и составляет фрагментированную программу на этане исполнения. Поскольку LuNA относится к высокоуровневым средствам создания параллельных программ, то решение проблем отладки и динамической балансировки нагрузки очень затруднительно для пользователя. В связи с этим для системы разрабатываются модуль автоматизированной отладки на основе метода анализа но трассе и модуль автоматической централизованной динамической балансировки нагрузки.

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

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

Изложены результаты тестирования модулей на вычислительном кластере НГУ на задаче блочного умножения матриц, продемонстрировавшие эффективность модуля централизованной балансировки нагрузки и приемлемые накладные расходы модуля автоматизированной отладки.

Ключевые слова: фрагментированное программирование, система LuNA, автоматизированная отладка, динамическая балансировка нагрузки.

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

(с) А. Ю. Власенко, М, А. Мичуров, Д. Э, Мустафин, 2022

случае параллельных приложений ситуация усугубляется еще сильнее. Появляется множество новых по сравнению с последовательным программированием ошибок, обусловленных взаимодействием одновременно работающих процессов и/или потоков, К этому множеству ошибок принадлежат дедлоки, гонки данных, несоответствия в параметрах коммуникационных процедур при передаче данных между процессами и т, д, [1].

Параллельные программы создаются в первую очередь для ускорения вычислений. Однако ускорение сложной программы зачастую оказывается существенно ниже ожидаемого, сводя эффективность распараллеливания практически к нулю [2]. В связи с этим особую значимость приобретает оптимизация параллельных программ, одной из основных задач которой является достижение хорошего баланса нагрузки.

Главными целями парадигмы фрагментированного программирования и системы

I.U.ХА (Language for Numerical Algorithms) [3] является повышение уровня программирования и абстракция от технических деталей, которые ложатся на пользователя в случае применения таких технологий параллельного программирования, как MPI и ОреиМР, Под „техническими деталями “ имеются в виду следующие задачи: декомпозиция данных и вычислений, программирование коммуникаций, синхронизация работы процессов и потоков, обеспечение динамической балансировки нагрузки, сохранение контрольных точек и пр. Система l.ti.X А берет эти проблемы на себя, оставляя пользователю только запрограммировать сам алгоритм на одноименном языке и в котором не содержится конструкций, явно указывающих на параллелизм при исполнении программы. Созданная на языке l.ti.X А программа может быть запущена на многопроцессорной вычислительной системе с общей памятью или с распределенной памятью,

1. Особенности и проблемы фрагментированного программирования. В технологии фрагментированного программирования, которую реализуют язык и система

l.ti.X А. составляемый фрагментированный алгоритм (ФА) представляет собой двудольный направленный граф, состоящий из фрагментов вычислений (ФВ) и фрагментов данных (ФД) [4]. Если проводить аналогию с традиционными императивными языками, то ФВ будут соответствовать вызовам процедур, а ФД — входным и выходным параметрам этих процедур. Исполняя ФА, ФВ потребляют одни ФД и производят другие, В коде фрагментированной программы реализованные на языке l.ti.X А процедуры называются фрагментами кода (ФК), Таким образом, одному ФК могут соответствовать несколько ФВ, поскольку одна и та же процедура может быть вызвана несколько раз,

ФК могут быть атомарными (функции или процедуры на сторонних языках типа C/C++ или Fortran, содержимое которых система l.ti.X А не анализирует) и структурированными (процедурами на языке l.ti.X А). В процессе трансляции атомарные ФК передаются компилятору соответствующего языка, а структурированные обрабатываются компилятором l.ti.X А. Таким образом, если у пользователя есть собственная библиотека процедур на каком-либо распространенном императивном языке, то он легко может использовать этот наработанный функционал при составлении фрагментированной программы.

Источником параллелизма в описанном ФА является тот факт, что если в некоторый момент могут исполняться несколько ФВ (все их входные ФД уже вычислены), то они могут быть запущены одновременно на различных процессорных ядрах/вычислительных узлах. Отсюда вытекает важное свойство фрагментированных программ. При императивном программировании опера,тор2, следующий по коду за строкой, содержащей оператор 1, выполняется всегда строго после 1-го оператора. Во фрагментированной программе

если ФК2 расположен за ФК1, то это ничего не говорит о порядке, в котором будут выполнены ФВ1 и ФВ2, порожденные запуском этих ФК, поскольку начинают свой жизненный цикл они одновременно.

Жизненный цикл ФВ можно упрощенно представить следующим образом:

1) Отправка запросов на доставку значений входных ФД,

2) Получение всех запрошенных ФД,

3) Выполнение кода ФВ и присваивание значений выходным ФД,

При этом для того чтобы ФВ смог начать работу, все его входные ФД должны быть уже „готовы“ — обладать значениями, В ином случае ФВ просто ожидает готовности ФД,

Еще одно важное свойство LuNA-программ состоит в том, что ФД, в отличие от переменных в большинстве императивных языков, являются объектами единственного присваивания, Их тип и значение определяется непосредственно в момент инициализации. Аналогами массивов в языке LuNA являются индексированные ФД, Их принципиальное отличие от массивов заключается в том, что в императивном языке память выделяется сразу для всех элементов массива. Обращение к элементу массива, лежащему вне выделенного диапазона, является ошибкой и часто приводит к аварийному завершению программы, В языке LuNA память под ФД с определенным индексом выделяется в момент его инициализации. То есть, если, например, в цикле происходит работа только с четными элементами, то нечетных элементов при этом не будет в принципе,

В системе LuNA введены следующие обозначения:

1) Id — объект runtime-системы LuNA, используемый для идентификации ФД и ФВ, Объявлению ФД в LuNA-программе соответствует создание Id во время исполнения,

2) Блок кода — генерируемая транслятором LuNA функция из динамической библиотеки, в которую собирается LuNA-программа, Во время выполнения блоки кода идентифицируются целыми числами — номерами. Блок кода обычно отвечает за определенный этап выполнения ФВ (запрос данных, вызов функций C/C++, порождение новых ФВ, миграция на другой процесс и пр.) По номеру блока можно восстановить информацию о ФК, к которому он относится. Как правило, одному ФВ соответствуют несколько блоков кода. Выполнение ФВ — последовательное выполнение этих блоков кода,

3) Рекомендация — необязательное для исполнения указание runtime-системе LuNA, способное повлиять на эффективность работы программы. Рекомендации могут быть относительно размещения определенных ФД на определенных процессах, удаления ФД в определенный момент, переиспользования памяти и др.

Составляя программу на языке LuNA, пользователь избавляется от управления параллельным исполнением. Он не программирует поведение отдельных ветвей, не распределяет работу между ними, не определяет коммуникации. Всю эту работу берет на себя runtime-система LuNA, По составленному ФА она определяет информационные зависимости между ФВ и запускает в различных потоках или процессах те ФВ, зависимости которых уже удовлетворены. Для коммуникаций между процессами используется N11*1.

Благодаря такому подходу прикладной программист избавляется от обозначенных выше задач. Однако у него появляются новые проблемы, поскольку технологии фрагментированного программирования свойственны ошибки, не присущие ни последовательным, ни параллельным программам, В связи с этим первой задачей, описываемой в данной статье, была поставлена разработка программного обеспечения для автоматизированного обнаружения логических ошибок в LuNA-программах,

Следующая проблема заключается в том, что при исполнении LuNA-программы в силу постоянного порождения новых ФВ на различных вычислительных узлах в течение работы всей программы нередко возникает дисбаланс вычислительной нагрузки. Этот дисбаланс приводит к тому, что аппаратные ресурсы начинают использоваться неэффективно. Для его устранения необходимо передавать ФВ от более нагруженных узлов к менее нагруженным — выполнять „балансировку нагрузки “. В свою очередь, передача ФВ может привести к дополнительной нагрузке на коммуникационную сеть, что может замедлить работу программы в целом. Если имеется несколько свободных узлов, то возникает вопрос, кому из них следует передать нагрузку. Таким образом, необходимо учитывать сетевые и аппаратные ресурсы вычислительной системы. Необходимо также принять во внимание зависимость ФВ от ФД,

Для решения обозначенных проблем второй задачей была поставлена разработка модуля автоматической балансировки нагрузки в системе LuNA [5].

2. Ошибки во фрагментированных программах. В число основных классов логических ошибок для параллельных программ входят ошибки соревнования („гонки дан-ных“) и ошибки, приводящие к бесконечному ожиданию, в частности — дедлоки [6], Эти классы характерны и для фрагментированных программ. Однако отладка LuNA-программ осложняется тем, что входной язык системы предоставляет высокоуровневые абстракции и скрывает от пользователя реализацию параллелизма.

Далее будут рассмотрены наиболее типичные ошибки времени выполнения программы, а также некоторые причины их возникновения,

1) Бесконечное ожидание.

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

Более типичной причиной бесконечного ожидания является использование неинициализированных ФД, Неинициализированным считается ФД, который вообще не получает значения во время работы программы. Как отмечалось ранее, устройство runtime-системы LuNA таково, что исполнение ФВ начинается только после получения значения всеми входными ФД, Если же существуют неинициализированные ФД, то некоторые ФВ невозможно будет выполнить, и runtime-система не сможет завершить работу. Пример LuNA-программы, содержащей ошибку, связанную с использованием неинициализированного ФД, приведен в листинге 1,

Листинг 1, Неинициализированные индексированные ФД

C++ sub set( name х, int val) ${<!} { //name — тип выходного ФД

x,setValue<int>(val); //код на языке C++

}■

sub vec_init( name vec, int size, int val) {

for i = 0,,size-1 {

set(vec[i], val); //vecfij := val

}

}

sub vec_sum( name vl, name v2, int size, name result) { for i = 0,,size-1 {

set (result [i], vl [i] + v2[i]); //result/] := vl[i]+v2[i]

}

}

sub main() { //как в C/C++ main запускается первой df х, у, size, sum; //объявление 4 ФД set(size, 10); vec_init(x, size, 1); vec_init(y, size - 2, 2); vec_sum(x, v, size, sum);

}

В данной программе сложения двух векторов ФД у[8] и у[9] не получают своих значений, в результате чего не могут выполниться ФВ, порожденные вызовами set(result[8], vl[8] + v2[8]) и set(result[9], vl[9] + v2[9j).

2) Ошибки соревнования.

Выше отмечалось одно из свойств языка LuNA: запрещено повторное присваивание значения ФД [4]. Зачастую попытка повторной инициализации ФД приводит к генерации исключения и аварийному завершению runtime-системы. Однако в ситуации, когда на момент повторной инициализации ФД был удален по указанной рекомендации или „сборщиком мусора “, runtime-система не распознает его инициализацию как повторную. В листинге 2 приведен фрагмент LuNA-программы, иллюстрирующей данное поведение. Листинг 2. Повторная инициализация ФД sub main() { df х; set( х, 0);

print ( х) @ { delete х; } //рекомендация, выполняемая, после print wait_and_set( х, 1);

}

Семантика процедур set, wait_ and_ set и print соответствует их именам. С помощью рекомендации delete явно указывается, что ФД х может быть удален после выполнения ФВ.

3) Несоответствие 'типов данных.

Тип, как и значение ФД, определяется непоередетвенно в момент инициализации. Такое решение предоставляет единообразный способ обмена данными между ФВ, однако программист должен знать тип значения, хранимого во ФД, чтобы использовать это значение в атомарных ФК. Попытка использовать ФД как значение неверного типа приводит к аварийному завершению программы. Пример такого поведения приведен в листинге 3. Листинг 3. Использование ФД одного типа в качестве другого типа СН—Ь sub set_real( name х, real v) ${<!} { //real — тип вещественного числа х.set Value (v);

}■

C++ sub print_int(int v) ${<!} { printf(„%d\n“, v);

}■

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

sub main() { df x;

set_real(x, 3.14); print _int(x);

}

3. Автоматическое обнаружение зависаний. Зависание runtime-системы ситуация, когда ни один рабочий поток не может выполнить ни один из оставшихся ФВ. Таким образом, зависания в системе LuNA — проявление ошибки „бесконечного ожидания “,

Для обнаружения логических ошибок в LuNA-программах разрабатывается модуль автоматизированной отладки фрагментированных программ [7]. В числе прочего модуль способен выявлять ситуации зависания.

Автоматическое обнаружение зависания имеет много общего с решением проблемы остановки распределенной вычислительной системы. В настоящее время модуль системы LuNA, отвечающий за остановку runtime-системы после выполнения всех ФВ, основан на алгоритме Дейкстры—Шольтена [8]. Алгоритм подразумевает, что каждый процесс может находиться в одном из двух состояний — „есть работа” и „нет работы”. Вкратце алгоритм заключается в том, что все множество процессов, организованных в кольцо, обходит целочисленный счетчик. Изначально он расположен на некотором процессе, где есть работа. Когда работа на процессе заканчивается, счетчик инкрементируется и передается следующему процессу по кольцу. Если на том процессе, куда передан счетчик, работа есть, то он сбрасывается в значение 0. Если работы нет, то инкрементируется и передается дальше. Решение об остановке принимается тогда, когда значение счетчика равно удвоенному количеству процессов (счетчик совершил 2 обхода, нигде не найдя работы).

Если считать за отсутствие работы на процессе такое состояние всех имеющихся на нем ФВ, когда они отправили запросы на доставку входных ФД, а за наличие работы — когда хотя бы один ФВ получил необходимые ФД или когда уже исполняется, то ФВ, находящиеся в состоянии ожидания данных, не будут учитываться при определении наличия работы на процессе. Если же все ФВ в системе находятся в состоянии ожидания, что означает ее зависание, то система будет остановлена.

4. Сбор отладочной информации. При порождении нового ФВ для него создается уникальный Id. При подключении модуля автоматизированной отладки во время работы runtime-системы для каждого ФД сохраняется информация о соответствии его имени, Id и номера блока кода, в котором Id был создан.

Также во ФВ сохраняется так называемая история вызовов — последовательность номеров блоков, формируемая следующим образом: для ФВ, соответствующего main, история вызовов пуста; для каждого порожденного ФВ история вызовов получается из истории вызовов родительского ФВ дописыванием номера блока, который порождает новый ФВ (если его там еще нет), и номера блока, с которого начнется выполнение порожденного.

При вызове метода, отвечающего за ожидание получения ФД, сохраняется локальное имя ФД. В начале выполнения ФВ сохраняются идентификаторы входных и выходных ФД.

Информация, описанная выше, записывается в лог-файлы по достижении задаваемого параметром объема и при завершении работы системы. Позже эта информация может быть проанализирована с помощью утилиты luna_ trace. Каждый процесс независимо от других генерирует лог-файлы, и информация о ФВ и ФД сохраняется в разных файлах.

Также ведется учет ФВ на процессе: отслеживается создание, отправка другому процессу и завершение выполнения ФВ. При наличии таких ФВ на момент завершения работы процесса генерируется файл, содержащий для каждого зависшего ФВ его идентификатор и информацию о ФД, которые ФВ ожидал на момент завершения программы.

Following CFs appear to be the root cause of the system hang:

set(result[i]j vl[i] + v2[i]) [./main.fa:15] never finished (2 instances) main -> vecsim

in for i = 0..size-1 [./main.fa:12]

in sub vec_sim(name vl, name v2., int size., name result) [./main.fa:ll] in vecsim (я j y., size., sim) [ ./main.fa:25] in sub main() [./main.fa:17]

Awaited DFs v2[i] (where v2 is у, у declared in sub nain): v2[8]..v2[9] (y[8]..y[9])

Maybe it should have been initialized here: set(vec[i]j val) [./main.fa:7] in for i = 0..size-1 [./main.fa:6]

in sub vec_init(name veCj int size., int val) [./main.fa:5] in vec_init(yj size - 2., 2) [./main.fa:23] in sub main() [./main.fa:17]

Рис. 1. Информация о причине зависания

5. Обнаружение некоторых классов ошибок. К одним из наиболее часто встречающихся к.чаееов ошибок в LuXA-нрограммах относятся отсутствие инициализации ФД и множественная инициализация ФД.

После завершения LuXA-ирограммы пользователь может запустить утилиту luna_trace, передав ей лог-файлы, собранные в ходе исполнения модулем автоматизированной отладки. При анализе этих файлов luna_ trace выводит следующую информацию о зависших ФВ:

1) Выражение в коде LuXA-ирограммы, соответствующее зависшему ФВ, с указанием имени файла и номера строки для упрощения навигации.

2) Историю вызовов (сигнатуры процедур, выражения, соответствующие вызовам, некоторые другие управляющие конструкции).

3) Информацию об ожидаемых ФД с указанием выражения, соответствующего использованию ФД в коде, а также локального имени ФД и имени при объявлении.

4) Информацию о местах в коде LuXA-ирограммы, где могла быть пропущена инициализация ожидаемых ФД.

На рис. 1 приводится пример вывода дня некорректной программы, представляющей собой простой пример поэлементного сложения векторов, моделируемых индексированными ФД (ее код приведен в листинге 1).

Утилита luna_ trace объединяет информацию о ФВ, порожденных в одном цикле, а также представляет информацию об ожидаемых ФД в виде диапазона.

Также, как видно па рис. 1, утилита сумела определить выражение в тексте программы, которое соответствует инициализации элементов вектора (set(vec/il, val)). К тому же, для пего в выводе присутствует история вызовов, среди элементов которой находится строка ,,vec_init(y, size — 2, 2)“ — вызов процедуры, содержащий ошибку („size — 2й вместо «size11), приведшую к зависанию.

Реализация данной функциональной возможности основывается на следующем предположении: если не были инициализированы ФД <пате>[i\] .. <name>[iN], но существу-

Following DFs are initialized nultiple tines: x in

set(Xj 0) [./main.fa:15] setlaterfXj lj 2) [./main.fa:16]

Рис. 2. Сообщение о множественной инициализации

ют ФВ сД .. с/м, выполняющие код одного и того же блока и породившие <пате>[j\] .. <name>[jK]; то с большой долей вероятности <пате>[ц]... [iN] должен был породить ФВ, выполняющий тот же код, что и сД .. с/м- В данном случае luna_trace обнаруживает существование ФВ, породивших у/0/ .. у/7/, которым соответствует выражение set(veejil, val) в цикле процедуры vec_iin.it.

Пользователь имеет возможность специальным параметром указать — нужна ли ему информация обо всех зависших ФВ, либо только о „первопричинных“. Под первопричинами зависания будем понимать ФВ, пе имеющие информационных зависимостей от других зависших ФВ. Дня поиска первопричин строится направленный граф информационных зависимостей, вершинами которого являются пе выполненные ФВ, а ребрами — пары вида (ФВ1, ФВ2) такие что множества входных ФД дня ФВ1 и выходных ФД дня ФВ2 пересекаются. Тогда первопричинами будут ФВ, пе имеющие исходящих ребер. Если же пе удается найти пи одной такой вершины и граф содержит две или более вершины, это свидетельствует о том, что причиной зависания стана цикл зависимостей („мертвая блокировка'') [9]. luna_trace также сообщит об этом.

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

Процедура set инициализирует ФД х, своим вторым аргументом, set_ later делает то же самое, по с задержкой в секундах, передаваемой третьим аргументом.

6. Модуль централизованной динамической балансировки нагрузки. Под балансировкой нагрузки |10| понимается разделение вычислительной нагрузки между процессорами распределенной вычислительной системы с целью оптимизации использования ресурсов. Задачу балансировки можно сформулировать следующим образом: дай набор задач и набор вычислительных устройств, па которых эти задачи могут быть выполнены. Необходимо распределить задачи таким образом, чтобы время простоя вычислительных устройств было минимальным.

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

Динамическая балансировка подходит дня программ, в которых:

1) заранее неизвестно количество задач;

2) количество задач изменяется во время исполнения программы;

3) заранее неизвестен вес задач.

Существуют две основные стратегии динамической балансировки: централизованная и распределенная [11].

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

В соответствии е поставленной задачей в системе LuNA разработан модуль централизованной динамической балансировки нагрузки. При его подключении отдельный MPI-процеее ,, балансировщика “ запускается наряду с „процессами-рабочими“, занимающимися выполнением ФВ. Балансировщик распределяет ФВ между рабочими процессами.

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

Модуль балансировки нагрузки имеет 2 параметра, которые могут

быть изменены опытными программистами: JOBS_LEFT_THRESHOLD и

JOBS_DIFFERENCE_RATIO. Первый параметр определяет минимальную суммарную нагрузку на процессах (общее количество еще не выполненных ФВ), при которой необходимо включить механизм балансировки. Второй параметр определяет минимальную относительную разность нагрузки между „самым нагруженным “ и „самым свободным “ процессами и варьируется от 0 до 1. Если разность нагрузки между двумя процессами превышает данный параметр, то будет совершено перераепределение нагрузки между ними.

Общий алгоритм проверки на необходимость в перераепределении нагрузки состоит из нескольких шагов:

1. Если количество невыполненных ФВ меньше, чем JOBS_LEFT_THRESHOLD, то алгоритм заканчивает свою работу.

2. Находится наименее нагруженный процесс (нагрузка 111}. наиболее нагруженный процесс (нагрузка Н2) и относительная разность нагрузки между ними (PH = (Н2 - Н1) / Н2).

3. Если PH меньше, чем JOBS_DIFFERENCE_RATIO, то алгоритм заканчивает свою работу.

4. Балансировщик отправляет сообщение нагруженному процессу о передаче заданного количества ФВ наименее нагруженному процессу согласно плану балансировки.

5. Переход к шагу 2.

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

При появлении готового к исполнению ФВ балансировщику отправляется сообщение о номере первого блока — идентификаторе функции, е которой начинается выполнение

Группа 1

Выполненных ФВ: 4 = 3 + 1, среднее 2.5 сек = (1 + 3 + 4 ) / 4

Невыполненных ФВ 2, оценка 2.5 сек

Группа 2

Выполненных ФВ: 6 среднее 1.5 сек

Невыполненных ФВ 0

Группа 3

Выполненных ФВ: 0

Невыполненных ФВ 3,оценка

(4 *2.5 +6* 1.5)/(4 + 6) = 1.9 сек

Рис. 3. Перерасчет нагрузок

ФВ. Балансировщик группирует ФВ по поморам блоков. Таким образом, в одну группу попадают то ФВ, которые1 выполняют один и тот же код. Это характерно, например, дня циклов.

Процесс, выполнивший очередной ФВ, помимо помора блока, отправляет балансировщику время, затраченное па его выполнение. После этого происходит перерасчет нагрузок для рабочего процесса:

1) веса еще не выполненных ФВ из группы корректируются, используя экстраполяцию средним арифметическим весов выполненных ФВ из той же группы;

2) если выполненных ФВ из данной группы пет, то веса устанавливаются равными средним арифметическим весов всех выполненных ФВ па процессе.

На рис. 3 представлен пример перерасчета нагрузки. Балансировщик получает сообщение о выполненном за 2 секунды ФВ с номером блока 1. В группе 1 количество выполненных ФВ увеличивается на 1, оценка весов изменяется с 2.66 = (1 — 3 — 4) / 3 на 2.5 = (1 - 3 - 4 - 2) / 4.

При запуске программы происходит отправка нескольких сообщений разных размеров каждому из процессов дня оценки латентности и пропускной способности сети. Эта информация используется при составлении плана балансировки.

После определения двух процессов (П1 и П2), между которыми необходимо совершить перераспределение нагрузки, веса ФВ корректируются следующим образом:

XEW_ WEIGHT = WEIGHT - SIZE/SPEED - LATENCY, где:

1) WEIGHT — вес ФВ без учета пропускной способности сети;

2) SPEED — скорость передачи данных от П1 до П2;

3) SIZE — размер ФВ (суммарный объем всех его входных ФД);

4) LATENCY — латентность от П1 до П2.

Балансировщик при необходимости в выравнивании нагрузки составляет „план балап-сировки“ — решение о том, какое количество ФВ из каких групп нужно передать, для обеспечения равномерной нагрузки.

На данный момент план составляется таким образом, что ФВ с нагруженного процесса перемещаются в порядке убывания веса. Нагрузка па процессе, получающем ФВ, после балансировки не должна превышать среднюю арифметическую нагрузку по всем процессам.

7. Тестирование. Оба разработанных модуля (автоматизированной отладки и централизованной балансировки) системы LuXA были протестированы на вычислительном кластере НГУ 1121. Дня тестирования были задействованы вычислительные узлы HP

Таблица 1

Время работы программы в зависимости от количества процессов

Количество узлов Количество процессов Централизованная балансировка нагрузки

Время, сек Ускорение Эффективность

1 1 60.43 (без балансировки) 1.00 100.00

1 2 63.50 0.95 47.58

1 3 32.45 1.86 62.07

1 4 25.77 2.34 58.62

2 8 15.71 3.85 48.08

3 12 12.39 4.88 40.64

4 16 7.79 7.76 48.48

BL2x220e G7 с процессорами Intel(R) Xeon(R) Х5670 @ 2.93Ггц (12 ядер) и 24Гб оперативной памяти на каждом узле. Для модуля автоматизированной отладки актуальной задачей была оценка накладных расходов (дополнительное потребление оперативной памяти и увеличение времени работы), для централизованного балансировщика — оценка эффективности. Тестирование обоих модулей выполнялось на программе, реализующей блочный алгоритм умножения квадратных матриц.

Условия тестирования модуля автоматизированной отладки,

1) Число рабочих потоков на каждый процесс: 4

2) Число использованных узлов кластера: 3

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

3) Количество МР1-процеееов: 8,

4) Инструмент для проведения измерений — утилита jobtrace.

Среднее замедление в серии экспериментов при варьировании размера блока и их общего числа в матрице составило около 50 %. Увеличение использования памяти не превысило 37 %, а в некоторых случаях пиковое использование памяти при сборе отладочной информации оказывалось ниже. Одним из возможных объяснений данной ситуации может служить то, что из-за замедления работы системы весь набор ФВ, порождаемых в процессе работы программы, более равномерно распределяется во времени, из-за чего ФВ, выполненные раньше, оказываются удалены к моменту сбора отладочной информации для более новых ФВ,

При тестировании централизованного балансировщика нагрузки в рамках каждого рабочего процесса запускалось по одному потоку. Результаты тестирования представлены в таблице.

Как видно из таблицы, время работы программы при использовании централизованного балансировщика е ростом количества процессов значительно уменьшается, однако также растут и накладные расходы на коммуникации [13].

Малое ускорение при небольшом количестве процессов связано е тем, что в алгоритме балансировки один из процессов является выделенным, он распределяет ФВ между остальными процессами, а не выполняет их. При большем же количестве процессов растут накладные расходы на взаимодействие между узлами.

Заключение. Для языков и инструментов высокоуровневого параллельного программирования, к числу которых относится Ги.ХЛ. задачи автоматизированной отладки и балансировки нагрузки еще более актуальны, чем для стандартных инструментов распараллеливания типа MPI и ОреиМР, Причина заключается в том, что пользователь, составляя программу на таком языке, абстрагируется от механизмов реализации исполнения своей программы. Концепция высокоуровневых средств подразумевает избавление пользователя

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

На данный момент созданы модуль автоматизированного обнаружения логических ошибок в LuNA-программах и утилита luna_trace, выполняющая „посмертный анализ“. Использование данных программных средств дает возможность находить такие распространенные логические ошибки как зависания, циклические зависимости по данным между ФВ и множественную инициализацию ФД, Основными направлениями развития данного модуля будут сокращение накладных расходов и подключение других методов автоматизированной отладки.

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

Список литературы

1. Vlasenko, A., Gudov, A. The Use of Erratic Behavior Templates in Debugging Parallel Programs by the Automated Validity Verification Method // Journal of Computer and Systems Sciences International. 2017. V. 56. № 4. P. 708-720.

2. Воеводин, В. В., Воеводин, Вл. В. Параллельные вычисления // СПб: БХВ-Петербург, 2002.

3. Akhmed-Zaki, D., Lebedev, D., Malvshkin, V., Perepelkin, V. Automated Construction of High Performance Distibuted Programs in LuNA System // Malvshkin, V. (ed.) 15th International Conference, PaCT 2019, Almaty, Kazakhstan. August 19-23, 2019. P. 3-9.

4. Малышкин, В. Э. Технология фрагментированного программирования // Вестник ЮУрГУ. Серия: Вычислительная математика и информатика. 2012. Vs 46 305. С. 45-55.

5. Мустафин, Д. Э. Модуль централизованной динамической балансировки нагрузки LuNA-программ // Журнал „Инновации. Наука. Образование”. 2021. № 40. С. 365-373.

6. Protze, J., Hilbrich, Т., Schulz, М.. de Supinski, B.R. MPI Runtime Error Detection with MUST: A Scalable and Crash-Safe Approach // 43rd Intern. Conf. on Parallel Processing Workshops. Minneapolis, MN, USA. 2014. P. 206-215.

7. Мичуров M. А. Средство анализа причин зависаний фрагментированных программ в системе LuNA // Журнал „Инновации. Наука. Образование”. 2021. № 40. С. 354-364.

8. Fokkink, W. Distributed Algorithms: An Intuitive Approach // MIT Press. 2013. P. 38.

9. Иртегов, Д. В. Введение в операционные системы // Изд. 2-е. Санкт-Петербург: БХВ-Петербург. 2008.

10. Cvbenko, G., Dynamic Load Balancing for Distributed Memory Multiprocessors // J. Parallel and Distributed Comp. 1989.

11. Zaki, M. J., Li, W., Parthasarathv, S. Customized Dynamic Load Balancing for a Network of Workstations // J. Parallel and Distributed Computing. 1997. V. 43. Vs 2. P. 156-162.

12. Об ИВЦ НГУ // Информационно-вычислительный центр Новосибирского государственного университета. [Электрон, pec.]: http://nusc.nsu.ru/wiki/doku.php/doc/nusc/about (дата обращения: 13.02.2022).

13. El-Zoghdv, S. F. A Load Balancing Policy for Heterogeneous Computational Grids // International Journal of Advanced Computer Science and Applications. 2011. V. 2. № 5. P. 93-100.

Власенко Андрей

Юрьевич канд. тсхн. наук, научный сотрудник лаборатории синтеза параллельных нрох'рамм ИВМиМГ СО РАН, доцент кафедры параллельных вычислений НГУ. Научные интересы: системы поддержки параллельных вычислений, автоматизированная отладка и оптимизация параллельных программ. Автор более 30 печатных работ. E-mail: a.vlasenkoSg.nsu. ru.

Andrey Vlasenko Candidate of

Engineering Sciences, associate research at the Parallel Program Synthesis Laboratory of ICMMG SB RAS, associate professor of the Department Parallel Computing Department of Novosibirsk State University. Scientific interests: parallel computing support systems, automated debugging and optimization of parallel programs. Author of more than 30 publications. E-mail: a.vlasenkoS g.nsu.ru.

Мичуров Михаил Антонович студент 4 курса факультета информационных тех-

нологий НГУ. Научные интересы: параллельное программирование, системы поддержки параллельных вычислений. E-mail: m.michurov®

Мустафин Дамир Эркинович студент 4 курса факультета информационных технологий НГУ. Научные интересы: параллельное программирование, системы иод-

g.nsu.ru.

Mikhail Michurov

4th year student of the Information Technology Faculty of NSU. Research interests: parallel programming, parallel computing support systems. Email: m.michurov@g.nsu.ru.

держки параллельных вычислений. E-mail: d.mustafinl@g.nsu.ru.

Damir Mustafin 4th year student of the Information Technology Faculty of NSU. Research interests: parallel programming, parallel computing support systems. E-mail: d.mustafinl@g.nsu.ru.

Дата поступления 11.04.2022

i Надоели баннеры? Вы всегда можете отключить рекламу.