• A
  • A
  • A
  • АБВ
  • АБВ
  • АБВ
  • А
  • А
  • А
  • А
  • А
Обычная версия сайта

Запуск задач на вычислительном кластере НИУ ВШЭ

👉Вернуться к списку инструкций

Основные правила выполнения расчетов на суперкомпьютере

  • На “логин-сервере” (головной сервер, sms) можно выполнять лишь такие запуски, которые не требует значимых вычислительных ресурсов: компиляция, сборка, тесты запуска и т.п.
  • Все вычислительные задачи должны выполняться только на вычислительных узлах.
  • Все задачи пользователей выполняются через систему управления заданиями Slurm.

Как выполнять расчеты на суперкомпьютере?

При подключении к суперкомпьютеру НИУ ВШЭ вы подключаетесь к “логин-серверу”, а не к вычислительным узлам.
Логин-сервер является общим ресурсом, на который имеют доступ все пользователи. С данного сервера пользователи запускают задачи, просматривают статус очереди, управляют своими файлами. На данном сервере разрешены лишь такие запуски, которые не требуют значимых вычислительных ресурсов: компиляция, сборка, тесты запуска и т.п.
Для непосредственного выполнения расчетов необходимо использовать систему управления заданиями Slurm через скрипты и команды, описанные далее. Они сообщают суперкомпьютеру где выполнить задачу, какие ресурсы ей нужны и как долго она будет выполняться. Slurm автоматически запустит задачу на подходящих узлах или поставит её в очередь, если запрошенные ресурсы сейчас недоступны.

Определить, корректно ли работает ваша задача, Вы можете чрез систему HPC TaskMaster, разработанную Отделом суперкомпьютерного моделирования НИУ ВШЭ [1]. Убедитесь, что все выделенные задаче ядра процессора и GPU загружены полностью. Если ресурсы не заняты, ищите ошибку в программе. Если вы используете готовые программы, прочитайте в документации, сколько ядер и GPU они могут использовать. Не нужно выделять лишние ресурсы, если программа их не поддерживает.

Базовые команды, необходимые для работы с очередью задач

sbatch - позволяет запустить задачу в "пакетном" режиме (с возможностью полной подготовки окружения и т.п.), приоритетный способ.
srun - позволяет выполнить задачу в интерактивном режиме, обычно используется для отладки.
squeue - отобразить все задачи в очереди.
mj - отобразить состояние только своих задач.
mj --exp - отобразить ориентировочное время запуска своих ожидающих задач.
scancel <job_id> - прекратить выполнение своей задачи с указанным id.

Создание задачи

Задача состоит из двух частей: запрос ресурсов и шагов выполнения. В запросе ресурсов указывается необходимое количество процессорных ядер и графических ускорителей, ожидаемое время выполнения, объём памяти и дискового пространства и т.д. Шаги выполнения описывают задачи (tasks) и программы, которые необходимо выполнить.
Задачи могут быть запущены в “пакетном” режиме (sbatch) с возможностью подготовки окружения и загрузки необходимых модулей, а также в “интерактивном” режиме (srun), с выводом результатов расчётов на экран.
Задачи в очереди запускаются на расчет согласно приоритетам. В некоторых случаях, даже при наличии свободных ресурсов, задача не сможет их занять, если есть более приоритетная задача, которая ждет дополнительных ядер. Одним из способов повысить приоритет своей задачи является уменьшение максимально возможного времени её выполнения при помощи опции --time.

Хранение расчетов

Для удобного хранения расчетов и их результатов рекомендуется разделить их по категориям, с помощью чего данный расчет будет выполняться, например: python, MATLAB и т. д. Далее, в соответствующей директории создать поддиректорию под конкретную задачу, например my_numpy_task в директории python. В my_numpy_task, соответственно, расположить my_numpy_task.py скрипт и my_numpy_task.sbatch файл для запуска расчета с помощью программы sbatch. При выполнении sbatch my_numpy_task.sbatch из этой же директории результаты расчетов также окажутся в ней.

Запуск задачи в пакетном режиме с помощью sbatch

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

 Для создания скрипт-файла можно использовать специальный генератор пакетных файлов, разработанный в ОСМ для суперкомпьютера cHARISMa: https://lk.hpc.hse.ru/sbatch/

Общий синтаксис запуска следующий: sbatch [опции] script_name.sbatch  или sbatch [опции] --wrap="команда запуска"

В качестве <script_name> должен выступать скрипт-файл, в котором описываются требуемые ресурсы и шаги выполнения задачи. Общий синтаксис скрипта для передачи в sbatch выглядит следующим образом:

#!/bin/bash
#SBATCH <ключ sbatch> <значение>
...
#SBATCH <ключ sbatch> <значение>
<пользовательские команды> ... <пользовательские команды>

Опции для sbatch могут быть переданы как в командной строке при вызове команды, так и в самом скрипте (#SBATCH ...).

Шаблон скрипт-файла для sbatch, рекомендуемый для использования:

#!/bin/bash
#SBATCH --job-name={task}            # Название задачи
#SBATCH --error={task}-%j.err        # Файл для вывода ошибок
#SBATCH --output={task}-%j.log       # Файл для вывода результатов
#SBATCH --time={12:00:00}            # Максимальное время выполнения
#SBATCH --ntasks={16}                # Количество MPI процессов
#SBATCH --nodes={1}                  # Требуемое кол-во узлов
#SBATCH --gpus={4}                   # Требуемое кол-во GPU
#SBATCH --cpus-per-task={2}          # Требуемое кол-во CPU

module load {modules}                # Загрузка модуля
{command}                            # Выполнение расчёта
#srun {options} {command} # Выполнение MPI расчёта

Не забывайте менять параметры, указанные в {фигурных скобках} на свои.

Например, для запуска python-расчета на 4 CPU и 2 GPU, требующего подготовки окружения, необходимо написать следующий скрипт:
#!/bin/bash
#SBATCH --job-name=my_numpy_task            # Название задачи 
#SBATCH --error=my_numpy_task-%j.err        # Файл для вывода ошибок 
#SBATCH --output=my_numpy_task-%j.log       # Файл для вывода результатов 
#SBATCH --time=1:00:00                      # Максимальное время выполнения 
#SBATCH --cpus-per-task=4                   # Количество CPU на одну задачу
#SBATCH --nodes=1 # Требуемое кол-во узлов #SBATCH --gpus=2 # Требуемое кол-во GPU module load Python/Anaconda_v11.2021 # Загрузка модуля Anaconda python my_numpy_task.py # Выполнение расчёта

Результат работы программы будет выведен в файл result.out.

Если для выполнения задачи не требуется каких-то подготовительных действий, скрипт можно не писать, а выполняемую команду "обернуть" через опцию "--wrap", например:

sbatch -n 1 -c 2 --wrap="/home/testuser/my_program arg1 arg2"

Подробнее см. в дополнительной инструкции: Примеры запуска задач через очередь заданий Slurm.

Запуск задач в режиме массива

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

#!/bin/bash
#SBATCH --job-name=my_array_task            # Название задачи 
#SBATCH --error=my_array_task-%A-%a.err     # Файл для вывода ошибок 
#SBATCH --output=my_numpy_task-%A-%a.log    # Файл для вывода результатов 
#SBATCH --array=1-20                        # Массив подзадач с номерами от 1 до 20

module load Python/Anaconda_v11.2021        # Загрузка модуля Anaconda
idx=$SLURM_ARRAY_TASK_ID # В переменную idx записывается номер текущей подзадачи
echo "I am array job number" $idx # Отображение ID подзадачи python my_array_task.py -i input_$idx.dat # Выполнение расчёта с входным файлом input_$idx.dat

В данном примере будет создана одна мастер-задача и массив из 20 подзадач. В переменную $SLURM_ARRAY_TASK_ID будет записан номер подзадачи. В дальнейшем эту переменную можно удобно использовать при указании входного файла.
Вывод каждой подзадачи будет записан в отдельный файл my_numpy_task-%A-%a.log, где %A - ID мастер задачи, %a - ID подзадачи.
Подробное руководство по использованию массивов задач доступо на официальном сайте SLURM.

Запуск задачи в интерактивном режиме с помощью srun

srun, в отличие от sbatch, выполняет задачу интерактивно - т.е. можно перенаправить ввод и вывод или напрямую взаимодействовать с программой через консоль.
Принцип выделения аналогичный, за тем исключением, что в очередь ставится задача на выделение ресурсов, а не сам расчет. А уже после выделения ресурсов начинается интерактивное выполнение программы.
Важной особенность srun является возможность автоматического управления пуллом MPI-процессов. Например, для запуска MPI-программы на 20 потоках в интерактивном режиме можно выполнить команду srun -n 20 ./my_mpi_task
* srun может быть выполнен внутри sbatch (может быть полезно для MPI задач).

Выбор проекта для выполнения задачи

Пользователи, которые являются участниками нескольких активных проектов, должны принудительно указывать проект, в рамках которого будет выполнена задача. Для этого необходимо указать параметр --account <ID_проекта> или -A <ID_проекта> в sbatch-скрипте или в любой из команд запуска задачи (sbatch/srun).
Например, можно добавить параметр при выполнении sbatch -A proj_1 train.sbatch или указать его прямо в sbatch-скрипте:

#!/bin/bash
#SBATCH --job-name=my_task                  # Название задачи 
#SBATCH --account=proj_1 # Идентификатор проекта #SBATCH --time=1:00:00 # Максимальное время выполнения
#SBATCH --cpus-per-task=4 # Количество CPU на одну задачу
#SBATCH --nodes=1 # Требуемое кол-во узлов #SBATCH --gpus=2 # Требуемое кол-во GPU module load Python/Anaconda_v11.2021 # Загрузка модуля Anaconda python train.py # Выполнение расчёта

ID проектов, в которых состоит пользователь, можно посмотреть в консоли суперкомпьютера с помощью команды mp 

Автоматический перезапуск задач

Планировщик заданий Slurm поддерживает автоматический перезапуск задач. Данная функция полезна при использовании ПО, которое использует механизм контрольных точек во время расчёта, например, GROMACS. Перезапуск задачи будет произведён автоматически в случае сбоя узла или после проведения профилактики (см. раздел О профилактических работах). Для отключения возможности перезапуска при постановке задачи в очередь добавьте опцию --no-requeue:

sbatch --job-name=myjob --time=5-0:0 --no-requeue --wrap="/home/testuser/simple_program"

Приоритет задач

Очередь заданий на суперкомпьютере строится на основе приоритетов – чем выше приоритет задачи, тем ближе она к началу очереди. Задача, стоящая в самом начале очереди, резервирует для себя требуемые системные ресурсы по мере их освобождения. То есть, даже если есть свободные вычислительные узлы, их нельзя занять, если есть более приоритетная задача, которая ждёт дополнительных ресурсов.
Из этого правила есть исключение – если выполнение задачи X с меньшим приоритетом не повлияет на время запуска задачи Y с большим приоритетом, то задача X может быть запущена перед Y. Такой метод планирования поддерживается благодаря плагину backfill scheduling. Одним из способов повысить приоритет своей задачи является уменьшение максимально возможного времени её выполнения с помощью опций --time и --deadline.

Как узнать плановую дату запуска задачи, находящейся в очереди?

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

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

Ориентировочную дату и время запуска задач в очереди можно посмотреть командой: squeue --start

Выбор типа вычислительного узла 

В суперкомпьютере НИУ ВШЭ используется пять типов вычислительных узлов (type_a, type_b, type_c, type_d, type_e). По умолчанию, задачи запускаются на любом свободном узле в соответствии с приоритетом: d -> a -> c -> b -> e. Выбираются только удовлетворяющие запрошенным ресурсам узлы (например, тип d не будет рассматриваться в случае запроса GPU).
Для принудительного выбора типа узлов, на котором должна быть запущена задача, необходимо использовать опцию --constraint=<тип_узла> или -C <тип_узла>. В параметре доступна возможность использования дизъюнкции (логическое ИЛИ): --constraint="type_c|type_d" (кавычки обязательны) - в этом случае для задачи может быть выделены как узлы type_c, так и узлы type_d.

В случае, когда необходимо, чтобы все выделяемые узлы были идентичны по типу, но при этом сам тип может варьироваться, тогда перечисление типов указывается в квадратных скобках: --constraint="[type_a|type_b]" - в этом случае все выделенные узлы будут либо type_a, либо все type_b.

Список типов вычислительных узлов доступен по команде nodetypes.

Оповещение об изменении состояния задачи на e-mail 

Для получения сообщений об изменении состояния задач на e-mail добавьте к команде sbatch параметры --mail-type и --mail-user.
Формат параметров: --mail-user=example@hse.ru --mail-type=ALL

Где вместо ALL могут быть различные типы событий (см. https://slurm.schedmd.com/sbatch.html).

Основные опции sbatch, srun

-n <число>  (он же --ntasks=<число>) - число запускаемых процессов;
-c <число>  (он же --cpus-per-task=<число>) - количество CPU-ядер на каждый процесс;
-G <число> (он же --gpus=<число>) - количество GPU;
-N <число> (он же --nodes=<число>) - минимальное количество узлов, выделяемых для задачи;
--ntasks-per-node=<число> - количество процессов на каждый узел (например, "-n 4 --ntasks-per-node=2" — значит, нужно 2 узла для выполнения этих 4 процессов);
--gpus-per-task=<число> - количество GPU на каждый запускаемый процесс;
--gpus-per-node=<число> - количество GPU на каждый выделяемый узел;
--cpus-per-gpu=<число> - количество CPU на каждую выделяемую GPU;

Дополнительная информация

sbatch -N 2 -G 8 – запустить задачу на 2 узлах и 8 GPU (на каждом узле 4 GPU - невозможно выделить больше 8 GPU для 2 узлов).
sbatch -N 2 -G 4 --gpus-per-node=2 – запустить задачу на 2 узлах и 4 GPU, задействуя по 2 GPU на каждом узле.
sbatch -N 2 --gpus-per-node=4 – запустить задачу на 2 узлах, задействуя все 4 GPU на каждом узле.
sbatch -n 4 --gpus-per-task=1 – запустить задачу с 4 процессами, на каждый из которых выделяется по 1 GPU (всего 4 GPU).
sbatch -N 4 --ntasks-per-node=2 --gpus-per-task=2 – запустить задачу на 4 узлах, по 2 процесса на каждом узле, каждый из которых задействует 2 GPU (всего 16 GPU).
sbatch -G 4 --cpus-per-gpu=1 – запустить задачу с использованием 4 GPU и 4 CPU (по 1 CPU на каждый выделенный GPU)

--time=<число> - необходимое время выполнения задачи (в минутах), может быть задано форматами:
[минуты | минуты:секунды | часы:минуты:секунды | дни-часы | дни-часы:минуты | дни-часы:минуты:секунды]
По умолчанию, максимальное время выполнения задачи ограничено 24 часами. Если задача требудет больше времени, то необходимо в скрипт-файле использовать параметр --time
--partition=<название очереди>: очередь, в которую будет поставлена задача (по умолчанию “normal”);
--job-name=<название задачи>: название задачи в очереди;
--deadline=<время выполнения>: ограничение по времени выполнения, после которого задача будет принудительно завершена;
--output=<название файла>: файл, куда будет записываться вывод в процессе выполнения задачи;
--wrap=<строка запуска>: строка запуска задачи.



 * Подробная информация по использованию планировщика Slurm доступна на официальном сайте.

Примеры скрипт-файлов sbatch

1. Запуск простой задачи с помощью sbatch с подготовкой скрипт-файла: sbatch myscript.sh Где содержимое myscript.sh это:

#!/bin/bash
#SBATCH --job-name=myjob                # Название задачи в очереди
#SBATCH --time=5-0:0                         # Максимальное время выполнения (5 дней)
#SBATCH --output=myjob.slurm.log     # Вывод результата в myjob.slurm.log
#SBATCH --cpus-per-task=8                # Выполнение расчёта на 8 ядрах CPU
#SBATCH --nodes=1                            # Все выделенные ядра должны быть на 1 узле

/home/testuser/simple_program           # Запуск ПО

2. Запуск простой задачи с помощью sbatch с указанием запрашиваемых ресурсов (эквивалент предыдущему):

sbatch --partition=normal --job-name=myjob --time=5-0:0 --output=myjob.%j.log --wrap="/home/testuser/simple_program"

3. Запуск консоли bash с доступом к 1 GPU и 4 CPU:

srun --pty --ntasks 4 --gpus=1 bash

4. Запуск задачи на 8 ядрах на одном узле:

sbatch --cpus-per-task=8 one_node_program

5. Запуск MPI-задачи на 2 узлах на 24 ядрах с лимитом в 1 час (myscript.sh):

#!/bin/bash
#SBATCH --job-name=mpi_job_test     # Название задачи в очереди
#SBATCH --ntasks=24                          # Кол-во MPI процессов (MPI рангов)
#SBATCH --cpus-per-task=1                # Кол-во ядер на каждый процесс
#SBATCH --nodes=2                            # Кол-во узлов для задачи

#SBATCH --ntasks-per-node=12         # Кол-во процессов на каждом узле
#SBATCH --time=00:05:00                  # Ограничение времени выполнения задачи (дни-часы:мин:сек)
#SBATCH --output=mpi_test_%j.log   # Путь до выходного файла относительно рабочего каталога

echo "Date = $(date)"
echo "Hostname = $(hostname -s)"
echo "Working Directory = $(pwd)"
echo ""
echo "Number of Nodes Allocated = $SLURM_JOB_NUM_NODES"
echo "Number of Tasks Allocated = $SLURM_NTASKS"
echo "Number of Cores/Task Allocated = $SLURM_CPUS_PER_TASK"

# Загрузка необходимых переменных окружения
module load INTEL/parallel_studio_xe_2020_ce

srun /home/testuser/mpi_program

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

#!/bin/bash
#SBATCH --ntasks=24             # Кол-во MPI процессов
#SBATCH --cpus-per-task=1   # Кол-во ядер на каждый процесс
module purge                          # Очистка переменных окружения

# Загрузка необходимых переменных окружения
module load INTEL/parallel_studio_xe_2020_ce

# Последовательный запуск задач
srun ./a.out > task1_output 2>&1
srun ./b.out > task2_output 2>&1
srun ./c.out > task3_output 2>&1

7. Одновременное выполнение нескольких параллельных задач. Обратите внимание на команду «wait» в конце скрипта. Она позволяет планировщику ожидать завершения всех задач.

#!/bin/bash
#SBATCH --ntasks 56                 # Кол-во MPI процессов
#SBATCH --cpus-per-task=1      # Кол-во ядер на каждый процесс
module purge                             # Очистка переменных окружения

# Загрузка необходимых переменных окружения
module load INTEL/parallel_studio_xe_2020_ce

# Одновременный запуск задач
srun -n 8 --cpu_bind=cores ./a.out > a.output 2>&1 &
srun -n 38 --cpu_bind=cores ./b.out > b.output 2>&1 &
srun -n 10 --cpu_bind=cores ./c.out > c.output 2>&1 &

# Ожидание завершения всех процессов
wait

8. Запуск обучения нейронной сети на 4 GPU и 16 CPU:

#!/bin/bash
#SBATCH --job-name=net_training
#SBATCH --error=stderr.%j.txt
#SBATCH --output=stdout.%j.txt
#SBATCH --partition=normal
#SBATCH --gpus=4
#SBATCH --cpus-per-task 16

module load Python/Anaconda_v10.2019

# Активация окружения Anaconda
# Перед активацией окружения рекомендуется деактивировать текущее
source deactivate
source activate pytorch

echo "Working on node `hostname`"
echo "Assigned GPUs: $CUDA_VISIBLE_DEVICES"
cd /home/testuser/pytorch
export NGPUS=4
python -m torch.distributed.launch --nproc_per_node=$NGPUS /home/testuser/pytorch/train_net.py --config-file "configs/network_X_101_32x8d_FPN_1x.yaml"

Примечание для расчетов на python с выводом в терминал

Важное примечание для расчетов на python, результаты которых отображаются в выводе!
По умолчанию python использует буфферизованный вывод (т.е. вывод НЕ мгновенно передается в результирующий файл).
Например, в случае такого кода:

from time import sleep
print ('Start')
for i in range(60):
    sleep(1)
print ('Done')

Начальный вывод "Start" появится в файле вывода (slurm-.out) только спустя 60 итераций (одновременно с "Done").
Для задач, результаты которых оцениваются в процессе выполнения (выводятся промежуточные значения и тп), это не подходит (например, в случае, когда задача завершится по таймауту, вывода в файле не будет).
Для мгновенного отображения результатов предлагается 2 варианта:
1. Добавлять аргумент flush=True в функцию print: "print ('Start', flush=True)" (это работает только при версии python >= v3.3)
2. Добавить аргумент -u при запуске задачи к самому интерпретатору: например, "python3 -u myprog.py" (изменения в кода в данном случае не понадобится)

Запуск прикладного ПО

Для запуска прикладного ПО (Gromacs, Octave, BEAST, IQ-Tree, MATLAB и т.д.) ознакомьтесь с примерами их использования в разделе Прикладное программное обеспечение суперкомпьютера НИУ ВШЭ.


 

Нашли опечатку?
Выделите её, нажмите Ctrl+Enter и отправьте нам уведомление. Спасибо за участие!
Сервис предназначен только для отправки сообщений об орфографических и пунктуационных ошибках.