PBS作业管理下集群环境的相关使用方法

2016-05-04 11:29:51 CESSCluster

PBS作业管理,即以qsubqstatqdel命令为核心的集群作业管理系统,且它是开源的。

在此环境下运行,用户不需要指定程序在哪些节点上运行,程序所需的硬件资源由PBS管理和分配。

qsubqstatqdel的功能分别为“提交作业”、“查看作业状态”、“删除作业”。

非PBS下mpi计算

通常来说,使用mpirun即可,例如mpirun -np 16 ./pom.kii2b.exe < /dev/null > pom.log,意为在一个节点上使用16核执行pom.kii2b.exestdin重定向至空,stdout重定向至pom.log

之后可能会再执行几个mv命令之类的,例如把pom.log文件移动至别处,防止多次调用时覆盖log。

PBS作业提交

直接执行qsub会提示输入PBS作业脚本,这样很不方便,因此通常来说都是把qsub脚本写到文件里,重定向输入来进行作业提交,例如qsub < cess.sbpom.qsub(其实不加<也可以),提交一个写在cess.sbpom.qsub文件里的PBS脚本。

PBS脚本形如下面那段代码从#!/bin/shmv pom.log ../$TIME.pom.log的部分。

由于存在需要多次提交相似作业的可能,例如我有20个文件夹的数据,每个文件夹里数据的处理方式相同,调用同一个程序,总不能写20个PBS脚本。因此更为通常的做法是,使用shell脚本进行qsub脚本输出再提交,举例如下:

    PNAME=fz_letkf
    NODE=1
    NP=16
    QSUBTIME="24:00:00"
    NOWDIR=`pwd`
    QSUB=cess.letkf.qsub
    LETKF=letkf020.m01
cat <<EOF >$QSUB
#!/bin/sh
#PBS -q hpca 
#PBS -V 
#PBS -N $PNAME
#PBS -l nodes=$NODE:ppn=$NP
#PBS -l walltime="$QSUBTIME"
#PBS -o /home/xfh_stu/WORK3/qsublog
#PBS -j oe 
cd $NOWDIR
mpirun ./$LETKF < /dev/null
mv pom.log ../$TIME.pom.log
EOF
    qsub $QSUB >cessrunid

调用此脚本就会自动将PBS脚本输出至$QSUB文件中,并提交此作业。通常在这段代码外面会套上循环,每次修改相应变量,从而实现一次提交多个相似作业。

在这里cat命令使用了一种叫做heredoc的写法,用于输出大段文字,同时还要替换其中的变量。界定符EOF是可以自定义的,不过通常来说都使用EOF。另外,用于结束的界定符必须顶格写(想不顶格也是可以的,但是有其他限制,且不方便)。

下面解释一下参数的意思。

  • -q:指定使用的队列。可使用qstat -q查看队列信息,包括队列名、资源限制、正在运行的任务数等。
  • -V:将执行qsub命令时拥有的环境变量都export该作业。
  • -N:指定作业名。
  • -l:指定作业使用的节点数与核数、时间限制等。
  • -o:重定向此作业的stdout至指定的文件夹中,名为作业名.o作业ID
  • -j oe:合并此作业的stdoutstderr

qsub成功提交作业后,会在stdout输出Job ID,形如作业ID.主机名,例如15252.manager。在上面的例子中,我将qsub的结果重定向至cessrunid文件中,用于存储作业ID,以便后续处理。

查看作业状态

执行qstat即可查看当前正在执行的作业以及刚刚完成的作业。在S那一列,C表示已完成,R表示正在执行,Q表示正在等待,还有一些其他不常见的状态,可以man qstat并以job state为关键词查询即可。

现在还有个问题,即如何在脚本中判断作业完成与否呢?一个很实际的例子是,我在脚本中一次提交完多个作业后,后续的脚本必须在完成这些作业后才能继续执行,那么就需要知道这些作业有没有完成。

通常有两种思路:

一是查看程序本应输出的文件有没有正常输出,即判断输出文件是否存在。或者在程序中写一些日志输出语句,脚本就可以通过查找日志文件某关键的一句话有没有输出从而知道程序运行有没有正常完成。

二是查看上文中通过-o参数指定的作业stdout输出文件,文件名为作业名.o作业ID。这也就是为什么我要把qsub提交信息保存到cessrunid这个文件里。通常来说,只要作业正常完成了,就会生成此文件。

对于第一种思路,就要根据程序具体情况来编写了。

对于第二种思路,一个典型的判断脚本如下:

while :
do

    temp=`cat cessrunid`
    runid=${PNAME}.o${temp%.manager}
    runfilename='/home/xfh_stu/WORK3/qsublog/'$runid
    if [ -f "$runfilename" ]; then
        break
    fi

    sleep 60

done

大意为:

提取出cessrunid这个文件里的qsub提交信息,并去掉后面的.manager主机名(CESS集群主机名为manager),之后改写成作业名.o作业ID的形式,并加上路径,判断该文件是否存在。

如果文件存在,则说明作业已完成,即可break掉这个无限循环,继续后面的操作了。

这里需要注意的一个地方就是,在无限循环里的每次判断中间要加上一个sleep语句,比如我设置的是每分钟跑一次循环,这样机器就不会由于每时每刻都在执行判断而耗尽资源。

删除作业

执行qdel -W 15 15303即可在15秒后停止并删除Job ID为15303的作业。

脚本的正确使用方法

通常来说,我们都是在shell脚本中进行qsub脚本输出再提交该qsub脚本。

这里存在一个问题,即shell脚本自身需要后台执行。如果执行前台执行脚本,就会导致断开SSH连接后,脚本就会停止执行。

因此,需要使用nohup ./your.script.name.sh &命令,它可以脚本在后台执行且将stdout重定向至nohup.out文件中。要注意命令最后的&是不可缺少的,如果不写,脚本虽然也会在后台执行,但是在关闭SSH后就会停止。

另外,在执行完这个命令之后要按一下回车,使其回到shell上来。

当我们解决脚本后台执行的问题后,又出现了新问题,即如何停止该脚本?

通过脚本提交的PBS作业可以通过qdel命令结束掉,而脚本本身停止就需要kill掉该脚本的进程了。

首先,我们使用ps -ef | grep your.script.name.sh查询到脚本的进程PID,之后执行kill xxxxx即可停止PID为xxxxx的进程了。

其他一些技巧

并行编译

使用make时,可用make -j来使make可以调用多核从而同时编译多个文件。可以通过-jx来指定任务数,例如-j4,如果不指定,就会尽可能调用处理器进行编译。

(另外,如果文件名不是Makefile,可以通过-f指定要make的文件。例如make -f cess.makefile

记录时间

如需知道脚本运行时间,可以在脚本首尾加上date语句,这样就可以在nohup.out文件里看到开始和结束时间了。

感谢

http://blog.csdn.net/bupt_bu/article/details/7308312

http://www.cnblogs.com/allenblogs/archive/2011/05/19/2051136.html

如果长时间无法加载评论,请对 *.disqus.com 启用代理!