NWPC高性能计算机环境介绍:作业管理

目录

本文是《NWPC高性能计算机环境介绍》系列文章的一部分。

本文内容部分参考ECMWF的文档《Batch Systems》。

直接运行与批处理

之前章节介绍过,高性能计算机系统由少量的登陆节点和大量的计算节点组成。

直接在登录节点上运行程序就是下图所示的情形,登陆节点上跑了大量的程序,导致登陆节点响应速度降低,而大量计算节点处于空闲状态。

我们在平时工作中经常会遇到登陆节点执行命令卡住的情况,大部分都是因为某用户在登录节点上运行大量程序,导致CPU占用过高。

登陆节点上直接运行程序,图片来自ECMWF的《Batch Systems》

我们应该将作业提交到计算节点上以批处理的方式运行,如下图所示。这就需要使用作业调度系统。

提交到计算节点上运行程序,图片来自ECMWF的《Batch Systems》

为了保证系统正常提供服务,请不要在登录节点上运行程序。

直接运行

某些特殊情况下,我们仍然需要在登录节点上运行程序,例如编辑文件、编译程序等。

登录节点上直接运行程序有下面几种方式:

交互方式

命令行输入程序名及参数,程序在登录终端前台运行,程序运行结束才能运行下一条命令。

./your_program arg1 arg2

后台方式

使用&在后台运行程序,同时执行其他操作。此种方式需要保证登录终端一直存在才能运行结束。

./your_program arg1 arg2 &

我们使用ecFlow UI监控数值预报业务系统一般使用这种方式。

如果需要在登录终端退出后依然运行程序,则使用nohup运行程序。

nohup ./your_program arg1 arg2 &

ecFlow的后台服务就是使用nohup命令使程序与终端解绑。

作业调度系统

PAI上的批处理由Gridview综合管理系统实现,该系统基于开源作业调度系统Slurm Workload Manager开发。

Slurm Workload Manager主要提供一下功能:

  • 运行和管理批处理作业
  • 资源申请
  • 作业调度

在作业调度系统中运行的批处理作业一般都是shell脚本,使用某些特殊指令描述作业属性。

作业调度原理

下图说明作业调度系统的原理。

作业调度系统原理,图片来自ECMWF的《Batch Systems》

批处理系统负责对计算节点进行组织,提供队列、优先级和限制等功能。 用户从登陆节点可以提交作业和查询批处理系统的状态。 批处理系统从计算节点获取节点和作业信息。

作业调度系统的基本任务

不同作业调度系统提供不同的命令和方法,但提供的功能大多相似:

  • 向调度系统提交作业
  • 检查队列的状态
  • 检查作业是否运行
  • 从调度系统中取消或删除某个作业

在创建脚本时,通常会在脚本开头添加特殊注释,定义作业的属性。例如:

  • 作业名
  • 队列名
  • 使用资源(处理器个数、内存等)
  • 标准输出、标准错误输出文件
  • 工作路径
  • 时间限制

任务队列

不同队列有不同的优先级和限制。

所有用户可以使用的队列(子系统2)

队列名描述优先级节点个数节点名
serial串行队列100024cmbc[0011-0034]
normal并行队列10001479cmbc[0035-1538]
largemem大内存并行队列1000230cmbc[0035-0260]

仅限业务账户使用的队列(子系统2)

队列名描述优先级节点个数节点名
serial_op串行队列100024cmbc[0011-0034]
operation并行队列20001479cmbc[0035-1538]

可以看到serial/serial_op、normal/operation是共享节点的,largemem和normal/operation共享部分节点。

业务账户具有最高的优先级,在资源不够的时候会抢占对应队列的资源。 建议大家在非业务运行高峰时间段提交作业,避免被抢占。

查询队列状态

使用sinfo命令查看队列状态。

sinfo命令查看队列状态

STATE代表节点状态,含义如下图所示:

节点状态含义
idle空闲
alloc被占用
mix部分占用
down不可用
drain管理员下线

使用sinfo -s可以查看队列的汇总状态。

sinfo -s命令查看队列状态

NODES列是各种状态的节点个数,节点状态如下表所示

节点状态含义
A占用
I空闲
O其它
T总数

编写作业脚本

提交作业前需要首先便也作业脚本。

作业是一个shell脚本。第一行必须指定shell解释器,如bash、ksh、csh等。

指令是shell注释。以#SBATCH开头,#SBATCH中间没有空格。不能展开shell变量,仅是shell注释。

必须设置comment参数,指定运行的模式名称,例如GRAPES。

#!/bin/ksh

# 作业名称
#SBATCH -J GRAPES

# 队列名称
#SBATCH -p operation

# 标准输出文件
#SBATCH -o /g2/nwp/ECFOUT/gmf_grapes_gfs_v2.4/06/model/fcst_long.1

# 标准错误输出文件
#SBATCH -e /g2/nwp/ECFOUT/gmf_grapes_gfs_v2.4/06/model/fcst_long.1.err
  
# 注释,必须设置
#SBATCH --comment=GRAPES

# 特殊指令,出错后不自动重新提交
#SBATCH --no-requeue

# 节点个数
#SBATCH -N 128

# 每个节点使用的CPU数
#SBATCH --ntasks-per-node=30

作业指令

作业指令可以在shell注释中以#SBATCH开头的指令设置,也可以在使用sbatch命令提交作业时使用命令行参数设置。

常用的作业指令如下:

指令描述示例
–job-name / -J作业名称#SBATCH –J GRAPES
–comment指定运行的模式名称#SBATCH –comment=GRAPES
–partition / -p指定队列#SBATCH -p normal
–nodes / -N节点个数#SBATCH -N 2
–ntasks / -n任务个数(一般为处理器总数)#SBATCH -n 64
–ntasks-per-node每个节点使用的处理器数量#SBATCH –ntasks-per-node=32
–cpus-per-task每个任务使用的处理器数量(OpenMP线程)#SBATCH –cpus-per-task=4
-t 天-时:分:秒作业运行时间#SBATCH –t 00:20:00
–output / -ostdout输出文件#SBATCH -o %j.out
–error / -estderr输出文件#SBATCH -e %j.err

说明:

  • nodes、ntasks、ntasks-per-node:一般只需要指定2项,第3项可以由另外两项推导出。
  • partition:串行作业必须使用串行节点。
  • t: 某些情况下,作业运行出错后不会自动退出,最好设置墙钟时间。业务系统必须设置,避免作业运行时间过长。

模式名称

使用modelname命令查看支持的模式名称。

modelname命令查看支持的模式名称

数值预报中心一般使用GRAPES即可。 该项参数主要是用于统计高性能计算机资源都用于何种用途,所以强烈建议数值预报中心使用GRAPES作为comment参数。

作业脚本示例

示例1:串行作业

下面代码是全球GRAPES预报后处理系统使用ncl画图的脚本,是一个串行作业。

#!/bin/ksh
#SBATCH -J GRAPES
#SBATCH -p serial_op
#SBATCH -o /g2/nwp_pd/.../RAIN24_SFC_FC_AEA_sep_024.1
#SBATCH -e /g2/nwp_pd/.../RAIN24_SFC_FC_AEA_sep_024.1.err
#SBATCH --comment=GRAPES
#SBATCH -t 00:10:00
#SBATCH --no-requeue

# ...skip some codes...

ncl ${file_name}
示例2:并行MPI作业

下面代码是全球GRAPES集合预报模式积分任务,是一个并行作业。

#!/bin/ksh
#SBATCH -J GRAPES
#SBATCH -p operation
#SBATCH -o /g2/nwp_qu/ECFLOWOUT/.../forecast.1
#SBATCH -e /g2/nwp_qu/ECFLOWOUT/.../forecast.1.err
#SBATCH --comment=GRAPES
#SBATCH -N 32
#SBATCH --ntasks-per-node=32
#SBATCH --no-requeue
#SBATCH -t 01:45:00
#SBATCH --exclusive

srun --mpi=pmi2 ./grapes_global.exe

运行并行程序的具体方式由并行计算课程单独介绍,不属于本教程的一部分。

提交作业

使用sbatch向slurm提交作业。上一节提到作业参数的设置方法:

  • 脚本中使用指令(以#SBATCH开头的shell注释)
  • 使用与指令相同的命令行参数

作业提交成功会返回作业号

sbatch提交成功会返回作业号,本例中作业号是3217587

作业提交失败会返回错误消息

sbatch提交失败会返回错误信息,本例中作业脚本没有指定comment参数

判断作业是否提交成功

我们可以使用上面的输出判断作业是否提交成功。

下面的代码源自业务系统在ecflow中提交作业使用的命令,可以访问/g1/u/nwp/bin/slsubmit6查看源代码。

第2行使用sbatch提交作业,并将标准输出保存到submit_output变量。

第4行从输出中提取作业号,第6行会判断作业号是否提取成功。如果提取成功,说明作业提交成功;如果作业号为空,说明作业提交失败。

 1#!/bin/bash
 2submit_output=$(sbatch ${job_name} 2>>${submit_log_path})
 3
 4rid=$(echo ${submit_output} | cut -d ' ' -f 4)
 5
 6if [ -n "$rid" ]; then
 7	echo "Job submit success: ${task_name}"
 8    # do something: set a flag...
 9else
10	echo "Job submit failed: ${task_name}"
11    # do something: show an error...
12fi

检查作业

判断脚本是否在Slurm中运行

对于串行作业来说,同一个脚本可以在串行队列中运行,也可以在登录节点上运行。

尽管之前提到过不应该在登录节点上运行程序,但业务系统中某些任务不适合在登录节点上运行。

循环检测模式输出文件的作业一般会运行1到2个小时,如果在串行队列中运行,会长时间占用一个任务槽。 该任务大部分时间调用sleep命令,占用CPU较小,所以可以将其放到登录节点上运行,不会影响登录节点正常使用,同时能节省串行队列。

对于不同的运行方式,我们需要获取不同的作业标识用于控制任务:

  • 队列中运行:作业号
  • 登录节点运行:进程号

所以我们需要判断脚本是否在Slurm中运行。

Slurm运行作业时会自动设置一些环境变量,例如:

  • SLURM_JOB_ID: 作业号
  • SLURM_NODELIST: 节点列表

业务系统使用如下的脚本判断作业是否在Slurm中运行

#!/bin/ksh
JOB_ID=$( echo ${SLURM_JOB_ID:-0.0} )
if [ $JOB_ID -eq 0 ] ; then
  JOB_ID=$$
  echo "JOB is running on login node"
else
  echo "JOB is running on Slurm"
fi

squeue

squeue显示正在运行或等待的作业信息。

squeue显示slurm中当前所有作业的状态

ST代表作业状态,具体含义见下表。

作业状态含义
PD等待资源
R正在运行
S挂起
CD作业正常退出
F作业异常退出
PR作业被抢占
TO作业超时被杀

其中PD和R是最常见的状态。

slclient_go

slclinet_go query 是封装的slurm查询程序,程序放在/g1/u/nwp/bin/slclient_go

slclient_go query输出

该工具是数值预报中心开发的开源项目,如果对该项目感兴趣请访问 https://github.com/perillaroc/slurm-client-go。

取消作业

scancel 取消指定的作业,主要参数如下:

  • -i: 交互模式
  • -v: 显示
  • -u: 用户名

scancel jobid: 取消作业号为jobid的作业

scancel取消特定作业号的任务

scancel -u user: 取消用户user提交的所有作业

scancel取消用户wangdp提交的所有作业

为什么作业没有运行

提交作业后往往会遇到作业没有立即运行的情况,squeue输出的最后一列会给出提示。

squeue最后一列说明未运行的原因

常见的未运行原因如下表所示:

原因描述
Priority其他作业优先级更高
Resources没有足够的资源
JobHeld作业被挂起
PartitionNodeLimit作业请求的节点数超过分区的作业节点数限制
PartitionTimeLimit作业请求的运行时间超过分区的作业运行时间限制
PartitionDown作业所在的分区处于 DOWN 状态
QOSMaxJobsPerUserLimit超过最大运行作业数限制
QOSMaxCpuPerUserLimit超过最多使用CPU核数限制
Dependency其他依赖作业没有完成

最常见的原因就是没有足够的资源或者被业务系统作业抢占资源。

队列使用规则

每个账户都有队列使用限制,这里列出2018版培训PPT中给出的限制数,2019年应该由修改,具体情况请咨询高性能计算机管理员。

CPU核数

每个用户最多使用4100核(8200?)

作业数

每个用户最多运行50个作业;最多提交200个作业(所有队列作业和)

每个用户最多在normal和largemem队列运行10个并行作业(100?)

队列

串行作业必须提交到串行作业队列

参考

ECMWF关于批处理系统和Slurm的文档

https://software.ecmwf.int/wiki/display/UDOC/Batch+Systems

https://software.ecmwf.int/wiki/display/UDOC/SLURM

https://software.ecmwf.int/wiki/display/UDOC/Slurm+job+script+examples

Slurm网站和文档

http://www.schedmd.com/

https://slurm.schedmd.com/

https://slurm.schedmd.com/tutorials.html