Мне нужно преобразовать каждый файл в определенном каталоге, а затем скомпилировать результаты в одно вычисление в системе, используя slurm. Работа над каждым отдельным файлом занимает столько же времени, сколько и остальные коллективные вычисления. Поэтому я бы хотел, чтобы отдельные обращения происходили одновременно. Последовательно, это то, что мне нужно сделать:
main.sh
#!/bin/bash
#SBATCH --account=millironx
#SBATCH --time=1-00:00:00
#SBATCH --ntasks=32
#SBATCH --cpus-per-task=4
find . -maxdepth 1 -name "*.input.txt" \
-exec ./convert-files.sh {} \;
./compile-results.sh *.output.txt
./compute.sh
echo "All Done!"
convert-files.sh
#!/bin/bash
# Simulate a time-intensive process
INPUT=${1%}
OUTPUT="${$INPUT/input.txt/output.txt}"
sleep 10
date > $OUTPUT
Пока эта система работает, я обычно обрабатываю пакеты из 30+ файлов, и время вычислений превышает ограничение по времени, установленное администратором при использовании только одного узла. Как я могу обрабатывать файлы параллельно, а затем компилировать и вычислять их после полной обработки?
Что я пробовал / считал
Добавление srun к find -exec
find . -maxdepth 1 -name "*.input.txt" \
-exec srun -n1 -N1 --exclusive ./convert-files.sh {} \;
find -exec
ожидает блокирования процессов , а srun блокирует , так что это делает то же самое, что и базовый код по времени.
Использование sbatch в скрипте отправки
find . -maxdepth 1 -name "*.input.txt" \
-exec sbatch ./convert-files.sh {} \;
Это не ожидает завершения преобразований перед началом вычислений, и, следовательно, они терпят неудачу.
Использование GNU параллельно
find . -maxdepth 1 -name "*.input.txt" | \
parallel ./convert-files.sh
OR
find . -maxdepth 1 -name "*.input.txt" | \
parallel srun -n1 -N1 --exclusive ./convert-files.sh
параллель может «видеть» только количество процессоров на текущем узле, поэтому обрабатывает только четыре файла одновременно. Лучше, но все же не то, что я ищу.
Использование массивов заданий
Этот метод звучит многообещающе , но я не могу найти способ заставить его работать, так как файлы, которые я обрабатываю, не имеют порядкового номера в своих именах.
Отправка заданий отдельно с использованием sbatch
На терминале:
$ find . -maxdepth 1 -name "*.input.txt" \
> -exec sbatch --account=millironx --time=05:00:00 --cpus-per-task=4 \
> ./convert-files.sh {} \;
Пять часов спустя:
$ srun --account=millironx --time=30:00 --cpus-per-task=4 \
> ./compile-results.sh *.output.txt & \
> sbatch --account=millironx --time=05:00:00 --cpus-per-task=4 \
> ./compute.sh
Это лучшая стратегия, которую я когда-либо придумал, но это значит, что я должен помнить, чтобы проверять ход пакетов конверсии и начинать вычисления после их завершения.
Использование sbatch с зависимостью
На терминале:
$ find . -maxdepth 1 -name "*.input.txt" \
> -exec sbatch --account=millironx --time=05:00:00 --cpus-per-task=4 \
> ./convert-files.sh {} \;
Submitted job xxxx01
Submitted job xxxx02
...
Submitted job xxxx45
$ sbatch --account=millironx --time=30:00 --cpus-per-task=4 \
> --dependency=after:xxxx45 --job-name=compile_results \
> ./compile-results.sh *.output.txt & \
> sbatch --account=millironx --time=05:00:00 --cpus-per-task=4 \
> --dependency=after:compile_results \
> ./compute.sh
Я еще не осмелился попробовать это, поскольку знаю, что последняя работа не гарантируется последней.
Кажется, это должно быть так легко сделать, но я пока не понял этого.