У меня проблема с изящным выходом из моих заданий slurm с сохранением данных и т.д.
В моей программе есть обработчик сигнала, который устанавливает флаг, который затем запрашивается в основном цикле, после чего следует изящный выход с сохранением данных. Общая схема примерно такая:
#include <utility>
#include <atomic>
#include <fstream>
#include <unistd.h>
namespace {
std::atomic<bool> sigint_received = false;
}
void sigint_handler(int) {
sigint_received = true;
}
int main() {
std::signal(SIGTERM, sigint_handler);
while(true) {
usleep(10); // There are around 100 iterations per second
if (sigint_received)
break;
}
std::ofstream out("result.dat");
if (!out)
return 1;
out << "Here I save the data";
return 0;
}
К сожалению, пакетные сценарии сложны, потому что:
- Мне нужны сотни параллельных независимых задач с малым количеством потоков, но мой кластер допускает только 16 задач на пользователя
-
srun
в моем кластере всегда требует целый узел, даже если мне не нужны все ядра, поэтому для запуска нескольких процессов на одном узле я должен использоватьbash
Из-за этого в пакетном скрипте такая каша (2 узла на 4 процесса):
#!/bin/bash -l
#SBATCH -N 2
#SBATCH more slurm stuff, such as --time, etc.
srun -N 1 -n 1 bash -c '
./my_program input1 &
./my_program input2 &
wait
' &
srun -N 1 -n 1 bash -c '
./my_program input3 &
./my_program input4 &
wait
' &
wait
Теперь, чтобы распространять сигналы, отправленные slurm, у меня есть еще большая путаница, подобная этой (после этого ответа, в частности двойных ожиданий):
#!/bin/bash -l
#SBATCH -N 2
#SBATCH more slurm stuff, such as --time, etc.
trap 'kill $(jobs -p) && wait' TERM
srun -N 1 -n 1 bash -c '
trap '"'"'kill $(jobs -p) && wait'"'"' TERM
./my_program input1 &
./my_program input2 &
wait
' &
srun -N 1 -n 1 bash -c '
trap '"'"'kill $(jobs -p) && wait'"'"' TERM
./my_program input3 &
./my_program input4 &
wait
' &
wait
По большей части это работает. Но, во-первых, я получаю сообщения об ошибках в конце вывода:
run: error: nid00682: task 0: Exited with exit code 143
srun: Terminating job step 732774.7
srun: error: nid00541: task 0: Exited with exit code 143
srun: Terminating job step 732774.4
...
и, что еще хуже, примерно 4-6 из более чем 300 процессов на самом деле терпят неудачу на if (!out)
- errno
выдает "Прерванный системный вызов". Опять же, руководствуясь этим, я предполагаю, что мой обработчик сигнала вызывается два раза - второй во время какого-то системного вызова в конструкторе std::ofstream
.
Сейчас,
- Как избавиться от ошибок slurm и обеспечить корректный выход?
- Правильно ли я понимаю, что сигнал отправляется два раза? Если да, то почему и как это исправить?
Сохраняет ли
srun
переменные среды?@KamilCul Думаю, да, это сработало с OMP_NUM_THREADS