交互式提交并行作业:srun¶
srun
可以交互式提交运行并行作业,提交后,作业等待运行,等运行完毕后,才返回终端。
基本语法为:
srun [OPTIONS...] executable [args...]
主要输入环境变量¶
一些提交选项可通过环境变量来设置,命令行的选项优先级高于设置的环境变量,将覆盖掉环境变量的设置。环境变量与对应的参数如下:
SLURM_ACCOUNT
:类似-A, --account。SLURM_ACCTG_FREQ
:类似--acctg-freq。SLURM_BCAST
:类似--bcast。SLURM_COMPRESS
:类似--compress。SLURM_CORE_SPEC
:类似--core-spec。SLURM_CPU_BIND
:类似--cpu-bind。SLURM_CPUS_PER_GPU
:类似-c, --cpus-per-gpu。SLURM_CPUS_PER_TASK
:类似-c, --cpus-per-task。SLURM_DEBUG
:类似-v, --verbose。SLURM_DEPENDENCY
:类似-P, --dependency=\。 SLURM_DISABLE_STATUS
:类似-X, --disable-status。SLURM_DIST_PLANESIZE
:类似-m plane。SLURM_DISTRIBUTION
:类似-m, --distribution。SLURM_EPILOG
:类似--epilog。SLURM_EXCLUSIVE
:类似--exclusive。SLURM_EXIT_ERROR
:Slurm出错时的退出码。SLURM_EXIT_IMMEDIATE
:当--immediate使用时且资源当前无效时的Slurm退出码。SLURM_GEOMETRY
:类似-g, --geometry。SLURM_GPUS
:类似-G, --gpus。SLURM_GPU_BIND
:类似--gpu-bind。SLURM_GPU_FREQ
:类似--gpu-freq。SLURM_GPUS_PER_NODE
:类似--gpus-per-node。SLURM_GPUS_PER_TASK
:类似--gpus-per-task。SLURM_GRES
:类似--gres,参见SLURM_STEP_GRES
。SLURM_HINT
:类似--hint。SLURM_IMMEDIATE
:类似-I, --immediate。SLURM_JOB_ID
:类似--jobid。SLURM_JOB_NAME
:类似-J, --job-name。SLURM_JOB_NODELIST
:类似-w, –nodelist=\,格式类似node[1-10,11,13-28]。 SLURM_JOB_NUM_NODES
:分配的总节点数。SLURM_KILL_BAD_EXIT
:类似-K, --kill-on-bad-exit。SLURM_LABELIO
:类似-l, --label。SLURM_LINUX_IMAGE
:类似--linux-image。SLURM_MEM_BIND
:类似--mem-bind。SLURM_MEM_PER_CPU
:类似--mem-per-cpu。SLURM_MEM_PER_NODE
:类似--mem。SLURM_MPI_TYPE
:类似--mpi。SLURM_NETWORK
:类似--network。SLURM_NNODES
:类似-N, --nodes,即将废弃。SLURM_NO_KILL
:类似-k, --no-kill。SLURM_NTASKS
:类似-n, --ntasks。SLURM_NTASKS_PER_CORE
:类似--ntasks-per-core。SLURM_NTASKS_PER_SOCKET
:类似--ntasks-per-socket。SLURM_NTASKS_PER_NODE
:类似--ntasks-per-node。SLURM_OPEN_MODE
:类似--open-mode。SLURM_OVERCOMMIT
:类似-O, --overcommit。SLURM_PARTITION
:类似-p, --partition。SLURM_PROFILE
:类似--profile。SLURM_PROLOG
:类似--prolog,仅限srun
。SLURM_QOS
:类似--qos。SLURM_REMOTE_CWD
:类似-D, --chdir=。SLURM_RESERVATION
:类似--reservation。SLURM_RESV_PORTS
:类似--resv-ports。SLURM_SIGNAL
:类似--signal。SLURM_STDERRMODE
:类似-e, --error。SLURM_STDINMODE
:类似-i, --input。SLURM_SRUN_REDUCE_TASK_EXIT_MSG
:如被设置,并且非0,那么具有相同退出码的连续的任务退出消息只显示一次。SLURM_STEP_GRES
:类似--gres(仅对作业步有效,不影响作业分配),参见SLURM_GRES
。SLURM_STEP_KILLED_MSG_NODE_ID=ID
:如被设置,当作业或作业步被信号终止时只特定ID的节点下显示信息。SLURM_STDOUTMODE
:类似-o, --output。SLURM_TASK_EPILOG
:类似--task-epilog。SLURM_TASK_PROLOG
:类似--task-prolog。SLURM_TEST_EXEC
:如被定义,在计算节点执行之前先在本地节点上测试可执行程序。SLURM_THREAD_SPEC
:类似--thread-spec。SLURM_THREADS
:类似-T, --threads。SLURM_TIMELIMIT
:类似-t, --time。SLURM_UNBUFFEREDIO
:类似-u, --unbuffered。SLURM_USE_MIN_NODES
:类似--use-min-nodes。SLURM_WAIT
:类似-W, --wait。SLURM_WORKING_DIR
:类似-D, --chdir。SRUN_EXPORT_ENV
:类似--export,将覆盖掉SLURM_EXPORT_ENV
。
主要输出环境变量¶
srun
会在执行的节点上设置如下环境变量:
SLURM_CLUSTER_NAME
:集群名。SLURM_CPU_BIND_VERBOSE
:--cpu-bind详细情况(quiet、verbose)。SLURM_CPU_BIND_TYPE
:--cpu-bind类型(none、rank、map-cpu:、mask-cpu:)。SLURM_CPU_BIND_LIST
:--cpu-bind映射或掩码列表。SLURM_CPU_FREQ_REQ
:需要的CPU频率资源,参见--cpu-freq和输入环境变量SLURM_CPU_FREQ_REQ
。SLURM_CPUS_ON_NODE
:节点上的CPU颗数。SLURM_CPUS_PER_GPU
:每颗GPU对应的CPU颗数,参见--cpus-per-gpu选项指定。SLURM_CPUS_PER_TASK
:每作业的CPU颗数,参见--cpus-per-task选项指定。SLURM_DISTRIBUTION
:分配的作业的分布类型,参见-m, --distribution。SLURM_GPUS
:需要的GPU颗数,仅提交时有-G, --gpus时。SLURM_GPU_BIND
:指定绑定任务到GPU,仅提交时具有--gpu-bind参数时。SLURM_GPU_FREQ
:需求的GPU频率,仅提交时具有--gpu-freq参数时。SLURM_GPUS_PER_NODE
:需要的每个节点的GPU颗数,仅提交时具有--gpus-per-node参数时。SLURM_GPUS_PER_SOCKET
:需要的每个socket的GPU颗数,仅提交时具有--gpus-per-socket参数时。SLURM_GPUS_PER_TASK
:需要的每个任务的GPU颗数,仅提交时具有--gpus-per-task参数时。SLURM_GTIDS
:此节点上分布的全局任务号,从0开始,以,分隔。SLURM_JOB_ACCOUNT
:作业的记账名。SLURM_JOB_CPUS_PER_NODE
:每个节点的CPU颗数,格式类似40(x3),3,顺序对应SLURM_JOB_NODELIST
节点名顺序。SLURM_JOB_DEPENDENCY
:依赖关系,参见--dependency选项。SLURM_JOB_ID
:作业号。SLURM_JOB_NAME
:作业名,参见--job-name选项或srun启动的命令名。SLURM_JOB_PARTITION
:作业使用的队列名。SLURM_JOB_QOS
:作业的服务质量QOS。SLURM_JOB_RESERVATION
:作业的高级资源预留。SLURM_LAUNCH_NODE_IPADDR
:任务初始启动节点的IP地址。SLURM_LOCALID
:节点本地任务号。SLURM_MEM_BIND_LIST
:--mem-bind映射或掩码列表(\- )。
SLURM_MEM_BIND_PREFER
:--mem-bin prefer优先权。SLURM_MEM_BIND_TYPE
:--mem-bind类型(none、rank、map-mem:、mask-mem:)。SLURM_MEM_BIND_VERBOSE
:内存绑定详细情况,参见--mem-bind verbosity(quiet、verbose)。SLURM_MEM_PER_GPU
:每颗GPU需求的内存,参见--mem-per-gpu。SLURM_NODE_ALIASES
:分配的节点名、通信IP地址和节点名,每组内采用:分隔,组间通过,分隔,如:SLURM_NODE_ALIASES
=0:1.2.3.4:foo,ec1:1.2.3.5:bar。SLURM_NODEID
:当前节点的相对节点号。SLURM_NODELIST
:分配的节点列表,格式类似node[1-10,11,13-28]。SLURM_NTASKS
:任务总数。SLURM_PRIO_PROCESS
:作业提交时的调度优先级值(nice值)。SLURM_PROCID
:当前MPI秩号。SLURM_SRUN_COMM_HOST
:节点的通信IP。SLURM_SRUN_COMM_PORT
:srun的通信端口。SLURM_STEP_LAUNCHER_PORT
:作业步启动端口。SLURM_STEP_NODELIST
:作业步节点列表,格式类似node[1-10,11,13-28]。SLURM_STEP_NUM_NODES
:作业步的节点总数。SLURM_STEP_NUM_TASKS
:作业步的任务总数。SLURM_STEP_TASKS_PER_NODE
:作业步在每个节点上的任务总数,格式类似40(x3),3,顺序对应SLURM_JOB_NODELIST
节点名顺序。SLURM_STEP_ID
:当前作业的作业步号。SLURM_SUBMIT_DIR
:提交作业的目录,或有可能由-D,–chdir参数指定。SLURM_SUBMIT_HOST
:提交作业的节点名。SLURM_TASK_PID
:任务启动的进程号。SLURM_TASKS_PER_NODE
:每个节点上启动的任务数,以SLURM_NODELIST
中的节点顺序显示,以,分隔。如果两个或多个连续节点上的任务数相同,数后跟着(x#),其中#是对应的节点数,如SLURM_TASKS_PER_NODE
=2(x3),1"表示,前三个节点上的作业数为3,第四个节点上的任务数为1。SLURM_UMASK
:作业提交时的umask掩码。SLURMD_NODENAME
:任务运行的节点名。SRUN_DEBUG
:srun命令的调试详细信息级别,默认为3(info级)。
多程序运行配置¶
Slurm支持一次申请多个节点,在不同节点上同时启动执行不同任务。为实现次功能,需要生成一个配置文件,在配置文件中做相应设置。
配置文件中的注释必需第一列为#,配置文件包含以空格分隔的以下域(字段):
- 任务范围(Task rank):一个或多个任务秩,多个值的话可以用逗号,分隔。范围可以用两个用-分隔的整数表示,小数在前,大数在后。如果最后一行为*,则表示全部其余未在前面声明的秩。如没有指明可执行程序,则会显示错误信息:“No executable program specified for this task”。
- 需要执行的可执行程序(Executable):也许需要绝对路径指明。
- 可执行程序的参数(Arguments):“%t”将被替换为任务号;“%o”将被替换为任务号偏移(如配置的秩为“1-5”,则偏移值为“0-4”)。单引号可以防止内部的字符被解释。此域为可选项,任何在命令行中需要添加的程序参数都将加在配置文件中的此部分。
例如,配置文件silly.conf内容为:
###################################################################
# srun multiple program configuration file
#
# srun -n8 -l --multi-prog silly.conf
###################################################################
4-6 hostname
1,7 echo task:%t
0,2-3 echo offset:%o
运行:srun -n8 -l --multi-prog silly.conf
输出结果:
0: offset:0
1: task:1
2: offset:1
3: offset:2
4: node1
5: node2
6: node4
7: task:7
常见例子¶
运行多核并行任务¶
使用8个CPU核 ( -n8
) 运行作业,并在标准输出上显示任务号 (-l
)
srun -n8 -l hostname
输出结果:
3: cu021
4: cu021
5: cu021
6: cu021
7: cu021
1: cu021
0: cu021
2: cu021
分配任务在不同进程上¶
在脚本中使用 -r2
参数使其在第2号(分配的节点号从0开始)开始的两个节点上运行,并采用实时分配模式而不是批处理模式运行。
脚本test.sh
内容:
#!/bin/sh
echo $SLURM_NODELIST
srun -lN2 -r2 hostname
srun -lN2 hostname
运行: salloc -N4 -p cpu test.sh
输出结果:
cu[011-014]
1: cu014
0: cu013
1: cu012
0: cu011
可以看出先启动的任务在 cu[013-014]
上运行,即后两个节点。
在分配的节点上并行运行两个作业步¶
脚本test.sh
内容:
#!/bin/bash
srun -lN2 -n2 -r 2 sleep 60 &
srun -lN2 -n2 -r 0 sleep 60 &
sleep 1
squeue
squeue -s
wait
运行: salloc -N4 -p cpu test.sh
输出结果:
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
368585 cpu interact ypliucat R 0:04 4 cu[011-014]
STEPID NAME PARTITION USER TIME NODELIST
368585.0 sleep cpu ypliucat 0:01 cu[011-012]
368585.1 sleep cpu ypliucat 0:01 cu[013-014]
368585.extern extern cpu ypliucat 0:04 cu[011-014]
可以看出我们分别创建了两个作业步 (Step),分别运行在后两个和前两个节点上。
运行 MPI 作业¶
脚本test.sh
内容:
#!/bin/sh
MACHINEFILE="nodes.$SLURM_JOB_ID"
# 生成 MPI 所需的包含节点名的machinfile文件
module load intel/2023.2
srun -l /bin/hostname | sort -n | awk ’{print $2}’ > $MACHINEFILE
# 运行 MPI 作业
mpirun -np $SLURM_NTASKS -machinefile $MACHINEFILE mpi-app
rm $MACHINEFILE
采用2个节点(-N2)共4个CPU核(-n4)运行:salloc -N2 -n4 test.sh
利用不同节点运行不同作业¶
利用不同节点号(SLURM_NODEID
)运行不同作业,节点号从0开始:
脚本test.sh
内容:
case $SLURM_NODEID in
0)
echo "I am running on "
hostname
;;
1)
hostname
echo "is where I am running"
;;
esac
运行: srun -N2 test.sh
输出:
cu012
is where I am running
I am running on
cu011
利用多核选项控制任务执行¶
采用2个节点(-N2
),每节点2颗CPU,每颗CPU 2颗CPU核(-B 2-2:2-2
),运行作业:
srun -N2 -p cpu -B 2-2:2-2 a.out
运行GPU作业¶
脚本gpu.sh
内容:
#!/bin/bash
srun -n1 -p gpu --gres=gpu:2 prog1
-p gpu
指定采用GPU队列,--gres=gpu:2
指明每个节点使用 2 块 GPU 卡。
Tip
目前嘉庚智算上的 GPU 均为 NVIDIA A100 80G NVLink 全连接计算卡。
排它性独占运行作业¶
脚本my.sh
内容:
#!/bin/bash
srun --exclusive -n4 prog1 &
srun --exclusive -n3 prog2 &
srun --exclusive -n1 prog3 &
srun --exclusive -n1 prog4 &
wait
注意
利用 --exclusive
开启排他性独占时,默认计费按照 每个srun
使用其所在节点全部资源进行,即使申请了 1 个 CPU 核或者 1 张 GPU 卡也会按照整个节点(64 个 CPU 核 / 8 张 GPU 卡)来计算。