在服务器上提交任务前,通常需要关注一下有多少计算资源,LSF 计算节点还有多少可用核,GPU 节点上又有哪些卡处在空闲状态。

这些信息都在 bjobslshostslsloadbhostsnvidia-smips 里。单条命令都不难,但信息分散在不同输出中,每次都要来回查询、对齐,再做判断。好在这些基础命令支持按字段查询,可以继续整理成更符合自己习惯的显示方式。

我把这些基础命令整理成了两个 Bash 资源查看工具:lsf-nodes 汇总 CPU 计算节点,list-gpu 汇总 GPU 和计算进程,并设置了 lflg 两个短别名。

Summary

本文介绍如何整理 bjobsnvidia-smi 等基础命令,形成更顺手的 LSF 与 GPU 资源查看工具。

为什么要重新整理这些基础命令

LSF 已经提供了完整的查询命令。bjobs 可以查看作业,lshosts 提供节点的静态资源,lsload 返回当前负载,bhosts 则给出调度系统看到的主机状态。

然而,默认输出并不完全满足我的需要。例如,bjobs 会压缩 JOB NAME 栏,名称较长的任务总是显示不全;nvidia-smi 在 tmux 半屏中又会因为宽度不足而自动换行,导致表格错位,难以阅读。

整理这些命令时,我只保留日常判断资源占用所需的字段,再统一排序、配色和显示宽度。下面会具体介绍实现方式,读者可以据此调整自己的资源查看工具,不必原样复刻。

lsf-nodes:把节点状态压成一行

使用完整命令:

lsf-nodes

或别名 lf

alias lf='$DIRECTORY/soft/bin/lsf-nodes'

输出会按节点名自然排序,使用效果如下:

每个字段代表什么

ncpu 来自 lshosts,表示该节点在 LSF 主机信息中的 CPU 数量。free 由“总核数减去正在运行作业占用的执行槽位”得到。

jobs 统计当前分配到该节点的 RUN 作业条目。它方便判断节点上同时跑着几个任务,但不包含等待中的作业,也不是历史作业数量。

ut 取自 lsload 的 CPU 利用率。它展示的是“这台机器现在有多忙”。脚本把低于 60% 显示为绿色,60% 到 89% 显示为黄色,达到 90% 后显示为红色。

mem 不是 LSF 作业申请的内存,也不是某个作业的独占用量。脚本将 lshosts 的总内存与 lsload 的可用内存统一换算为 GiB,再估算整台节点的内存占用比例:

内存占用率 = (总内存 - 可用内存) / 总内存

它支持 KMGT 四种单位。颜色阈值和 CPU 一样,方便快速发现内存压力较高的节点。

脚本如何合并数据

lsf-nodes 依次执行四次只读查询:

bjobs -w -u all  →  每个节点的运行作业、已分配槽位
lshosts -w       →  CPU 数量、总内存
lsload           →  当前状态、CPU 利用率、可用内存
bhosts -w        →  调度器主机状态

每条命令的必要字段先写入临时文件,随后交给一段 awk 按主机名合并。脚本退出时,trap 会清理这些临时文件。合并结果先按节点名排序,最后再加入 ANSI 颜色,避免颜色控制字符干扰排序。

状态颜色也有单独规则:ok 为绿色,unavailunreachdown 一类异常状态为红色,closed_* 等其他状态显示为黄色。剩余槽位小于或等于 0 时,free 会变红。

完整脚本和使用说明放在文末的文件入口。

list-gpu:用同样的思路整理 GPU 信息

使用 list-gpulg 查看 GPU 节点:

alias lg='$DIRECTORY/soft/bin/list-gpu'

脚本先检查当前机器能否找到 nvidia-smi。如果已经位于 GPU 节点,就在本机查询;如果是在没有 NVIDIA 驱动的登录节点,它会通过 SSH 转到预设 GPU 节点,并在共享文件系统中再次执行。

每次运行都会获得以下两个部分的内容。

第一部分:每张 GPU 的即时状态

脚本通过 NVIDIA 官方文档中的 nvidia-smi --query-gpu 选择性查询以下字段:

  • GPU 序号;
  • GPU 利用率;
  • 已用显存与总显存;
  • 温度。

显示格式大致如下:

其中显存百分比由已用显存除以总显存计算。这里的颜色主要用于区分字段:GPU 序号、利用率、显存和温度使用不同颜色,并没有像 lsf-nodes 那样设置告警阈值。看到 100% 利用率时,仍然要读具体数字。

第二部分:这张卡上到底在跑什么

GPU 概览之后,脚本继续使用 nvidia-smi --query-compute-apps 读取计算进程的 PID、显存和 GPU UUID。

之所以先拿 UUID,是因为进程查询返回的设备标识并不适合直接阅读。脚本会额外建立一张“GPU UUID 到序号”的映射,再把每个进程还原到 GPU 0、GPU 1 这样的编号。

随后,ps 根据 PID 补充三个信息:

  • 进程所属用户;
  • 已运行时间;
  • 完整启动命令。

输出格式如下:

显示完整命令对于机器学习任务很有用。如果只显示 python 往往无法判断具体实验,补上脚本名和参数以后,重复启动、配置用错和忘记停止的旧任务会更容易识别。

命令太长时,脚本会把显示长度限制在 110 个字符左右,保留开头和结尾。这样既能看到解释器与脚本名,也尽量留下末尾的配置参数。常见的 DataLoader 子进程和 Jupyter kernel 会折叠成简短标签,减少一批重复长命令对屏幕的占用。

获取脚本

完整脚本和使用说明放在下面两个文件页。下载前请先阅读说明,并根据服务器环境修改节点前缀、GPU 主机名和共享路径。

写在最后

lsf-nodeslist-gpu 都只有一百行左右。它们没有引入新的监控服务,只是把几条基础命令返回的信息整理成了两张终端表格。

对这种命令行工具,我最需要的就是查询要足够快,字段要能直接支持下一步判断,脚本失败时也不会影响作业或系统状态。

如果你也经常在登录节点、CPU 集群和 GPU 节点之间切换,可以从自己常用的基础命令出发,把需要反复查看的字段整理成一套顺手的资源查看工具。

相关阅读