Запуск параллельной программы

Основные сведения

Параллельная программа - это программа, копии которой, запущенные на кластере одновременно, могут взаимодействовать друг с другом в процессе счета.

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

Для выполнения программы пользователя всегда вызывается программа MatLab.

При запуске программы пользователя на кластере в программе MatLab создаётся объект Job (работа) с описанием параллельной работы, которое включает определение объекта Task (задача), непосредственно связанного с заданной программой. Можно сказать, что копия работающей программы представлена в системе MatLab объектом Task.

Каждый объект Job получает идентификатор (ID) в системе MatLab, равный порядковому номеру. Нумерация начинается с 1.
Соответствующее имя работы вида Job1, выдаваемое при запуске, хранится в переменной окружения MDCE_JOB_LOCATION и может быть использовано в программе, а сам объект доступен пользователю во время сеанса MatLab.
Аналогично пользователь имеет доступ и к объектам Task (задача), которые также нумеруются с 1. Идентификатор или номер задачи (1,2,...) - это номер соответствующего параллельного процесса (lab) и его можно узнать с помощью функции labindex, а общее число запущенных копий с помощью функции numlabs.

Имена работы (Job1), задач (Task1, Task2,…) используются в процессе вычислений для формирования имен файлов и каталогов, связанных с заданной программой. В частности, каталог вида Job1 содержит наборы файлов с информацией по задачам. Имена этих файлов начинаются соответственно с Task1, Task2, …, например, файлы вывода имеют вид Task1.out.mat, Task2.out.mat, …

Информация о состоянии (State) работы доступна пользователю через соответствующий объект Job.

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

Система запуска создает каталог вида my_function.1 , в котором пользователю интересен, в частности, файл errors (см. Возможные ошибки).

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

Пользователь может контролировать прохождение своей программы через систему запуска как в окне системы Matlab (с версии R2011b) с помощью Job Monitor (п. меню Parallel/Monitor Jobs), так и из командной строки с помощью команд системы запуска (запросить информацию об очереди, удалить стоящую в очереди или уже выполняющуюся программу).

Действия пользователя

Войти на кластер (с помощью PuTTY или MobaXterm) и запустить программу-функцию из командной строки или в окне системы Matlab, указав необходимое для счета число параллельных процессов и максимальное время выполнения в минутах.
В ответ пользователь должен получить сообщение вида:
Job output will be written to: /home/u1303/Job1.mpiexec.out
,
где Job1 - имя сформированной работы, 1 - идентификатор работы
(/home/u1303 - домашний (личный) каталог пользователя).
Замечание. Для локализации результатов вычислений рекомендуется осуществлять запуск программы (даже в случае запуска встроенных функций Matlab ) из каталога, специально созданного для данной программы в домашнем каталоге.

Запуск параллельной программы из командной строки
Команда запуска mlrun имеет вид
    mlrun -np <number_of_procs> -maxtime <mins> <func> ['<args>']

где
<number_of_procs> - число параллельных процессов (копий программы)
<mins> - максимальное время счета в минутах
<func> - имя файла с одноименной функцией (например, my_function)
<args> - аргументы функции (не обязательный параметр) берутся в кавычки и представляются в виде
        k,{arg1,...,argn}

где    k - число выходных аргументов функции, а в фигурных скобках список ее входных аргументов.

Запуск параллельной программы в окне Matlab
В командном окне Matlab (Command Window) вызвать служебную функцию imm_sch (в ранних версиях imm_sch_f), которой в качестве параметров передать число процессов, время выполнения и предназначенную для параллельных вычислений функцию с аргументами или без, сохраняя или не сохраняя в переменной (например, job) ссылку на созданный объект Job (имя функции набирается с символом "@" или в кавычках):
    job = imm_sch(np,maxtime,@my_function,k,{arg1,...,argn});

или
    imm_sch(np,maxtime,'my_function',k,{arg1,...,argn});

Вид команд запуска mlrun и imm_sch с использованием функции rand см. в пункте Развернутый пример запуска.

Общее замечание.
При отсутствии аргументов у функции, что соответствует "0,{}", их можно опустить, например,
для файла my_function.m с одноименной функцией без параметров запуск имеет вид
из командной строки
    mlrun -np 8 -maxtime 20 my_function

в окне Matlab
    job = imm_sch(8,20,@my_function);

где 8 - число процессов, 20 - максимальное время счета в минутах.

Доступ к объекту Job (работа)
Все работы хранятся на кластере. При необходимости доступа к работе, на которую в текущий момент отсутствует ссылка, можно (1) в окне Job Monitor правой кнопкой мыши выделить нужную работу и выбрать соответствующую опцию в контекстном меню (Assign Job to Workspace в версии R2012a, по умолчанию рабочей) или (2) по идентификатору (ID) определить ссылку на работу (обозначаемую job) с помощью, например, команд:
    c = parallel.cluster.Generic
    job = c.findJob('ID',1)

Примечание.
Вышеприведенные команды предназначены для версий MatLab с профилем кластера, т.е. начиная с R2012a.
В ранних версиях (с конфигурацией кластера) следует набирать:
    s = findResource('scheduler', 'type', 'generic')
    job = findJob(s,'ID',1)

При этом в поле DataLocation структуры s должен быть текущий каталог (тот, в котором ищем работу). Если каталог другой, то можно выполнить
    clear all
    и повторить предыдущие команды.

Состояние работы
Состояние работы можно посмотреть в поле State работы job, набрав
    job    
или    job.State
или узнать с помощью Job Monitor.
Основные значения состояния работы следующие:
    pending      (ждет постановки в очередь)
    queued       (стоит в очереди)
    running      (выполняется)
    finished     (закончилась)

Окончания счета (состояние finished) можно ждать с помощью функции wait
    wait(job);    
или    job.wait()

Вывод результатов

В окне Matlab (с R2012a) для работы job и любой ее задачи (Task) с номером n=1,2,... можно выдать (далее для удобства n=1)
1) протокол сеанса:
    job.Tasks(1).Diary

2) информацию об ошибках (поле ErrorMessage)
    job.Tasks(1)    
или    job.Tasks(1).ErrorMessage
3) результаты (значения выходных параметров) работы job в целом (по всем Task-ам):
    out = job.fetchOutputs

Тогда значение 1-го выходного параметра 1-ой задачи (Task)
    res = out{1,1}

или, если он единственный, то он опускается,
    res = out{1}

соответственно, значение 2-го выходного параметра 1-ой задачи (Task)
    res2 = out{1,2}

Другой способ выдачи результатов по задачам
    out1 = job.Tasks(1).OutputArguments

Замечания.
1. Эту же информацию можно выдать, запустив Matlab в интерактивном текстовом режиме (matlab -nodisplay) и набирая затем упомянутые команды.
2. Если ссылка на работу (job) отсутствует, то ее можно найти по идентификатору.
3. Для ранних версий (до R2012a) следует использовать следующие команды, чтобы выдать
   1) протокол сеанса:
    job.Tasks(1).CommandWindowOutput

   3) результаты (значения выходных параметров) работы job в целом (по всем Task-ам):
    out = job.getAllOutputArguments

Вывод из файлов
По завершении параллельной работы в файлы вывода TaskN.out.mat ее задач (номер задачи N=1,2,…np; np - число задач данной работы) попадают
- выходные параметры функции пользователя (массив ячеек argsout),
- содержимое stdout (переменная commandwindowoutput) и
- содержимое stderr (переменная errormessage).

Выдать эту информацию можно из командной строки или в окне системы Matlab.

Приведем примеры соответствующих команд для Task1 работы с именем Job1.
Предполагаем, что команды выполняются в каталоге, из которого была запущена программа.
Вывод из командной строки
первого выходного параметра:
    echo 'load Job1/Task1.out.mat; argsout{1}, exit' | matlab -nodisplay

содержимого stdout:
    echo 'load Job1/Task1.out.mat; commandwindowoutput, exit' | matlab -nodisplay

содержимого stderr (ошибок трансляции):
    echo 'load Job1/Task1.out.mat; errormessage, exit' | matlab -nodisplay

Вывод в окне системы Matlab
После вызова, например,
    matlab &

набрать команду
    load Job1/Task1.out.mat

и выдать
первый выходной параметр:
    argsout{1}

содержимое stdout:
    commandwindowoutput

содержимое stderr (ошибки трансляции):
    errormessage

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

Перед просмотром файла вывода следующей задачи, т.е. перед загрузкой в Matlab, например, файла Job1/Task2.out.mat, рекомендуется очищать окно Workspace командой
    clear


Развернутый пример запуска

В качестве примера запуска программы на кластере используем функцию rand, вызываемую для генерации 2х3 матрицы случайных чисел
(традиционный вызов функции: y = rand(2,3)).
Для получения 4 экземпляров матрицы задаем число процессов, равное 4. Максимальное время счета пусть будет равно 5 минутам.

Запускать функцию будем на кластере "Уран" (umt) (см. Вычислительные ресурсы), для удобства в каталоге test, специально созданном заранее в домашнем каталоге пользователя /home/u9999, где u9999 – login пользователя (см. Схема работы на кластере и Базовые команды ОС UNIX).

Для запуска функции rand из командной строки используется команда mlrun,
а из системы Matlab - служебная функция imm_sch (см. Параллельный Matlab/Общая информация).

Войдя на umt через PuTTY, для запуска rand можно
1) выполнить команду
    mlrun -np 4 -maxtime 5 rand '1,{2,3}'

или
2) вызвать Matlab в интерактивном текстовом режиме командой
    matlab -nodisplay

и в ответ на приглашение (>>) набрать
    job = imm_sch(4,5,@rand,1,{2,3});

где job – ссылка на сформированную работу.
Для выхода из Matlab следует набрать
    exit
   или   quit

Для запуска программ из окна Matlab пусть установлен MobаXterm.
Тогда войдя на umt из MobаXterm, можно вызвать Matlab командой
    matlab &

и в открывшемся окне набрать
    job = imm_sch(4,5,@rand,1,{2,3});

После выполнения команды mlrun или служебной функции imm_sch выдается строка вида
Job output will be written to: /home/u9999/test/Job1.mpiexec.out

где Job1 - имя сформированной работы, 1 - идентификатор (номер) работы.

Если ресурсов кластера достаточно, задача войдет в решение. (см. Запуск задач на кластере в системе SLURM)

Дожидаемся окончания задачи, т.е. job.State должно быть finished.
В окне Matlab контролировать состояние задачи можно и с помощью Job Monitor (п. меню Parallel/Monitor Jobs).

Результаты выдаем с помощью команд:
со всех процессов
    out = job.fetchOutputs

а для выдачи матрицы, полученной 1-ым процессом (т.е. Task1)
    out{1}

и т.д.

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

Некоторые рекомендации

1. Начать работу на кластере рекомендуется с запуска своей последовательной программы в тестовом однопроцессном варианте, например,
    mlrun -np 1 -maxtime 20 my_function

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