我想做的是在数千个输入 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 脚本不使用线程和/或进程。
提前非常感谢,我非常感谢提供的任何帮助!
首先,您需要小心使用
--ntasks-per-node
。 sbatch
的指令一开始可能有点令人困惑:
--nodes
——这是您为作业请求的节点数量。注意:每个节点的 CPU 数量完全取决于您运行的集群。每个节点可能有 1 个 CPU;可能是 4。--ntasks
——这是您为您的工作请求的任务的总数。
--ntasks-per-node
——如果您指定
--ntasks
,则这是每个节点上可以运行的最大任务数。否则,它就是确切的数字。请参阅文档:https://slurm.schedmd.com/sbatch.html
--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 个任务的作业。