如何为Kaldi安装GridEngine

Sun GridEngine(SGE)是一个开源的计算集群\网格管理工具。是Kaldi的维护团队使用最多的版本。目前由甲骨文负责维护,所以他们现在管它叫Oracle GridEngine(译者注:从2013年10月22日起,GridEngine的维护和客户服务已经由Univa软件公司接管)。在CSLP@JHU使用的版本是6.2u5。SGE是一个稳定的工具,所以使用哪个版本其实没那么重要。除SGE外,还有很多其他类似的软件,有一些是后期创建的开源分支。在这个文档中,我们仅指由Oracle维护的原版SGE。

在这一部分,我们将说明如何在一个集群中安装并配置GridEngine。如果你的集群使用亚马逊云EC2,并且要一个能够方便扩展新节点的工具,我建议你看看MIT的StarCluster项目。我们在Sourceforge上也创建过一个类似的项目,叫做kluster,因为当时StarCluster不是很稳定。但相信它现在已经有很大进步了。

安装GridEngine

首先,你需要安装GridEngine的基本工具。在GridEngine中,队列管理软件运行在主控节点(master)上,另外一些工具运行在所有队列节点上。master本身也可以加入队列。这里有个概念叫做影子主控(shadow master),相当于master的备份,以防master节点掉线。但在这里我们不做探讨(作者注:我们感觉就是在另外一个节点上安装gridengine-master,然后把master设置为原来的master。但不确定这么做是否可行)。

根据我们的经验,从源代码编译安装GridEngine是非常痛苦的。如果你的Linux发行版的源中包含GridEngine包,那就简单多了。你得谨慎一点,因为并不是所有的发行版中都包含GridEngine包。我们是在Debian上安装的,所以下面介绍如何在Debian上安装和配置。

在主控节点上安装GridEngine的指令是

sudo apt-get install gridengine-master gridengine-client

在选择界面中选择yes进行自动配置。安装程序将会让你输入cell name,可以用默认的default。然后它会问你master的名字,需要填上你所选择作为主控节点的计算机的主机名。通常,需要填写主控计算机的域名全称,但我觉得任何一个能通过主机名查找的方式找到这台计算机名字都可以。需要注意的是,有时候GridEngine会比较挑剔,要求主机名查找和域名(DNS)查找的结果完全匹配。很多GridEngine的运行问题都是由这个问题导致的。另外需要注意,使用apt-get remove删除这些工具并重新安装并不会要求你重新配置,因为Debian会记住你上次安装时的选择(译者注:管理员可以使用aptitude purge完全删除软件绑定的配置文件)。

然后把你自己加入SGE的管理员组

sudo qconf -am <your-user-id>

这里-am表示添加(add)管理员(manager),以此类推,-dm用来删除(delete)管理员,-sm用来显示(show)管理员列表。使用qconf -help查看所有可用的选项。

在普通节点上安装GridEngine的指令是

sudo apt-get install gridengine-client gridengine-exec

同样,cell name不变,master就是你之前安装了主控节点的主机名。你可以在主控节点上安装,这样主控节点也可以运行队列中的任务。

安装完成后,运行qstat和qhost -q,你会看到SGE是否已经开始工作了。下面就是一切正常的情况下你会看到的内容

dpovey_gmail_com@instance-1:~$ qstat dpovey_gmail_com@instance-1:~$ qhost -q HOSTNAME ARCH NCPU LOAD MEMTOT MEMUSE SWAPTO SWAPUS ------------------------------------------------------------------------------- global - - - - - - - instance-1.c.analytical-rig-638.internal lx26-amd64 1 0.07 3.6G 133.9M 0.0 0.0

到这一步时,还没有完全配置好,这一步只是用来检查工作节点和主控节点是否已经连通。如果在这一步出现错误,那很可能跟DNS查找、反DNS查找、或者是你的/etc/hostname和/etc/hosts文件的内容有关。当这些信息不一致的时候,GridEngine会罢工。如果你想改变主控节点的名字,需要编辑文件

/var/lib/gridengine/default/common/act_qmaster

(作者注:这是在Debian Wheezy发行版中的位置)(译者注:修改之后最好运行/etc/init.d/gridengine-exec restart或者重新启动,以确保配置成功被加载)

配置GridEngine

首先需要定义一个队列(queue)。因为GridEngine默认不会定义任何队列。我们先来创建一个叫做all.q的队列。请确保shell环境变量EDITOR的值是你常用的编辑器,如vim或emacs。以下的配置方法适用于主控节点和工作节点。

qconf -aq

这条指令会打开一个编辑器。在编辑器中编辑以下这行

qname template

将它改为

qname all.q

然后,将shell的值改为/bin/bash。这个设置比默认值更好,不过对于Kaldi没有影响。退出编辑器后,这些设置会自动保存,但是如果存在语法错误,qconf会拒绝你的修改。后面我们会用qconf -md all.q进一步修改这个队列的属性。

在GridEngine中保存着一些全局配置,这些配置不专属于某个队列。使用qconf -sconf查看这些配置项,或者用qconf -mconf进行编辑修改。比如下面这行

administrator_mail root

如果你能在服务器上发送邮件(作者注:测试方法是,在服务器上执行mail [email protected]指令。),那么你就可以把root改成一个有效的邮件地址,这样如果GridEngine出现问题你就会通过邮件收到通知。需要注意的是,由于反垃圾邮件策略,在EC2上从云端发送邮件是非常麻烦的,要想用Google云服务发送邮件更是几乎不可能。所以最好不要修改这个配置项。另外一个可以修改的配置项是

flush_time=00:00:10

其默认值是00:00:15。这样修改可以使任务提交的速度加快。

在GridEngine中,存在一个叫做“资源”的概念,你可以在任务中请求或指定资源。可以通过qconf -sc查看资源或用qconf -mc修改。修改默认的内存需求的方法是,编辑mem_free行的值,由0改为1G。

name shortcut type relop requestable consumable default urgency #------------------------------------------------------------------------------------------ <snip> mem_free mf MEMORY <= YES NO 1G 0

建议加上下面这两行,在任何地方插入都可以

name shortcut type relop requestable consumable default urgency #------------------------------------------------------------------------------------------ <snip> gpu g INT <= YES YES 0 10000 ram_free ram_free MEMORY <= YES JOB 1G 0

只有当你想在队列中添加GPU服务时才需要"gpu"项。我们发现ram_free项在管理节点的内存方面用处很大,而系统默认的mem_free似乎并不能起到作用。后面往集群中添加节点时,将使用qconf -me <some-hostname>然后编辑complex_values如下

complex_values ram_free=112G,gpu=2

(作者注:此例是对于一个有112G物理内存和2个GPU卡的机器)。如果提交一个内存需求10G的任务,可以在qsub的选项中指定-l mem_free=10G,ram_free=10G,mem_free会确保在任务开始时工作节点有足够的内存。ram_free确保我们不会往同一个节点上同时提交多个需要大量内存的任务。除了添加ram_free资源需求外,我们还尝试了用qconf -mc编辑mem_free项的consumable值为YES,以确保GridEngine会持续监测内存需求。但是这种方法好像不太管用。注意,ram_free和gpu都是我们选择的名字,对于GridEngine而言它们没有特别的意义,而其他默认的项目,如mem_free是有确切含义的。ram_free项的consumable值JOB的意义是ram_free资源是对每个任务指定的,而不是针对每个线程。这样对Kaldi而言更有用处。

接下来,你需要往GridEngine中添加并行环境smp。大部分GridEngine的管理员都会这样做,但是并没有被默认支持。这是一个非常简单的并行环境,GridEngine并不会做任何特别的事,它只是为你保留一定数目的CPU槽,这样当你执行qsub -pe smp 10 <your-script>时,就会有10个CPU槽可用,这对于多线程或多进程的任务是有帮助的。执行qconf -ap smp,并编辑slots项为999

pe_name smp slots 9999 ...

然后使用qconf -mq all.q,编辑pe_list项以添加smp。

pe_list make smp

这样就在all.q中添加了smp并行环境。

配置GridEngine(高级)

在这一部份,我们会介绍一些可能有帮助、但对于基本使用并不必需的小技巧。在CLSP集群中,我们编辑了qconf -mq all.q中的prolog域

prolog /var/lib/gridengine/default/common/prolog.sh

这一项的默认值是NONE。我们将这个脚本拷贝到每个节点上相同的目录中。这一步的作用是,如果任务脚本当前无法获取,管理节点会等待一段时间,因为如果脚本刚刚被编辑,需要给NFS一些时间完成同步。这个脚本的内容如下:

!/bin/bash function test_ok { if [ ! -z "$JOB_SCRIPT" ] && [ "$JOB_SCRIPT" != QLOGIN ] && [ "$JOB_SCRIPT" != QRLOGIN ]; then if [ ! -f "$JOB_SCRIPT" ]; then echo "$0: warning: no such file $JOB_SCRIPT, will wait" 1>&2 return 1; fi fi if [ ! -z "$SGE_STDERR_PATH" ]; then if [ ! -d "dirname $SGE_STDERR_PATH" ]; then echo "$0: warning: no such directory $JOB_SCRIPT, will wait." 1>&2 return 1; fi fi return 0; } if ! test_ok; then sleep 2; if ! test_ok; then sleep 4; if ! test_ok; then sleep 8; fi fi fi exit 0;

等待至多14秒,这对我们的NFS来说足够了,因为我们在NFS中设置了刷新缓冲目录的最长等待时间为acdirmax=8。

同时在队列配置中,我们设置rerun为TRUE

rerun TRUE

如果任务失败,它们会在qstat的输出中显示为Eqw状态,E表示出错了,通过运行qmod -cj <numeric-job-id>清除出错标记,你可以要求队列重新分配这些任务。或者如果你不想重新运行这些队列,可以用qmod -dj <numeric-job-id>0删除它们。将队列设置为允许重运行,可以避免从头开始。

除此以外,我们还对CLSP队列做了如下修改

rlogin_daemon /usr/sbin/sshd -i rlogin_command /usr/bin/ssh qlogin_daemon /usr/sbin/sshd -i qlogin_command /usr/share/gridengine/qlogin-wrapper rsh_daemon /usr/sbin/sshd -i rsh_command /usr/bin/ssh

这些项目原来的默认值是

qlogin_command builtin qlogin_daemon builtin rlogin_command builtin rlogin_daemon builtin rsh_command builtin rsh_daemon builtin

这么做的原因已经无从考证了,但是如果你的qlogin和qrsh出现故障时,可以试试这些配置。

配置GridEngine(添加节点)

在这一部分中,我们介绍如何在你的队列中添加节点。如上所述,你可以在新的节点上安装GridEngine

sudo apt-get install gridengine-client gridengine-exec

集群名默认,主控节点设为你配置为master的那个节点的主机名。

安装好并不意味着你的新节点已经添加到队列资源中。GridEngine将主机分为管理主机(administrative hosts)、执行主机(execution hosts)和提交主机(submit hosts)。你的新机器需要同时具有这三个角色。你可以通过qconf -sh,qconf -sel和qconf -ss查看这三类主机的列表。通过如下命令将新节点设置为管理主机和提交主机

qconf -ah <新节点的主机名> qconf -as <新节点的主机名>

用如下命令将新节点配置为执行主机

qconf -ae <新节点的主机名>

这一操作会打开一个编辑器,你可以将前面定义的ram_free和GPU项添加进去

complex_values ram_free=112G,gpu=1

到这里,你可能注意到了在命令行中存在不对称现象,一边是qconf -sh和qconf -ss,而另一边是qconf -sel。后者的"l"表示以列表为命令执行对象。这里的区别在于,管理节点和提交节点的列表中只包含主机,而执行节点的列表包含一系列相关信息,因此,对于执行节点用不同的数据结构加以区别。如果你想查看某个执行节点的详细信息,可以使用qconf -se <节点的主机名>。如果添加或者修改执行节点信息,则分别使用qconf -ae <节点的主机名>和qconf -me <节点的主机名>。这是GridEngine的通用格式。对于包含详细信息的资源,如队列,可以使用"l"结尾的指令查看资源的列表,如qconf -sql,或者用"a"和"m"指令进行资源的操作。

仅仅告知GridEngine执行节点的存在还不够,你得把它加到队列里,然后告诉队列这个节点可以分配多少个任务槽。首先要明确新节点的cpu核心数目:

grep proc /proc/cpuinfo | wc -l

假设是48,那么你可以用一个略小于这个数字的值,如40,作为任务槽的数目。使用qconf -mq all.q编辑队列资源,将新的节点添加到主机列表中,设置任务槽数目,举例如下

qname all.q hostlist gridnode1.research.acme.com,gridnode2.research.acme.com <省略若干行> slots 30,[gridnode1.research.acme.com=48],[gridnode1.research.acme.com=48] <省略若干行>

在slots项中,开头的30是一个默认值,如果不特别指定,你可以不必把节点添加到这一项。除了这种方法以外,你还可以用主机群的方式简化hostlist项的配置。方法就是,使用qconf -ahgrp @allhosts创建一个主机群,你也可以用过qconf -mhgrp @allhosts修改现有的主机群来添加你的新节点。如果使用这种方法,那么上面配置文件的第二行就应当写为

hostlist @allhosts

用哪种方法配置取决于你自己的选择,对于小型队列,直接写主机列表可能就够了。

用于显示GridEngine所有主机列表,以及每个主机属于哪个队列的指令是qhost -q,结果示例如下

qhost -q HOSTNAME ARCH NCPU LOAD MEMTOT MEMUSE SWAPTO SWAPUS ------------------------------------------------------------------------------- global - - - - - - - a01.clsp.jhu.edu lx26-amd64 24 12.46 126.2G 11.3G 86.6G 213.7M all.q BIP 0/6/20 a02.clsp.jhu.edu lx26-amd64 24 16.84 126.2G 12.4G 51.3G 164.5M all.q BIP 0/18/20 <省略若干行>

如果你在"BIP"的位置看见的是"E",那说明这个节点出现问题了。其他你不会想看到的标志是,"a"表示警告(通常表示节点的情况不太好),"u"标志状态无法获取,"d"表示这个节点被GridEngine管理员禁用了。有时候运行任务出现问题时,节点会出现"E"标志,这通常是由NFS或其他挂载的问题导致的。你可以清除错误标志

qmod -c all.q@a01

但是,如果节点真的存在严重问题,最好先修复它。这时候你可以禁用它

qmod -d all.q@a01

然后用qmod -e all.q@a01来恢复。

GridEngine出现问题的一种典型症状是当你觉得节点可用时,任务一直在等待。最简单的调试方法是用qstat查看任务标志,然后用qstat -j <任务标志>查看任务没有被执行的具体原因。

你可以用下面的指令查看所有用户提交的任务

qstat -u '*'

results matching ""

    No results matching ""