并行处理文件组,然后使用 slurm 进行串行计算

Process group of files in parallel then compute in series using slurm

我需要转换特定目录中的每个文件,然后使用 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!"

转换-files.sh

#!/bin/bash
# Simulate a time-intensive process
INPUT=${1%}
OUTPUT="${$INPUT/input.txt/output.txt}"
sleep 10
date > $OUTPUT

虽然这个系统能用,但我一般是批量处理30+个文件,而且只用一个节点,计算时间超过了管理员设置的时间限制。 如何并行处理文件,然后在它们全部处理完后对其进行编译和计算?

我有什么tried/considered

将 srun 添加到 find -exec

find . -maxdepth 1 -name "*.input.txt" \
  -exec srun -n1 -N1 --exclusive ./convert-files.sh {} \;

find -exec waits for blocking processes, and ,所以这在时间上与基本代码完全相同。

在提交脚本中使用sbatch

find . -maxdepth 1 -name "*.input.txt" \
  -exec sbatch ./convert-files.sh {} \;

这不会在开始计算之前等待转换完成,因此它们会失败。

使用 GNU 并行

find . -maxdepth 1 -name "*.input.txt" | \
  parallel ./convert-files.sh

find . -maxdepth 1 -name "*.input.txt" | \
  parallel srun -n1 -N1 --exclusive ./convert-files.sh

parallel只能"see"当前节点的CPU个数,所以一次只处理四个文件。更好,但仍然不是我想要的。

使用作业数组

,但由于我正在处理的文件名称中没有序号,所以我想不出一种方法让它工作。

使用 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

我还不敢尝试这个,因为我知道最后的工作不一定是最后完成的。


这看起来应该是一件很容易做的事情,但我还没有弄明白。

如果您的 $SLURM_NODELIST 包含类似于 node1,node2,node34 的内容,那么这可能有效:

find ... | parallel -S $SLURM_NODELIST convert_files

find . -maxdepth 1 -name "*.input.txt" | parallel srun -n1 -N1 --exclusive ./convert-files.sh 方法可能是要遵循的方法。但似乎 ./convert-files.sh 期望文件名作为参数,并且您正试图通过管道将其推送到 stdin。你需要使用xargs,因为xargs可以并行工作,你不需要parallel命令。

尝试:

find . -maxdepth 1 -name "*.input.txt" | xargs -L1 -P$SLURM_NTASKS srun -n1 -N1 --exclusive ./convert-files.sh

-L1 将每行拆分 find 的结果,并将其提供给 convert.sh,一次产生最大 $SLURM_NTASKS 个进程,并且 'sending' 由于 srun -n1 -N1 --exclusive.

,他们每个人都在 Slurm 分配的节点上 CPU