在 Slurm 中使用 Python 多处理,以及我需要哪种 ntasks 或 ncpus 组合
Using Python multiprocessing in Slurm, and which combination of ntasks or ncpus I need
我正尝试在 slurm 集群上 运行 一个 python 脚本,我正在使用 python 的内置 multiprocessing
模块。
我使用的设置非常简单,出于测试目的,示例是:
len(arg_list)
Out[2]: 5
threads = multiprocessing.Pool(5)
output = threads.map(func, arg_list)
所以 func
在 arg_list
中的 5 个参数上并行应用了 5 次。我想知道的是如何在 slurm 中分配正确数量的 cpu's/tasks 以使其按预期工作。这就是我的 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 cpus而不是 5)。
这是为我的目的分配资源的正确方法吗,因为目前作业花费的时间比预期的要长很多(更像是在单个线程中 运行ning)。
我需要改为设置 ntasks=5
吗?因为我从在线文档中得到的印象是 ntasks=5
反而会调用 srun ./script_wrapper.py 'test'
五次,这不是我想要的。我的假设是否正确?
此外,有没有一种方法可以轻松检查 CPU 使用情况以及 multiprocessing.Pool 调用的 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
默认情况下对输入列表的 "chunks" 起作用,而不是一次对一个元素起作用。它这样做是为了在任务较短时最小化开销。要强制多处理一次处理列表的一个元素,请将 map 的 chunksize 参数设置为 1,例如
threads.map(func, arglist, 1)
有关详细信息,请参阅 multiprocessing documentation。
因为您说您使用的是 SciPy 的多线程版本,您可能还想检查底层库的相关线程级别。例如,如果您的 SciPy 是针对英特尔数学核心函数库构建的,请尝试设置 OMP_NUM_THREADS
和 MKL_NUM_THREADS
environment variables 以确保每个进程使用不超过 2 个线程并充分利用(而不是过度使用)分配给您的 SLURM 资源。
编辑:sacct 只会为 s运行 直接启动的任何进程提供 运行ning 时间,而不会为任何子进程提供。因此,在您的情况下,您只能从单个 s运行 命令中获得一个进程。要监控子流程,您可能需要查看在系统级别运行的监控工具,而不是通过 Slurm。
我正尝试在 slurm 集群上 运行 一个 python 脚本,我正在使用 python 的内置 multiprocessing
模块。
我使用的设置非常简单,出于测试目的,示例是:
len(arg_list)
Out[2]: 5
threads = multiprocessing.Pool(5)
output = threads.map(func, arg_list)
所以 func
在 arg_list
中的 5 个参数上并行应用了 5 次。我想知道的是如何在 slurm 中分配正确数量的 cpu's/tasks 以使其按预期工作。这就是我的 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 cpus而不是 5)。
这是为我的目的分配资源的正确方法吗,因为目前作业花费的时间比预期的要长很多(更像是在单个线程中 运行ning)。
我需要改为设置 ntasks=5
吗?因为我从在线文档中得到的印象是 ntasks=5
反而会调用 srun ./script_wrapper.py 'test'
五次,这不是我想要的。我的假设是否正确?
此外,有没有一种方法可以轻松检查 CPU 使用情况以及 multiprocessing.Pool 调用的 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
默认情况下对输入列表的 "chunks" 起作用,而不是一次对一个元素起作用。它这样做是为了在任务较短时最小化开销。要强制多处理一次处理列表的一个元素,请将 map 的 chunksize 参数设置为 1,例如
threads.map(func, arglist, 1)
有关详细信息,请参阅 multiprocessing documentation。
因为您说您使用的是 SciPy 的多线程版本,您可能还想检查底层库的相关线程级别。例如,如果您的 SciPy 是针对英特尔数学核心函数库构建的,请尝试设置 OMP_NUM_THREADS
和 MKL_NUM_THREADS
environment variables 以确保每个进程使用不超过 2 个线程并充分利用(而不是过度使用)分配给您的 SLURM 资源。
编辑:sacct 只会为 s运行 直接启动的任何进程提供 运行ning 时间,而不会为任何子进程提供。因此,在您的情况下,您只能从单个 s运行 命令中获得一个进程。要监控子流程,您可能需要查看在系统级别运行的监控工具,而不是通过 Slurm。