Параллельные вычисления в ИММ УрО РАН
 
 

НАДЕЖНЫЕ ТОЧКИ СОХРАНЕНИЯ ДАННЫХ

С.В.Попова, С.В.Шарф

Интитут математики и механики УрО РАН, Екатеринбург

 posvet@imm.uran.ru

Работа выполнялась при частичной поддержке гранта РФФИ 01-07-90215.

Введение

Вычислительные задачи длительного счета обычно содержат контрольные точки, в которых производится сохранение промежуточных данных. Такие точки сохранения данных (ТСД) позволяют использовать результаты предыдущего запуска, который был прерван по той или иной причине — ошибке в программе, завершения счета системой запуска по истечении времени, сбоя в работе аппаратуры или базового ПО. Можно сказать, что ТСД уменьшают потери времени, связанные с ликвидацией последствий сбоя, т. е. повышают надежность программы.

Ясно, что нужно подумать и о защите от сбоя в момент записи промежуточных результатов. В статье с позиции применимости на кластерных ЭВМ типа МВС-1000 [1] рассматриваются некоторые способы и приемы программирования, обеспечивающие более надежную организацию ТСД. Полагаем, что наша работа может быть интересна тем прикладным программистам, кто в той или иной мере задумывался над часто выдвигаемым требованием "программа всегда должна завершаться корректно".

Широко используемые приемы и их ограничения

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

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

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

К сожалению, на МВС-1000, где файлы хранятся в сетевой файловой системе nfs, даже помещение изменения номера итерации после собственно записи данных не гарантирует отсутствия такой ситуации, когда номер итерации изменен, а данные записаны не полностью. Надо обращаться к функции fsync(), а также проверять коды ответа, как у процедур записи, так и у процедуры закрытия файла. Последнее не делается почти никогда, хотя настоятельно рекомендуется почти во всех руководствах.

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

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

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

Все изложенное наталкивает на мысль о необходимости программной поддержки  создания ТСД.

Организация ТСД независимо от пользователя требует сохранения всего состояния программы. Для МВС-1000 программа на этапе счета — это совокупность одновременно исполняемых на разных процессорах процессов, которые взаимодействуют друг с другом через сетевые устройства и используют файловую систему. Проблематично даже сохранение оперативной памяти всех процессоров, не говоря уже о том, что восстановить состояние параллельной программы просто невозможно без поддержки на уровне хотя бы базовых библиотек работы с сетью и файловой системой. Такая поддержка, например, на уровне MPI приводит, по крайней мере, к двукратному замедлению всех взаимодействий [2]. На настоящий момент отсутствует и в достаточной степени эффективная журналируемая файловая система с поддержкой транзакций.

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

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

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

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

Краткое описание библиотеки

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

Все подпрограммы библиотеки реализованы на языке Си для систем передач сообщений ROUTER [1]  и MPI, могут использоваться для программ, написанных на Си и на Фортране.

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

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

Приведем схематичный пример одного из вариантов организации работы. (Одна и та же программа задает все процессы задачи.) Предполагается, что в программе  используется 3 файла данных для чтения и записи fl, f2, f3, имена которых прикладной программист указал в информационном файле.

int iInitDF (nproc); /* инициализирует режим защиты данных */

                                   /*nproc - логический номер процессора, на котором будет

происходить сохранение*/

int iRestoreDF();     /* проверяет целостность и при необходимости восстанавливает  предыдущее состояние совокупности файлов с данными */

<открытие, чтение и закрытие файлов f1, f2, f3 >

<начало цикла>

iHideDF();  /*переносит  все указанные файлы во вспомогательный каталог */

   <СЧЕТ>

   <открытие, запись и закрытие файлов f1, f2, f3 >

< конец цикла>

iEOWDF ();  /* завершает работу подпрограмм защиты от сбоев */

Для часто используемой организации взаимодействия процессов типа фермы nproc — это логический номер процесса-мастера (обычно 0).

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

Заключение

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

Первая версия библиотеки передана в опытную эксплуатацию в ИММ УрО РАН, и сейчас разрабатывается новая версия комплекса подпрограмм. В ней предусмотрена возможность промежуточного сохранения файлов на локальных дисках узла МВС. Предполагается также реализовать копирование данных в том случае, если файл открыт и не очень большой. При необходимости сохранения «больших» файлов,  возможно, будет полезным сжатие информации. Предполагается дать возможность программисту указывать файлы, требующие сжатия при сохранении. Надеемся, что после завершения работ новая версия будет внедрена в ИММ УрО РАН и Межведомственном суперкомпьютерном центре (г. Москва).

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

1. Лацис А.О. Как построить и использовать суперкомпьютер. М.: изд-во Бестселлер, 2003. 274 с.
2. George Bosilca, Aure'lien Bouteiller, Franck Cappello et al. MPICH-V: Toward a Scalable Fault Tolerant MPI for Volatile Nodes // SuperComputing 2002, Baltimore USA, November 2002
.