SLURM:尴尬并行程序中的尴尬并行程序

oju*_*unk 4 bash matlab slurm

我有一个用 Matlab 编写的复杂模型。该模型不是由我们编写的,最好将其视为“黑匣子”,即为了从内部解决相关问题,需要重新编写整个模型,这需要数年时间。

如果我有一个“令人尴尬的并行”问题,我可以使用一个数组来提交带有选项的相同模拟的 X 变体#SBATCH --array=1-X。然而,集群通常对最大数组大小有一个(令人沮丧的小)限制。

在使用 PBS/TORQUE 集群时,我通过强制 Matlab 在单个线程上运行,请求多个 CPU,然后在后台运行多个 Matlab 实例来解决这个问题。一个示例提交脚本是:

#!/bin/bash
<OTHER PBS COMMANDS>
#PBS -l nodes=1:ppn=5,walltime=30:00:00
#PBS -t 1-600

<GATHER DYNAMIC ARGUMENTS FOR MATLAB FUNCTION CALLS BASED ON ARRAY NUMBER>

# define Matlab options
options="-nodesktop -noFigureWindows -nosplash -singleCompThread"

for sub_job in {1..5}
do
    <GATHER DYNAMIC ARGUMENTS FOR MATLAB FUNCTION CALLS BASED ON LOOP NUMBER (i.e. sub_job)>
    matlab ${options} -r "run_model(${arg1}, ${arg2}, ..., ${argN}); exit" &
done
wait
<TIDY UP AND FINISH COMMANDS>
Run Code Online (Sandbox Code Playgroud)

谁能帮我在 SLURM 集群上做同样的事情?

  • par函数不会在 Matlab 的并行循环中运行我的模型。
  • PBS/TORQUE 语言非常直观,但 SLURM 的语言让我感到困惑。假设一个类似结构的提交脚本作为我的 PBS 示例,这就是我认为某些命令会导致的结果。
    • --ncpus-per-task=5 对我来说似乎是最明显的。我是将 srun 放在循环中的 matlab 命令前面还是将其保留在 PBS 脚本循环中?
    • --ntasks=5 我想会请求 5 个 CPU,但会串行运行,除非程序特别请求它们(即 MPI 或 Python 多线程等)。在这种情况下,我是否需要将 srun 放在 Matlab 命令的前面?

Tom*_*eus 6

我不是阵列作业的大专家,但我可以帮助您处理内部循环。

我将始终使用GNU parallel在具有多个 CPU 的单个作业中并行运行多个串行进程。它是一个简单的perl脚本,所以“安装”并不难,而且它的语法非常简单。它的主要作用是并行运行一些(嵌套)循环。这个循环的每次迭代都包含一个(长)过程,就像你的 Matlab 命令一样。与您的解决方案相反,它不会一次提交所有这些进程,而是同时仅运行N进程(N您可用的 CPU 数量在哪里)。一个完成后,下一个提交,依此类推,直到您的整个循环完成。并非所有进程都花费相同的时间,这很好,只要一个 CPU 被释放,另一个进程就会启动。

然后,您想要做的是启动 600 个作业(我用下面的 3 个替换,以显示完整的行为),每个作业有 5 个 CPU。为此,您可以执行以下操作(其中我没有包括 的实际运行matlab,但可以简单地包括在内):

#!/bin/bash
#SBATCH --job-name example
#SBATCH --out job.slurm.out
#SBATCH --nodes 1
#SBATCH --ntasks 1
#SBATCH --cpus-per-task 5
#SBATCH --mem 512
#SBATCH --time 30:00:00
#SBATCH --array 1-3

cmd="echo matlab array=${SLURM_ARRAY_TASK_ID}"

parallel --max-procs=${SLURM_CPUS_PER_TASK} "$cmd,subjob={1}; sleep 30" ::: {1..5}
Run Code Online (Sandbox Code Playgroud)

使用以下方法提交此作业:

$ sbatch job.slurm
Run Code Online (Sandbox Code Playgroud)

向队列提交 3 个作业。例如:

$ squeue | grep tdegeus
         3395882_1     debug  example  tdegeus  R       0:01      1 c07
         3395882_2     debug  example  tdegeus  R       0:01      1 c07
         3395882_3     debug  example  tdegeus  R       0:01      1 c07
Run Code Online (Sandbox Code Playgroud)

每个作业获得 5 个 CPU。这些由parallel命令利用,以并行运行您的内部循环。再一次,这个内循环的范围可能(远)大于 5,parallel负责这个作业中 5 个可用 CPU 之间的平衡。

让我们检查输出:

$ cat job.slurm.out

matlab array=2,subjob=1
matlab array=2,subjob=2
matlab array=2,subjob=3
matlab array=2,subjob=4
matlab array=2,subjob=5
matlab array=1,subjob=1
matlab array=3,subjob=1
matlab array=1,subjob=2
matlab array=1,subjob=3
matlab array=1,subjob=4
matlab array=3,subjob=2
matlab array=3,subjob=3
matlab array=1,subjob=5
matlab array=3,subjob=4
matlab array=3,subjob=5
Run Code Online (Sandbox Code Playgroud)

您现在可以清楚地看到 3 次 5 进程同时运行(因为它们的输出是混合的)。

在这种情况下不需要使用srun. SLURM 将创造 3 个工作岗位。在每个作业中,一切都发生在单独的计算节点上(即就像您在自己的系统上运行一样)。


安装 GNU Parallel - 选项 1

要将 GNU 并行“安装”到您的主文件夹中,例如在~/opt.

  1. 下载最新的 GNU Parallel

  2. ~/opt如果目录尚不存在,请创建该目录

    mkdir $HOME/opt
    
    Run Code Online (Sandbox Code Playgroud)
  3. “安装”GNU Parallel:

    tar jxvf parallel-latest.tar.bz2
    cd parallel-XXXXXXXX
    ./configure --prefix=$HOME/opt
    make
    make install
    
    Run Code Online (Sandbox Code Playgroud)
  4. 添加~/opt到您的路径:

    export PATH=$HOME/opt/bin:$PATH
    
    Run Code Online (Sandbox Code Playgroud)

    (要使其永久化,请将该行添加到您的~/.bashrc.)


安装 GNU Parallel - 选项 2

使用conda.

  1. (可选)创建新环境

    conda create --name myenv
    
    Run Code Online (Sandbox Code Playgroud)
  2. 加载现有环境:

    conda activate myenv
    
    Run Code Online (Sandbox Code Playgroud)
  3. 安装 GNU 并行:

    conda install -c conda-forge parallel 
    
    Run Code Online (Sandbox Code Playgroud)

请注意,该命令仅在加载环境时可用。


Mil*_*ams 4

虽然 Tom 关于使用 GNU Parallel 的建议是一个很好的建议,但我将尝试回答所提出的问题。

如果您想使用matlab相同的参数运行该命令的 5 个实例(例如,如果它们通过 MPI 进行通信),那么您需要询问--ncpus-per-task=1--ntasks=5并且您应该在该行matlab前面加上srun并摆脱循环。

就您而言,由于您的 5 个呼叫中的每一个matlab都是独立的,因此您想要请求--ncpus-per-task=5, --ntasks=1。这将确保您为每个作业分配 5 个 CPU 核心来按照您的意愿进行操作。如果您愿意,您可以在行前matlab加上以下内容srun,但这对您只运行一项任务没有什么影响。

当然,只有当 5 次matlab运行中的每一次都花费相同的时间时,这才是有效的,因为如果其中一个运行时间更长,那么其他 4 个 CPU 核心将处于空闲状态,等待第五次运行完成。