你是否曾遇到过这样的场景:
深夜运行深度学习实验,第二天查看结果时发现训练中途崩溃。进入终端排查后才发现是显存溢出导致,但却无法确定究竟是哪个环境或哪段代码长期占用了GPU资源。
nvidia-smi
更令人困惑的是:明明系统中已安装CUDA,当前环境却提示“CUDA not available”,而另一个Conda环境却能正常调用GPU——问题到底出在哪里?
其实,这是AI工程师普遍会遭遇的困境:软件依赖与硬件资源管理之间存在脱节。
我们通过Miniconda实现了Python包和依赖的隔离,但GPU作为系统级资源,默认对所有进程开放,缺乏有效的上下文关联机制,导致资源使用情况难以追踪。
nvidia-smi
只有将两者结合,才能实现从虚拟环境到硬件资源的端到端监控。
很多人在实际操作中只掌握部分技能,导致信息断层:
sys.prefix或which python输出中;nvidia-smi的基本输出,但无法将其中的进程PID映射回具体的开发环境;conda activatepythonnvidia-smiPID
接下来的内容将系统性地解决这些问题,涵盖原理讲解、常用命令及可复用脚本,助你彻底掌控GPU资源使用情况。
尽管virtualenv + pip在普通Python项目中表现良好,但在AI/深度学习领域,它面临诸多局限:
| 能力 | virtualenv + pip | Miniconda |
|---|---|---|
| 管理 Python 包 | 支持 | 支持 |
| 安装 CUDA/cuDNN 等二进制库 | 依赖手动配置,成功率靠“运气” | 官方channel直接支持 |
| 多 Python 版本切换 | 需预先安装多个解释器 | 可一键创建指定版本环境 |
| 跨平台一致性 | Windows 下兼容性差 | 统一包管理系统,体验一致 |
virtualenv + pip
举例说明:若需安装支持GPU的PyTorch。
conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia
该命令不仅安装了PyTorch,还会自动部署所需的cudatoolkit等底层库,且完全独立于系统全局环境,避免污染主机配置。
cudatoolkit
因此,Miniconda不仅是虚拟环境工具,更是面向科学计算生态的一站式解决方案。
简单来说,nvidia-smi就是GPU的“任务管理器”。
无论你在哪个Conda环境中运行TensorFlow、PyTorch或其他框架,只要调用了GPU进行计算,nvidia-smi都能捕获相关进程。
tf-env
pt-exp2
$ nvidia-smi
+-----------------------------------------------------------------------------+
| Processes: |
| GPU PID Type Process name GPU Memory Usage |
| 0 12345 C+G python 3245MiB / 40960MiB |
+-----------------------------------------------------------------------------+
例如,在输出中可以看到某个Python进程正在执行训练脚本,占用了3.2GB显存。
PID=12345python
然而,仅凭nvidia-smi的默认输出,并不能直接判断该进程属于哪一个Conda环境。
不过,在Linux系统中,“一切皆文件”,进程的启动细节通常可通过系统接口获取。
我们可以借助ps命令结合进程ID(PID)反向查询其启动命令行:
ps
$ ps -p 12345 -o cmd=
典型输出如下:
/home/user/miniconda3/envs/ml-exp/bin/python train_model.py
? 成功定位!该进程运行于名为dl-project-env的Conda环境中。
ml-exp
核心方法总结:
nvidia-smi获取占用GPU的进程PID;ps -fp <PID>查看该进程的完整启动命令;ps
整个过程如同侦探破案,层层递进,最终锁定“真凶”。??????♂?
以下是我在日常开发中高频使用的几个命令组合,建议收藏备用。
最基础也最常用的命令,可即时了解GPU利用率、温度、显存占用等关键信息。
nvidia-smi
每2秒刷新一次,便于实时跟踪模型训练期间的资源变化趋势。
nvidia-smi -l 2
犹如心电图般持续监测,及时发现异常峰值或内存泄漏迹象。??????
将监控结果以CSV格式输出,方便后续导入Pandas或Excel进行绘图分析。
nvidia-smi --query-gpu=index,name,temperature.gpu,utilization.gpu,memory.used,memory.total --format=csv
保存为文件示例:
index, name, temperature.gpu, utilization.gpu, memory.used [MiB], memory.total [MiB]
0, NVIDIA A100-SXM4-40GB, 65, 85, 32456, 40960
几分钟内即可生成性能趋势图,助力优化训练策略。????
显示每个使用GPU的进程及其核心利用率和显存占比。
nvidia-smi pmon -s um
输出样例如下:
# gpu pid type sm mem enc dec command
0 12345 C 78 82 - - python
sm:Streaming Multiprocessor 利用率,反映计算核心负载;mem:显存占用百分比;C:Compute Mode 进程,通常为主动训练任务。手动追踪效率低?为此我编写了一个Python脚本,可自动关联GPU进程与其对应的Conda环境名。
import subprocess
import json
import time
def get_gpu_processes():
# 获取占用 GPU 的进程信息
cmd = [
"nvidia-smi",
"--query-compute-apps=pid,process_name,used_memory",
"--format=csv,noheader,nounits"
]
result = subprocess.run(cmd, capture_output=True, text=True)
lines = result.stdout.strip().split('\n')
processes = []
for line in lines:
if not line.strip():
continue
pid, pname, mem = [x.strip() for x in line.split(',')]
# 获取该进程的完整启动命令
try:
full_cmd = subprocess.getoutput(f"ps -p {pid} -o cmd=")
except:
full_cmd = "<unknown>"
# 尝试解析 Conda 环境名
env_name = None
if "miniconda" in full_cmd or "anaconda" in full_cmd:
parts = full_cmd.split('/')
if 'envs' in parts:
idx = parts.index('envs')
if idx + 1 < len(parts):
env_name = parts[idx + 1] # 提取环境名
processes.append({
"pid": pid,
"command": pname,
"memory_used_MiB": int(mem),
"conda_env": env_name,
"full_cmd": full_cmd
})
return processes
# 示例:每隔 5 秒打印一次
while True:
procs = get_gpu_processes()
print("\n[+] 当前 GPU 使用情况:")
print(json.dumps(procs, indent=2))
time.sleep(5)
运行效果如下:
[
{
"pid": "12345",
"command": "python",
"memory_used_MiB": 32456,
"conda_env": "ml-exp",
"full_cmd": "/home/user/miniconda3/envs/ml-exp/bin/python train_model.py"
}
]
输出清晰直观,极大提升调试效率。????
你还可以将其部署为后台服务,定期采集数据,甚至集成进监控仪表盘(dashboard),实现全天候资源观测。
假设团队多人共用一台GPU服务器,频繁出现“显存被未知进程占用”的情况。
通过上述组合技:
nvidia-smi发现可疑PID;ps查出其启动路径;整个流程无需重启系统或中断其他任务,高效精准。
此外,结合定时任务(如cron),可每日自动生成资源使用报告,帮助评估算力分配合理性,推动资源优化决策。
当多个实验并行运行时,系统突然报出 OOM(内存溢出)错误,导致某个任务崩溃。
应对步骤如下:
nvidia-smi pmon -s mps -p <PID> -o cmd=排查过程中发现异常进程来源于一个长期未关闭的测试分支实例:
/envs/debug-env/bin/python解决方案:
手动终止该进程:
kill <PID>在新建环境中尝试导入 PyTorch 时出现错误提示:
.cuda()
然而使用命令检测 GPU 状态时显示设备正常:
nvidia-smi排查逻辑链:
nvidia-smi → 显示正常 conda list | grep cudacudatoolkitconda install cudatoolkit=11.8 -c conda-forge根本原因:
并非 NVIDIA 驱动问题,而是当前环境缺少本地 CUDA runtime 支持。
小贴士:
NVIDIA 显卡驱动 ≠ CUDA Toolkit。前者是操作系统级别的硬件驱动,后者是程序运行所需的动态库,必须在每个独立环境中正确安装才能生效。
观察到 GPU 使用率持续低迷:
GPU-Util诊断流程如下:
nvidia-smi dmon -s u -d 1num_workers > 0 和 pin_memory=True关键结论:
多数情况下,性能瓶颈并不来自模型本身,而在于 I/O 读取效率或配置参数不合理。
要实现高效的资源管理,需理清整个系统的分层结构:
graph TD
A[用户应用层] --> B[Miniconda 环境层]
B --> C[操作系统与驱动层]
C --> D[硬件层]
subgraph "用户层"
A1[Python 脚本 train.py]
end
subgraph "环境层"
B1[env: tf-env (3.8)]
B2[env: pt-env (3.9)]
B3[env: jax-env (3.10)]
end
subgraph "系统层"
C1[CUDA Toolkit]
C2[cuDNN]
C3[NVIDIA Driver + NVML]
end
subgraph "硬件层"
D1[NVIDIA GPU (A100)]
end
A1 --> B2
B2 --> C1 --> C3 --> D1
style A1 fill:#D6EAF8,stroke:#3498DB
style B1 fill:#D5F5E3,stroke:#2ECC71
style B2 fill:#D5F5E3,stroke:#2ECC71
style B3 fill:#D5F5E3,stroke:#2ECC71
style C1 fill:#FEF9E7,stroke:#F1C40F
style C3 fill:#FEF9E7,stroke:#F1C40F
style D1 fill:#FADBD8,stroke:#E74C3C
各层级职责分明:
只有打通这三层之间的关联,才能真正掌握训练全流程的主动权。
| 项目 | 推荐做法 |
|---|---|
| 环境命名规范 | 采用语义化命名方式,如:、 |
| 包安装方式 | 优先使用 安装,避免 pip 与 conda 混用引发依赖冲突 |
| 监控轮询频率 | 设置采样间隔 ≥1 秒,防止过度轮询造成 CPU 负载过高 |
| 日志保留策略 | 启用日志自动切割功能:每日归档,便于追溯 |
| 多用户安全控制 | 通过 cgroups 或容器机制限制用户权限,禁止随意查看他人进程 |
| 自动化监控方案 | 编写轻量级服务定时采集指标,并推送告警至钉钉或企业微信 |
效率提升技巧:
将常用命令封装为 shell alias,例如:
# ~/.bashrc
alias gpustat='nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total --format=csv'
alias conda-ps='ps aux | grep -E "miniconda|anaconda"'gpustat随着 AI 开发复杂度上升,我们不应只聚焦于模型结构、准确率等“上层建筑”。
真正的技术高手往往胜在细节:
而这一切的基础,正是——
让软件环境与硬件资源变得透明且可追踪。
Miniconda 与 nvidia-smi 看似只是两个基础工具,但一旦组合运用得当,便能释放巨大生产力。
下一次当你看到熟悉的命令输出:
nvidia-smi“这个 PID,到底属于哪个进程?”
一旦你能清晰回答这个问题,你就已经走在了大多数人的前面。
管好环境,看清资源,才能跑得更快、更稳、更自信。
扫码加好友,拉您进群



收藏
