news 2026/10/14 17:57:50

TORQUE 6.1.1.1 集群作业调度器安装配置与避坑实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TORQUE 6.1.1.1 集群作业调度器安装配置与避坑实践

简介:Torque 6.1.1.1 源码包,面向需要搭建、维护高性能计算集群的系统管理员与运维工程师。Torque 集群由一个管理节点和多个计算节点组成,管理节点运行 pbs_server 进程,计算节点运行 pbs_mom 进程,客户端命令可部署于任意主机,整套机制用于作业提交、排队与调度。该源码包共包含 2000 个文件,以 C 源文件、头文件、Makefile 构建脚本、PO 翻译文件及 Shell 脚本为主,涵盖作业执行、节点管理、资源调度等核心模块的实现代码,压缩包体积仅 13.45MB,便于下载和二次编译。已有 835 人学习使用。读者既可利用源码完成 Torque 服务器的编译安装与集群部署,也可通过阅读 start_exec、mom_comm、mom_main 等模块加深对 PBS 调度机制的理解,还可基于现有接口进行功能扩展或定制,适合具备一定 Linux 基础并希望深入掌握集群作业管理系统的人员。

1. TORQUE 6.1.1.1:集群作业调度里绕不开的那个调度器

当你在 50 台机器上跑参数扫描,每台机器各跑 8 个任务,结果某个节点内存被打爆、其他节点却闲着——这种局面我见过太多次。TORQUE 6.1.1.1 这份源码包解决的就是这件事:它是集群资源管理器的经典开源实现,负责把作业塞到空闲资源上,排队、限资源、定优先级。适合正在搭小型 HPC 环境或实验室集群的工程师,也适合想弄懂 PBS 类调度器底层行为的人。源码包编一次就能铺开用,调度策略、队列配置、作业脚本全部自己掌控,不依赖任何商业调度器。

2. 编译之前的版本选型:为什么是 6.1.1.1 而不是更新或更旧的 Tag

2.1 TORQUE 版本线梳理:6.x 系列到底改了什么

TORQUE 的版本演进不是线性的。4.x 时代功能已经稳定,5.x 更像过渡版,而 6.x 在底层通信、内存管理、调度器行为上都有明显变化。6.1.1.1 这个版本号值得拿出来单独说的点,在于它把调度器对作业状态的处理改得更严谨了:作业结束后的资源回收不再有延迟,节点状态上报间隔也做了收敛。

我从 4.2.10 迁移到 6.1.1.1 时比较明显的体感是,pbs_sched 在高并发下出现偶发崩溃的次数比旧版少得多。6.x 的调度器把每次调度决策写成日志,排错的时候不用再靠猜。如果你是从 PBS Pro 或 Slurm 转过来的,TORQUE 的作业生命周期模型基本还是 PBS 那一套:作业被 qsub 提交后进入队列,pbs_sched 负责决策,pbs_mom 在计算节点上执行。6.1.1.1 的价值在于,它修正了一批 6.1.0 里就已出现但没处理干净的边界情况。

对于自己维护集群的团队来说,选版本看的不只是新功能,而是 bug 修复的收敛度。6.1.1.1 在社区 issue 列表里相对干净,没有跨大版本的遗留问题。而且它对普通 x86_64 平台的兼容性很好,不需要为特定 CPU 指令集打补丁,若用在 InfiniBand 环境里,配合 OpenMPI 跑并行任务,稳定性也比 5.x 高得多。

2.2 从 tarball 到可执行文件:编译依赖与配置参数拆解

源码包拿到手之后先别急着 configure,依赖没装齐会浪费一轮编译时间。TORQUE 6.1.1.1 的依赖不算多,但在较干净的服务器上很容易缺。

# CentOS / Rocky Linux 系 yum install -y libxml2-devel openssl-devel gcc gcc-c++ make expat-devel # Debian / Ubuntu 系 apt-get install -y libxml2-dev libssl-dev gcc g++ make

缺 libxml2 会直接导致 configure 在检测 XML 支持时卡住,而 TORQUE 的调度器配置和作业队列状态都依赖 XML 解析库,所以这个包必须提前装好。openssl 不是 TORQUE 运行的必要依赖,但如果你之后要配 TLS 加密通信,编译期不带 --with-ssl,后面补起来要重新编译一遍整个安装,非常折磨人。

依赖装完后,解压源码包并进入 configure 阶段:

tar -xzf torque-6.1.1.1.tar.gz cd torque-6.1.1.1 ./configure --prefix=/usr/local/torque \ --with-scp \ --with-ssl \ --without-tcl

这里的三个参数含义分别是:--prefix 指定安装目录,我习惯把 TORQUE 单独放在 /usr/local/torque,而不是散落在 /usr/local/bin 里,这样后续升级或卸载都干净利落;--with-scp 是让 pbs_mom 与 pbs_server 之间的文件传输走 scp,而不是默认的 rcp,后者在很多新系统上根本没有;--without-tcl 表示不编译 Tcl 接口,如果你不依赖 Tcl/Tk 的图形化管理界面,关掉能省掉不少编译时间。

configure 完成后执行 make 和 make install,这一步的输出很长,别急着跳过。要看最后几行是否出现 "Torque Installation Complete" 之类的提示,不是整个流程跑完就代表装好了,中间某个模块编译失败但 make 可能并不会立即退出。

make -j$(nproc) make install

装完之后记得把安装目录下的 bin 和 sbin 加进 PATH。这个步骤经常被忽略,导致后续执行 qsub 时提示 command not found。一般会写进 /etc/profile.d/torque.sh,内容就一行 export PATH=/usr/local/torque/bin:/usr/local/torque/sbin:$PATH。配好之后 source 一下,再跑 qsub --version 确认是否生效。

3. 初始化服务与节点纳管:把调度器真正跑起来

3.1 服务端初始化流程:pbs_server、pbs_sched、pbs_mom 三个角色的启动顺序

TORQUE 安装完成后,系统里会出现三个核心服务:pbs_server 管理所有队列与调度状态,pbs_sched 做具体分配决策,pbs_mom 跑在计算节点上执行作业。很多人一上来就三个全部启动,结果服务起来后节点显示 down,或者作业一直排队不运行。

正确的初始化顺序是先配置数据库目录,再启动 pbs_server,然后通过 qmgr 创建队列,最后才启动 pbs_sched 和 pbs_mom。

# 创建 TORQUE 运行时所需的目录 mkdir -p /var/spool/torque mkdir -p /var/spool/torque/server_priv mkdir -p /var/spool/torque/mom_priv # 设置服务端和调度器的 spool echo "localhost" > /var/spool/torque/server_name /usr/local/torque/sbin/pbs_server -t create

这里有个非常容易踩的坑是 server_name 文件里的主机名必须是完整的机器 hostname,而且所在服务器上的 /etc/hosts 里必须有对应解析。很多集群里机器名写成 short name,比如 node1 而不是 node1.cluster.local,pbs_server 启动时会自动把名字补全成 FQDN 格式,导致后面 qnodes 看到的节点名跟你配置的不一样。

pbs_server -t create 只在首次初始化时执行,如果 server_db 目录里已经有旧数据,执行它会提示 database already exists。此时不要强制覆盖,除非你确定不再需要旧队列配置。

3.2 队列和节点配置:qmgr 命令的完整用法

队列配置用 qmgr 命令,以交互模式或 -c 参数执行。TORQUE 6.x 的 qmgr 语法比旧版严格许多,队列名、属性名大小写敏感,写错任何一个词都不会报错,但配置不会生效。

/usr/local/torque/sbin/qmgr -c "create queue batch queue_type=execution" /usr/local/torque/sbin/qmgr -c "set queue batch enabled=true" /usr/local/torque/sbin/qmgr -c "set queue batch started=true" /usr/local/torque/sbin/qmgr -c "set server scheduling=true"

queue_type=execution这一项是必需的,否则队列建出来之后作业往里面投,调度器根本不会去扫它。enabled 和 started 两个属性分别控制队列能否接收新作业、能否运行已排队的作业。刚创建出来的执行队列默认都是 false,必须显式打开。set server scheduling=true是总开关,如果这个属性是 false,整个集群的调度器都不会工作,作业进来之后永远处于 Q 状态。

节点列表写在 /var/spool/torque/server_priv/nodes 文件里,每行一个节点:

node01 np=8 node02 np=8 node03 np=16

np 参数声明该节点可用的处理器核心数,TORQUE 会拿这个值去匹配作业请求里的 ppn。6.x 版本对这个文件的读取是动态的,改动后不需要重启 pbs_server,但需要执行qnodes -o触发一次刷新。

3.3 验证安装结果:从 qnodes 到 pbsnodes 的信息对比

配置完成后需要一套验证流程来确认系统真的可用,而不是只看服务进程存活。先看服务进程,然后对比节点状态和队列状态:

ps aux | grep pbs_ | grep -v grep qnodes -l qstat -q

注意 qnodes 和 pbsnodes 输出的差异。qnodes -l 只显示节点是否处于 free、job-exclusive 或 down 状态,而 pbsnodes -a 会给出每个节点的 CPU 使用、内存余量、作业列表等详细数据。节点状态为 down 时优先检查 pbs_mom 进程是否崩溃,以及该节点到服务端的通信端口是否被防火墙挡掉。

TORQUE 在 6.x 里新增了一个状态列 state,在 qnodes 中显示为 free 意味着节点正常。如果看到 state = down,而 pbs_mom 进程明明活着,大概率是节点名解析失败。在计算节点上执行pbs_mom -d查看调试输出,看到 "cannot resolve hostname" 就是这个问题。

我一般会跑一个最简作业来验证整条链路正常。创建一个 test.pbs 脚本,内容是sleep 10; echo done,提交后等它跑完:

cat > /tmp/test.pbs << 'EOF' #!/bin/bash #PBS -N smoke_test #PBS -l nodes=1:ppn=1 #PBS -l walltime=00:05:00 #PBS -q batch sleep 10 echo "job finished on $(hostname)" EOF qsub /tmp/test.pbs

提交后约一秒钟内,qstat 中该作业应显示 R(Running),10 秒后变为 C(Completed)。如果一直停在 Q 状态,调度器没有正确匹配到可用的资源,优先检查上面提到的 scheduling 开关和节点状态。

4. 作业提交与资源限制:qsub 参数怎么设才算合理

4.1 作业脚本结构:PBS 指令、Shell 指令与全局变量的边界

TORQUE 的作业本质上是一个 Shell 脚本,前几行以 #PBS 注释形式携带调度指令,#PBS 行之后的普通 Bash 命令才是实际执行体。这个结构很多人理解得很模糊,导致直接把环境变量写在 #PBS 行里,结果作业跑起来时变量是空的。

#!/bin/bash #PBS -N parallel_job #PBS -l nodes=2:ppn=4 #PBS -l mem=8gb #PBS -l walltime=02:00:00 #PBS -q batch #PBS -o /home/user/job_logs/ #PBS -e /home/user/job_logs/ export OMP_NUM_THREADS=4 module load intelmpi mpirun -np 8 ./simulation input.dat

#PBS 指令与 Shell 指令的边界在于:#PBS 作用在调度层,决定作业拿到多少资源;而 export 和 module load 作用在执行层,决定作业进程如何利用这些资源。-l 后面跟资源规格,mem 的单位直接写 gb、mb 即可。-o 和 -e 分别指定 stdout 和 stderr 的输出目录。

有个老手也容易混淆的点:-o 参数写的是目录而不是文件名,TORQUE 会自动在该目录下生成以作业 ID 命名的输出文件,格式为 jobname.o 。如果你把 -o 写成了 /path/to/file.txt,那 TORQUE 不会创建这个文件,输出会丢到默认位置,排错时找不到日志会非常难受。

4.2 资源规格与调度策略:nodes、ppn、mem、walltime 的估算逻辑

资源请求写多少,直接决定你的作业要排队多久。nodes=2:ppn=4 表示作业划分到 2 个节点上,每个节点分配 4 个核心。TORQUE 把这个映射关系交付给 pbs_mom,后者在节点上为任务创建 cpuset 或绑定处理器。

walltime 是很多新手最容易拍脑袋写的参数,但它直接影响调度器能不能把你的作业塞进某个时间窗口。如果你的 walltime 写了 48:00:00,但实际运行只要 2 小时,调度器会为了找一个能连续预留 48 小时的窗口而让你等很久。反过来,walltime 写得比实际所需短,作业会在超时后被 pbs_mom 强制杀掉。

#!/bin/bash #PBS -N memory_test #PBS -l nodes=1:ppn=8 #PBS -l mem=16gb #PBS -l walltime=01:00:00 cd $PBS_O_WORKDIR ./memory_intensive_app

如果你的应用内存需求波动大,mem 参数留 1.5 倍余量比较稳妥。但注意 TORQUE 的 mem 限制是整节点计算的,如果一台节点内存 32GB,你申请 mem=16gb,调度器会允许另一个作业也申请 16GB 放到同一节点,如果两个作业的实际内存峰值都到了 17GB,节点 OOM,两个作业一起被杀。这种相互踩踏的问题不太好排查,常见做法是把 mem 申请到 24GB,利用资源冗余留出缓冲。

作业脚本里没有显式指定队列时,qsub 会使用 default_q 属性指向的队列。用 qmgrset server default_q=batch设置默认队列,否则作业会被拒绝,提示报错的信息是 "Request invalid or unauthorized"。这个报错在 TORQUE 6.x 里极具误导性,它并不代表你没有权限,而是说队列没有配置 default_q,或者作业请求的资源超过了节点的最大规格。

4.3 排队与优先级:为什么你的作业永远在别的作业后面

调度器默认按作业提交时间顺序处理,但 TORQUE 的优先级参数会打乱这个顺序。qsub 的 -p 参数可以设置作业优先级,取值范围 -1024 到 1023,默认 0。设为正数可以让作业插队,但滥用的话低优先级作业永远跑不上。

有一种很聪明的调度策略是给短作业提高优先级。因为调度器的目标是集群吞吐量最大化,短作业快速完成可以释放资源给后续作业。常见做法是脚本里根据作业预期运行时长自动设置 -p:

#!/bin/bash #PBS -N smart_priority #PBS -l nodes=1:ppn=4 #PBS -l walltime=00:30:00 #PBS -q batch #PBS -p 100 ./short_task

-p 100 不是随便写的,在 TORQUE 的调度器里,优先级差值达到 50 以上时,新作业就会显著抢在旧作业前面。如果你的集群里既有跑 12 小时的仿真,又有跑 20 分钟的测试任务,给测试任务设 -p 80 到 100 是比较健康的做法。但优先级不是越大越好,如果有人把生产作业也设成高优先级,调度器的公平性就被破坏了。

调度器还有一个 fairshare 机制,在多用户共享集群时会根据每个用户的历史资源使用量动态调整优先级。6.1.1.1 里 fairshare 默认关闭,需要用 qmgr 开启,配置完会按照用户维度重新计算队列顺序。

5. 避坑:TORQUE 6.1.1.1 安装与调度中的六个常见问题

5.1 编译时提示找不到 libxml2

编译 configure 阶段报错 "libxml2 not found",但系统明明已经装过 libxml2-devel。原因是 64 位系统上 configure 查找库文件的路径是 /usr/lib64,而某些服务器会把 libxml2 装到 /usr/lib 下。

解决方式是手动指定库文件路径:

./configure --prefix=/usr/local/torque \ --with-xml=/usr/lib64 \ --with-ssl

再把 PKG_CONFIG_PATH 指向正确目录,再跑一次 configure 就不会检测失败。

5.2 pbs_server 启动后立刻退出,日志里没有任何异常

pbs_server 进程显示 active,但两秒后就消失。查看 /var/spool/torque/server_logs 发现日志为空。遇到这种情况先确认是不是有旧的 PBS 或其他调度器占用了 15001 端口。集群里同时装过 Slurm 或 PBS Pro 时,端口冲突概率极高。

检查端口占用:

netstat -tlnp | grep 15001

如果端口被其他进程占用,找到该进程并停掉,或者修改 TORQUE 的服务端口配置。我处理过一台机器同时在跑 PBS Pro 与 TORQUE 的情况,两个服务都试图监听 15001,后启动的那个一启动就被系统踢掉。

5.3 qsub 提交作业提示 "Request invalid or unauthorized"

作业脚本语法完全没问,队列也已经 enabled + started,但提交就是报这个错。这个问题我会优先检查提交作业的用户是否为 root,TORQUE 默认配置拒绝 root 直接提交作业,需要把 root 加入允许列表:

qring -c "set server operators = root@*" qmgr -c "set server managers = root@*"

另一个可能原因是作业请求的资源超出了任何节点的规格,比如节点全是 8 核,但作业请求 nodes=1:ppn=16,TORQUE 会把这个请求当作非法资源请求直接拒绝,报同样的错误信息。

5.4 作业一直 Q 状态,节点显示 free 却永远不调度

节点状态正常,队列配置也正确,作业就是不运行。这种问题先看调度器是否真的在跑:ps aux | grep pbs_sched。如果 pbs_sched 没有运行,作业将无限期排队。

排除了进程问题后,查看调度器日志,常见的隐藏原因是节点被标记为 "offline"。在别的管理端曾经执行过qmgr -c "set node node01 state=offline",但没有人撤销这个设置。利用pbsnodes -o node01把节点重新设为 online 状态。

5.5 作业运行一半被 Kill,dmesg 里没有 OOM 记录

作业被终止且没有 OOM 记录,大概率是 walltime 到了。很多人写 walltime 时只算主程序运行时间,但没算 MPI 启动时间、初始化时间、数据预处理时间。当作业的发起脚本被 pbs_mom 打断时,TORQUE 日志里会出现 "job killed by walltime" 字样。

排查方式是在作业脚本开头加一行date输出,对比 qstat -f 里的 start_time 和作业实际完成时间,就能估算出 init 阶段消耗了多少时间。

5.6 重启节点后 pbs_mom 不自动恢复

计算节点重启后 pbs_mom 服务如果没有配置开机自启,该节点会处于 down 状态。TORQUE 6.1.1.1 自带的 init 脚本对 systemd 的兼容性一般,建议直接写成 systemd service:

cat > /etc/systemd/system/pbs_mom.service << 'EOF' [Unit] Description=TORQUE MOM After=network.target [Service] Type=forking ExecStart=/usr/local/torque/sbin/pbs_mom ExecStop=/usr/local/torque/sbin/pbs_mom -shutdown PIDFile=/var/run/pbs_mom.pid [Install] WantedBy=multi-user.target EOF

注意类型必须写 forking,因为 pbs_mom 启动后自身会 daemonize,写成 simple 会导致 systemd 认为服务启动失败。配好之后 enable 该服务就行。

6. 从 qstat 到深度调度:把集群调度效率再提一档的验证技巧和习惯

最后一个技巧,也是我建议你在 TORQUE 6.1.1.1 上最值得深入做的一件事:用调度日志做集群利用率的复盘。TORQUE 的调度器每次决策都会在 /var/spool/torque/server_logs 里记录完整上下文,包括资源匹配算法遍历了多少个节点、为什么跳过某些节点、可分配的空闲资源总量。理论上你可以从日志重建出每一次决策的全过程,这比使用第三方监控工具还要精准。

我维护集群时的固定动作是写一个脚本定时拉取调度器的统计摘要,放到独立目录里做趋势分析:

#!/bin/bash # 从调度日志中提取资源利用率核心指标 LOG_DIR=/var/spool/torque/server_logs OUT=/home/admin/torque_stats mkdir -p $OUT for log in $(ls $LOG_DIR | grep sched); do echo "=== $log ===" >> $OUT/schedule_summary.txt grep "attempting to schedule" $LOG_DIR/$log | wc -l >> $OUT/schedule_count.txt grep "job scheduled" $LOG_DIR/$log | wc -l >> $OUT/scheduled_jobs.txt grep "no available resources" $LOG_DIR/$log | wc -l >> $OUT/no_resource_events.txt done

这个脚本不负责给出结论,真正的价值在对比三组数字之间的关系。如果 no_resource_events 占 schedule_count 比例超过三成,说明节点资源请求和实际硬件能力存在系统性错配,要么限制某些用户申请超规格资源,要么增加节点核心数配置。

还有一个实际验证节点是否有隐藏问题的技巧,利用 qstat -f 查看作业的 resource_usage 字段。许多作业跑完了之后你才从 resource_usage 看到它实际只用了 1.2GB 内存,但申请了 8GB。这类作业如果数量多,可以引导用户把 mem 参数收紧,节点上就能挤出更多调度窗口。

从那以后我每次给集群调优都强制走一遍:先看调度日志数据,再对照资源申请表,最后才动手改队列参数。按这套顺序做,大多数调度问题在改动配置之前就能定位到真正的根因,希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 17:57:30

Nacos 1.2.0整合Seata 1.2.0配置指南:从注册中心到分布式事务回滚

1. 为什么到现在还有人折腾Nacos 1.2.0 Seata 1.2.0这套组合先说结论&#xff1a;如果你手头维护的是2020年前后立项的老项目&#xff0c;大概率跑的还是Nacos 1.x Seata 1.x这套组合。我接手过一个业务系统&#xff0c;注册中心是Nacos 1.2.0&#xff0c;分布式事务一直用的…

作者头像 李华
网站建设 2026/10/14 17:57:29

用Python解析PTA理论考docx,将Word题库转为刷题系统

简介&#xff1a;PTA理论考部分.docx是一份面向PTA平台C语言理论考整理的复习资料&#xff0c;主要收录HW02、HW03等章节的判断题与少量选择题&#xff0c;每题均附正确答案&#xff0c;并对涉及的知识点进行展开说明&#xff0c;而不是简单给出对错。解析涵盖编译预处理命令的…

作者头像 李华
网站建设 2026/10/14 17:57:09

激光超声无损检测技术详解:非接触方案、热弹性机理与干涉测量

简介&#xff1a;《激光超声技术及其在无损检测中的应用概况》是以PDF格式提供的学术论文&#xff0c;面向无损检测、超声应用及激光技术领域的工程师、研究人员和高校学生&#xff0c;系统梳理了激光超声检测技术的原理与应用现状。文中从电磁理论出发&#xff0c;推导了固体中…

作者头像 李华
网站建设 2026/10/14 17:56:49

三角网格拉普拉斯算子:余切权重与矩阵构建实战指南

1. 从一个“跑不起来”的网格说起如果你正在做几何处理、三维重建、形状分析或者物理仿真&#xff0c;大概率绕不开一个东西&#xff1a;三角网格上的拉普拉斯算子。我第一次接触这个概念是在做一个网格平滑的小工具时&#xff0c;当时想对扫描得到的模型做去噪&#xff0c;结果…

作者头像 李华
网站建设 2026/10/14 17:56:34

Ant Design Pro V4/V5 安装实战:Yarn 与 Block 机制全解析

搞前端后台项目的朋友应该都绕不开 Ant Design Pro 这个名字。最近我把 Ant Design Pro V4 和 V5 完整地各装了一遍&#xff0c;顺便把 Block 的接入方式研究了个透。这篇记录先写安装部分&#xff1a;怎么用 Yarn 把 ADP V4、V5 装好&#xff0c;以及 V4 里那套 Block 机制怎么…

作者头像 李华
网站建设 2026/10/14 17:56:25

用RTL在FPGA上实现深度学习处理器:脉动阵列与指令集设计实践

说到 Deep-Learning Processor&#xff0c;很多人第一反应是英伟达的 GPU 或者手机上那颗 NPU。但我做的这个项目&#xff0c;并不是那类工业级大芯片&#xff0c;而是一个仍在持续更新中的、偏研究和学习向的深度学习处理器。它面向的是边缘端常见的 CNN 推理任务&#xff0c;…

作者头像 李华