如何测量HPC集群作业全时段GPU平均利用率?求启停式工具方案
针对GPU作业启停式利用率统计的解决方案
以下是几种实用的实现思路和工具,完全适配你“随作业启停采样、支持提前终止并输出平均利用率”的需求:
一、基于nvidia-smi的自定义Bash脚本(轻量无依赖)
nvidia-smi本身虽没有直接的启停采样功能,但可以用简单的脚本封装实现,无需额外安装工具:
- 启动采样:运行以下脚本后台启动采样,自定义采样间隔(示例为1秒),数据会写入临时文件:
#!/bin/bash # 生成唯一临时文件名,避免冲突 TEMP_FILE="/tmp/gpu_util_$(date +%Y%m%d_%H%M%S)_$$.tmp" # 后台循环采样GPU利用率 nohup bash -c 'while true; do nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits >> '"$TEMP_FILE"' sleep 1 # 可修改为你需要的采样间隔,比如5秒 done' & SAMPLING_PID=$! echo "GPU采样已启动,PID: $SAMPLING_PID,数据文件: $TEMP_FILE"
- 停止采样并计算平均值:作业结束或需要提前终止时,执行以下命令:
# 终止采样进程 kill $SAMPLING_PID # 计算并输出平均利用率 awk '{sum+=$1; count++} END { if(count>0) printf "平均GPU利用率: %.2f%%\n", sum/count; else print "无有效采样数据" }' $TEMP_FILE # 清理临时文件(可选) rm $TEMP_FILE
二、使用nvtop工具(可视化+数据导出)
nvtop是一款类似htop的GPU监控工具,支持命令行模式导出采样数据,操作更直观:
安装nvtop:大部分HPC集群可通过包管理器安装(如
apt install nvtop或yum install nvtop),源码编译也很简单。启动采样:后台启动nvtop并导出CSV格式的采样数据:
nvtop --export-csv gpu_util_monitor.csv --delay 1 & SAMPLING_PID=$! echo "nvtop采样已启动,PID: $SAMPLING_PID,数据文件: gpu_util_monitor.csv"
- 终止并计算:停止采样后,用脚本分析CSV文件(提取GPU利用率列计算平均):
kill $SAMPLING_PID # 假设CSV中第4列是GPU利用率(不同版本可能有差异,可先查看文件确认) awk -F ',' 'NR>1 {sum+=$4; count++} END { if(count>0) printf "平均GPU利用率: %.2f%%\n", sum/count; else print "无有效采样数据" }' gpu_util_monitor.csv
三、基于Python+pynvml的灵活方案(适合复杂场景)
如果需要多GPU统计、自定义逻辑扩展,用Python调用pynvml库是最优选择:
安装依赖:
pip install pynvml采样脚本示例:
import time import signal import pynvml from statistics import mean # 初始化NVML pynvml.nvmlInit() # 获取所有GPU的句柄(支持多GPU) gpu_count = pynvml.nvmlDeviceGetCount() gpu_handles = [pynvml.nvmlDeviceGetHandleByIndex(i) for i in range(gpu_count)] # 存储每个GPU的利用率数据 util_records = [[] for _ in range(gpu_count)] running = True # 处理终止信号(Ctrl+C或kill命令) def stop_sampling(sig, frame): global running running = False print("\n正在停止采样并计算结果...") signal.signal(signal.SIGINT, stop_sampling) signal.signal(signal.SIGTERM, stop_sampling) print(f"开始采样{gpu_count}块GPU的利用率...") try: while running: for idx, handle in enumerate(gpu_handles): util = pynvml.nvmlDeviceGetUtilizationRates(handle).gpu util_records[idx].append(util) time.sleep(1) # 采样间隔 finally: pynvml.nvmlShutdown() # 输出每个GPU的平均利用率 for idx, records in enumerate(util_records): if records: avg = mean(records) print(f"GPU {idx} 平均利用率: {avg:.2f}%") else: print(f"GPU {idx} 无采样数据")
额外优化建议
- 集成到集群调度系统:如果用SLURM等调度器,可将采样脚本配置为作业的
--wrap参数,或在作业脚本中自动启动/停止采样,结果直接写入作业日志。 - 采样间隔调整:无需固定1秒,根据作业类型调整(比如计算密集型作业用2-5秒间隔,减少系统开销)。
- 数据持久化:如果需要长期留存采样数据,可将临时文件存储到集群共享存储,而非节点本地磁盘。
内容的提问来源于stack exchange,提问作者William Allcock
相关产品推荐
相关产品推荐

