从零到一:用脚本精准获取显卡显存(VRAM)的终极指南(含Python/Shell实战)
📚 目录导读(Table of Contents)
- 为什么需要脚本获取显存? —— 监控、调优与自动化场景解析
- 底层原理:显存信息藏在哪里? —— 深入理解GPU查询接口(NVML/Sysfs/Windows WMI)
- Windows平台(NVIDIA/AMD/Intel)脚本获取 —— 利用
nvidia-smi与PowerShell/WMI - Linux平台(通用)脚本获取 —— 解析
/proc/driver/nvidia、rocm-smi与intel_gpu_top - 跨平台Python终极方案 —— 使用
pynvml与psutil封装优雅截图 - 常见问题FAQ(附带代码排查) —— 权限不足、多GPU识别、虚拟化环境下的坑
- 脚本之外,显存监控的未来趋势
✍️ 文章正文
为什么需要脚本获取显存?
在深度学习训练、视频渲染或大规模科学计算中,显存(VRAM)是比CPU内存更稀缺的资源,当您半夜跑模型时,程序因CUDA Out Of Memory崩溃,却不知道是哪个进程吃满了显存——这时候,一条简单的脚本命令就能让您即时定位“显存杀手”。

更重要的是,对于运维自动化(如K8s调度GPU Pod)或性能调优(如监控温度与频率联动),手动打开任务管理器/htop已完全不够用,脚本化获取显存是构建监控大盘、实现动态扩缩容的基础。
底层原理:显存信息藏在哪里?
- NVIDIA GPU:官方驱动自带
NVML(NVIDIA Management Library),命令行工具为nvidia-smi,所有Linux发行版和Windows均支持。 - AMD GPU:Linux下依赖
sysfs接口(位于/sys/class/drm/card*/device/mem_info_vram_total)或rocm-smi工具;Windows可调用WMI类Win32_VideoController的AdapterRAM属性(虽不精确但可用)。 - Intel核显:Linux下推荐
intel_gpu_top或/sys/class/drm/card0/gt_cur_freq_mhz;Windows用dxdiag查询不直观,脚本可依赖wmic path win32_VideoController get AdapterRAM。
核心思想:所有脚本的本质都是解析命令行输出或读取内核暴露的文件描述符。
实战一:Windows平台脚本获取(一网打尽)
1 纯CMD一行流(适合批处理)
@echo off nvidia-smi --query-gpu=name,memory.total,memory.used,memory.free --format=csv,noheader,nounits
若为AMD显卡,使用PowerShell:
Get-CimInstance -ClassName Win32_VideoController | Select-Object Name, AdapterRAM
注意:AdapterRAM是32位值,超过4GB显存会溢出(显示错误值),需改查注册表:
(Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\0000").HardwareInformation.qwMemorySize
2 进阶:定时记录到日志(任务计划程序配合)
$loop = $true
while($loop){
$mem = nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits
Add-Content "C:\gpu_log.txt" "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $mem MB"
Start-Sleep -Seconds 5
}
问答Q1:为什么我的Windows脚本总是权限不足? 答:
nvidia-smi需要管理员权限读取NVML驱动接口,请右键“以管理员身份运行”命令提示符,或在任务计划程序中勾选“使用最高权限运行”。
实战二:Linux平台脚本获取(极致简洁)
1 NVIDIA用户(最常用)
#!/bin/bash # 一行获取总显存与已用显存(单位MiB) nvidia-smi --query-gpu=memory.total,memory.used,memory.free --format=csv
解析多GPU:循环遍历所有索引
for i in $(seq 0 $(nvidia-smi -L | wc -l)); do nvidia-smi -i $i --query-gpu=memory.used --format=csv,noheader,nounits done
2 AMD用户(避免安装额外工具)
# 直接读取sysfs,速度极快
VENDOR=$(lspci | grep VGA | awk '{print $NF}')
if [[ $VENDOR =~ "AMD" ]]; then
total=$(cat /sys/class/drm/card0/device/mem_info_vram_total)
used=$(cat /sys/class/drm/card0/device/mem_info_vram_used)
echo "Total: $((total/1024/1024)) MB, Used: $((used/1024/1024)) MB"
fi
3 集成监控脚本(配合cron定时任务)
*/5 * * * * /usr/bin/python3 /opt/gpu_watch.py >> /var/log/gpu_mem.log 2>&1
问答Q2:在Docker容器中运行
nvidia-smi报错couldn't find libnvidia-ml.so怎么办? 答:必须挂载宿主的驱动目录,运行容器时添加参数:-v /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1:/usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1以及-v /usr/bin/nvidia-smi:/usr/bin/nvidia-smi,更推荐使用NVIDIA官方容器工具包(nvidia-container-toolkit)。
实战三:跨平台Python终极方案(推荐)
Python最大的优势是跨平台逻辑统一,且能轻松对接数据分析与告警系统。
1 安装依赖库
pip install pynvml psutil # pynvml仅支持NVIDIA,AMD需用amdsmi
2 优雅的封装代码(同时支持NVIDIA + AMD回退)
import os
import psutil
def get_gpu_memory():
"""返回列表,每个GPU一个字典:{name, total_mb, used_mb, free_mb}"""
gpu_info = []
try:
from pynvml import nvmlInit, nvmlDeviceGetHandleByIndex, nvmlDeviceGetMemoryInfo, nvmlDeviceGetName, nvmlShutdown
nvmlInit()
for i in range(int(os.popen("nvidia-smi -L | wc -l").read().strip())):
handle = nvmlDeviceGetHandleByIndex(i)
mem = nvmlDeviceGetMemoryInfo(handle)
gpu_info.append({
"name": nvmlDeviceGetName(handle).decode(),
"total_mb": mem.total // 1024**2,
"used_mb": mem.used // 1024**2,
"free_mb": mem.free // 1024**2
})
nvmlShutdown()
except Exception:
# 回退到读取sysfs(适配AMD)
for card in ["card0", "card1"]:
base = f"/sys/class/drm/{card}/device"
if os.path.exists(f"{base}/mem_info_vram_total"):
total = int(open(f"{base}/mem_info_vram_total").read()) // 1024**2
used = int(open(f"{base}/mem_info_vram_used").read()) // 1024**2
gpu_info.append({"name": card, "total_mb": total, "used_mb": used, "free_mb": total-used})
return gpu_info
if __name__ == "__main__":
for gpu in get_gpu_memory():
print(f"型号: {gpu['name']} | 总显存: {gpu['total_mb']}MB | 已用: {gpu['used_mb']}MB | 剩余: {gpu['free_mb']}MB")
代码优势:自动检测驱动类型,无需手动指定GPU厂商。
问答Q3:
pynvml获取的显存单位是什么?精度如何? 答:单位为字节(Bytes),代码中除1024**2转为兆字节(MiB),精度与nvidia-smi完全一致(底层同一NVML接口),但注意memory.free可能不包含“保留内存”,因此free + used ≠ total。
常见问题FAQ(附排查方案)
Q4:脚本获取的显存数值比任务管理器小,为什么?
答:Windows任务管理器默认显示专用GPU内存,而
nvidia-smi显示的包括了共享GPU内存,如需一致,在脚本中增加--query-gpu=memory.total,memory.used --format=csv即可。
Q5:虚拟化平台(如VMware ESXi)下,显存显示为0?
答:虚拟机不会直通物理GPU显存,若为vGPU,需在宿主机安装NVIDIA vGPU驱动,并在虚拟机内挂载
nvidia-smi对应版本,否则,只能获取主机分配的虚拟显存大小(通常为配置固定值)。
Q6:如何用脚本检测显存温度并触发降频?
答:在Python代码中增加
nvmlDeviceGetTemperature(handle, NVML_TEMPERATURE_GPU),当温度>85℃时,通过subprocess调用nvidia-smi -pl 250(功率限制)或nvidia-smi -lgc 1000,1500(锁定频率)。
脚本之外,显存监控的未来趋势
脚本化获取显存是基础能力,但现代GPU监控已向可观测性演进,例如NVIDIA DCGM(Data Center GPU Manager)能提供细粒度的显存带宽、ECC错误率等指标,并通过Prometheus导出,对于个人开发者,建议将上述脚本集成到Grafana + Prometheus生态中,实现可视化告警。
最终建议:在您的生产环境中,优先使用官方工具(nvidia-smi),但将脚本封装成独立模块(如get_vram()函数),方便在自动化流水线中复用,无论您用的是Windows还是Linux,请务必定期更新驱动版本,因为NVML接口会随驱动迭代而增强。
打开您的终端,运行第一行代码,看看您的“显存地图”吧!