SLURM:在多个文件上运行相同的并行脚本

问题描述 投票:0回答:1

我想做的是在数千个输入 csv 文件上运行相同的 python 脚本。 python 脚本是一个单进程脚本,它将单个文件作为输入,并创建一个输出文件,其中包含有关输入的一些摘要。我看到了问题here,并尝试了类似的方法,但没有成功(见结尾)。

我的 SLURM 提交脚本如下所示,并且 python 脚本嵌套在 bash for 循环内。我使用循环是因为我有一个大文件,其中包含输入 csv 文件的名称(每行一个),并使用它来调度 python 脚本。该脚本包含在文件

submit_script.sh
中,并使用 sbatch 将其提交给调度程序:
sbatch submit_script.sh

我还使用

sem
(GNU 并行)来并行化 python 脚本。

#!/bin/bash
#SBATCH --nodes=8
#SBATCH --ntasks-1024
#SBATCH --ntasks-per-node=128

OUTPUT_DIR='/path/to/output/dir'
INPUT_FILES='/some/path/to/list/of/inputs.txt'
INPUT_DIR='path/to/input/dir'
while IFS=read -r line

 FILE_NAME=${INPUT_DIR}/${line}.txt
 sem -j -1 --id ${FILE_NAME} python_script.py --input ${FILE_NAME} > ${OUTPUT_DIR}/${OUTPUT_DIR}.txt

done < <(tr -d '\r' < ${INPUT_FILES})

sem --wait

我所期望的是,通过上述 SLURM 提交,我将获得 8 个节点,在其中我将能够创建 1024 个 python 脚本实例,并且这些实例将被分成每个节点 128 个的桶?我仍在掌握 SLURM 的窍门,对于我的任何误解,我深表歉意。

发生的情况是,我确实获得了多个脚本实例,但只有大约 70 个,而不是我预期的 1024 个。

我尝试不使用

sem
并用
srun
替换(没有额外的参数),但这不起作用 - 它创建了脚本的多个副本,但所有副本都使用相同的输入文件运行,并且输出进入单个文件。

我想做的是使用

N
节点获取 SLURM 分配,并能够生成一些
M
的多个 Python 脚本副本,以便每个副本都可以处理单个文件。 python 脚本不使用线程和/或进程。

提前非常感谢,我非常感谢提供的任何帮助!

python bash gnu slurm gnu-parallel
1个回答
0
投票

首先,您需要小心使用

--ntasks-per-node
sbatch
的指令一开始可能有点令人困惑:

  • --nodes
    ——这是您为作业请求的节点数量。注意:每个节点的 CPU 数量完全取决于您运行的集群。每个节点可能有 1 个 CPU;可能是 4。
  • --ntasks
    ——这是您为您的工作请求的任务的总数。
  • --ntasks-per-node
    ——如果您指定
    --ntasks
    ,则这是每个节点上可以运行的
    最大任务数。否则,它就是确切的数字。请参阅文档:https://slurm.schedmd.com/sbatch.html
如果您知道每个节点的 CPU 数量(例如,如果您使用同构集群),则应该仅使用

--ntasks

--cpus-per-task
 来代替。这样您就可以避免过度订阅节点(这会限制您的性能)。

其次,你想使用

srun

,而不是
sem
。请参阅此处:
https://slurm.schedmd.com/srun.html

第三,你的剧本本身不太对。当您运行

sbatch

 时,您会说:“请稍后运行此脚本的内容”。 SLURM 在第一个分配的节点上运行它。

当您使用

srun

 时,您可以“立即”使用可用的 SLURM 资源运行作业。在 
sbatch 内,这意味着您可以从使用指令分配的资源中进行选择 (#SBATCH ...
)。 
sbatch
设置一些环境变量以使生活更轻松。
当你想要分区时,你需要自己设置。 SLURM 不会智能地“弄清楚”——您需要明确地安排。

我相信最终结果需要看起来更像这样:

#!/bin/bash #SBATCH --nodes=8 #SBATCH --ntasks-per-node=128 INPUT_DIR='path/to/input/dir' OUTPUT_DIR='/path/to/output/dir' # Read the file names into an array INPUT_STEMS_FILE='/some/path/to/list/of/inputs.txt' INPUT_STEMS=() while IFS= read -r line; do INPUT_STEMS+=("$line") done < <(tr -d '\r' < INPUT_STEMS_FILE) for j in `seq 0 ${#INPUT_STEMS[@]}`; do # Iterate over the indices for each of the N files # Round-robin allocation to nodes (0, 1, ..., 128, 0, 1, ...) NODE_NUMBER=$(($j % $SLURM_NTASKS_PER_NODE)) # Dynamically generate filename INPUT_FILE_NAME="$INPUT_DIR/$INPUT_STEMS[$(($i % $j))].txt" OUTPUT_FILE_NAME=$OUTPUT_DIR/$j.txt # Run a job on 1 task on 1 node, using the round-robin allocation. # The jobs run on different nodes, this way srun -N1 -n1 -r$NODE_NUMBER python_script.py --input $INPUT_FILE_NAME > $OUTPUT_FILE_NAME & done wait

这使用循环分配在每个节点上执行。还有其他分配工作的方式。

顺便说一句,您可能会发现作业数组对您的任务有用:

https://slurm.schedmd.com/job_array.html

它们更容易使用,但你创造了更多的就业机会。当您安排作业数组时,您将创建 M 个作业,而不是 1 个包含 M 个任务的作业。

© www.soinside.com 2019 - 2024. All rights reserved.