我正在尝试在slurm集群上运行python脚本,并且正在使用python的内置multiprocessing
模块。
我正在使用一个非常简单的设置,出于测试目的,示例是:
len(arg_list)
Out[2]: 5
threads = multiprocessing.Pool(5)
output = threads.map(func, arg_list)
因此,func
在 5 个参数上并行应用 5 次arg_list
.我想知道的是如何在 slurm 中分配正确数量的 cpu/任务,使其按预期工作。这是我的 slurm 批处理脚本的相关部分的样子:
#!/bin/bash
# Runtime and memory
#SBATCH --time=90:00:00
#SBATCH --mem-per-cpu=2G
# For parallel jobs
#SBATCH --cpus-per-task=10
##SBATCH --nodes=2
#SBATCH --ntasks=1
##SBATCH --ntasks-per-node=4
#### Your shell commands below this line ####
srun ./script_wrapper.py 'test'
如您所见,目前我有ntasks=1
和cpus-per-task=10
.请注意,func 的主要部分包含一个倾向于在两个内核上运行的 scipy 例程(即使用 200% 的 cpu 使用率,这就是为什么我想要 10 个 cpu 而不是 5 个)。
这是为我的目的分配资源的正确方法吗,因为目前作业花费的时间比预期的要长得多(更像是在单个线程中运行)。
我需要改为设置ntasks=5
吗?因为我从在线文档中得到的印象是,ntasks=5
反而会给srun ./script_wrapper.py 'test'
打电话五次,这不是我想要的。我的假设是对的吗?
另外,有没有办法轻松检查 CPU 使用率和多处理调用的 python 任务的所有进程 ID 等内容。池?目前我正在尝试使用sacct -u <user> --format=JobID,JobName,MaxRSS,Elapsed,AveCPU
,但由于某种原因,AveCPU
和MaxRSS
字段总是空的 (?),虽然我将第一个脚本视为一个进程,但我没有看到其他 5 个应该由多处理调用。例:
JobID JobName MaxRSS Elapsed AveCPU
------------ ---------- ---------- ---------- ----------
16260892 GP 00:13:07
16260892.0 script_wr+ 00:13:07
你的 Slurm 任务分配对我来说是正确的。Python 的多处理只能在一台机器上运行,在我看来,你在一个节点上正确地分配了 10 个 CPU。可能导致问题的原因是,默认情况下,多处理的Pool.map
工作在输入列表的"块"上,而不是一次处理一个元素。这样做是为了在任务较短时最大限度地减少开销。要强制多处理一次处理列表的一个元素,请将映射的块大小参数设置为 1,例如
threads.map(func, arglist, 1)
有关详细信息,请参阅多处理文档。
因为您说您使用的是 SciPy 的多线程版本,所以您可能还需要检查基础库的相关线程级别。例如,如果您的 SciPy 是针对英特尔数学核心函数库构建的,请尝试设置OMP_NUM_THREADS
和MKL_NUM_THREADS
环境变量,以确保每个进程使用的线程不超过 2 个,并充分利用(而不是过度使用)您分配的 SLURM 资源。
编辑:sacct 只会为您提供由 srun 直接启动的任何进程的运行时间,而不是任何子进程的运行时间。因此,在您的情况下,您将只有一个 srun 命令中的一个进程。要监视子进程,您可能需要研究在系统级别而不是通过 Slurm 运行的监视工具。