nvidia-smi 失灵,显存凭空消失?—— NVML 驱动版本错配的记录

引言

第二天回到工位,准备查看昨晚的运行结果。nvidia-smi 直接抛出版本不匹配:

Failed to initialize NVML: Driver/library version mismatch``NVML library version: 580.159

更诡异的是------btop 的 GPU 监控栏位全部消失,但 Triton 推理服务的日志还在滚动,吞吐数字看起来一切正常。

直到跑了一个新测试,发现 YOLO 推理耗时从 3ms 变成了 20ms,输出还是空的。问题才浮出水面。

复制代码
/.venv/lib/python3.12/site-packages/torch/cuda/__init__.py:182: UserWarning: CUDA initialization: Unexpected error from cudaGetDeviceCount(). Did you run some cuda functions before calling NumCudaDevices() that might have already set an error? Error 804: forward compatibility was attempted on non supported HW (Triggered internally at /pytorch/c10/cuda/CUDAFunctions.cpp:119.)
  return torch._C._cuda_getDeviceCount() > 0

案发现场:四层症状矩阵

现象 接口层 状态 根因
nvidia-smi 拒绝启动 NVML 完全失效 用户态库 580.159 vs 内核模块旧版本,严格版本锁拒绝握手
btop GPU 监控消失 NVML 完全失效 同走 libnvidia-ml.so,初始化即返回错误
YOLO 测试报 Error 804 后 fallback CPU CUDA Runtime ⚠️ 静默降级 新 CUDA 进程初始化时 forward compatibility 失败,PyTorch 静默回退 CPU
Triton 服务仍在推理 CUDA Driver / Context 残留运行 驱动更新前已建立 CUDA Context,旧内核模块仍为其服务

这不是驱动"损坏"。这是驱动更新只完成了一半


真凶:unattended-upgrades 的半成品更新

Ubuntu 默认启用的 unattended-upgrades 服务会在后台自动安装安全更新。NVIDIA 驱动包(nvidia-driver-580libnvidia-* 等)被它悄无声息地刷到了 580.159,写入磁盘。

但 Linux 内核模块(nvidia.ko)一旦加载就驻留内存。APT 不会、也不能替换运行中的内核模块。于是出现版本撕裂:

bash 复制代码
# 用户态库版本
dpkg -l | grep nvidia-utils-580
# ii  nvidia-utils-580  580.159-0ubuntu1  amd64
# 内核模块版本(仍在内存中)
cat /proc/driver/nvidia/version
# NVRM version: NVIDIA UNIX x86_64 Kernel Module  580.126.09

dkms 本应在新内核或新驱动安装后自动重建模块,但这里有两个陷阱:

  1. DKMS 构建需要匹配的内核头文件 ,如果 linux-headers-$(uname -r) 缺失或版本不对,构建会静默失败;

  2. 即使 DKMS 构建成功,新模块也需要重启才能加载 (除非你手动 rmmod + modprobe)。

所以 unattended-upgrades 留下了一个"更新了一半"的状态:磁盘上全是新代码,内存里跑着旧内核。


第一层:NVML 为什么必须拒绝服务

NVML(NVIDIA Management Library)是运维监控的唯一入口。它的设计是零容错版本锁

bash 复制代码
// libnvidia-ml.so 内部逻辑(示意)
if
(
    user_space_version != kernel_module_version
)
{
    return NVML_ERROR_DRIVER_NOT_LOADED; // 直接拒绝
}

nvidia-smibtopnvitopgpustat 全部依赖 NVML。当 580.159 的 libnvidia-ml.so 尝试通过 /dev/nvidiactl 与内核对话时,内核驱动发现版本号不匹配,直接返回 NVRM: API mismatch

结果不是"部分监控不可用",而是整个管理平面被连根拔起。 你看不到显存、看不到温度、看不到功耗,甚至无法判断 GPU 是否还在物理层面正常运行。


第二层:CUDA Error 804 的精确含义

YOLO 测试报错:

复制代码
Error 804: forward compatibility was attempted on non supported HW

这是 CUDA Runtime 的**向前兼容(Forward Compatibility)**机制失败。流程如下:

  1. PyTorch 内置的 CUDA Runtime(CUDA 12.x)启动时调用 cudaGetDeviceCount()

  2. Runtime 检测到内核驱动版本(580.126.09)低于自身要求的最低版本;

  3. Runtime 尝试进入 Forward Compatibility 模式 ------这是 NVIDIA 允许新 CUDA Toolkit 在旧驱动上运行的一种降级机制,但仅在数据中心驱动(Data Center/Tesla)且安装了 cuda-compat-* 包时可用

  4. 你的环境不满足 forward compatibility 条件(驱动类型不对、或缺少 compat 包、或版本差距过大),Runtime 抛出 cudaErrorCompatNotSupportedOnDevice(Error 804);

  5. PyTorch 捕获错误后,torch.cuda.is_available() 返回 False,整个推理链 silently fallback 到 CPU。

所以那 20.1ms 的 YOLO 推理不是在 GPU 上完成的。 是 CPU 在跑。(no detections) 和空 tensor 只是模型在 CPU 上的正常输出------你以为是 GPU 推理出错了,实际上它根本没拿到 GPU 门票。


第三层:Triton 为什么还在跑?

这是最反直觉的部分。如果驱动都"裂了",Triton 怎么还能推理?

答案是:CUDA Driver API 和 NVML 是两个完全独立的信任域。

bash 复制代码
┌─────────────────────────────────────────┐
│  用户空间工具层 (nvidia-smi, btop)      │  ← NVML 接口,版本敏感
│     libnvidia-ml.so (580.159)          │
├─────────────────────────────────────────┤
│  CUDA Runtime / cuDNN / PyTorch        │  ← CUDA 驱动 API,向后兼容
│     libcuda.so (580.159)               │
├─────────────────────────────────────────┤
│  NVIDIA 内核驱动 (nvidia.ko)           │  ← 仍在内存中 (580.126.09)
│  ├─ GPU 计算调度 (正常)                │
│  ├─ 显存管理 (正常)                    │
│  └─ NVML 管理接口 (版本校验失败)        │  ← 只有这里拒绝新库
└─────────────────────────────────────────┘

Triton 在驱动更新前已经完成了 cuInit()cuCtxCreate()cuMemAlloc() 的全套初始化。它的 CUDA Context 像一根钉子一样钉在旧内核模块里。只要进程不退出、不调用 NVML、不重新初始化 CUDA,它就能继续用旧驱动的计算能力。

但这是一种残留运行状态

  • 旧 Triton 进程:✅ 正常推理

  • 新启动的任何 CUDA 进程:❌ Error 804,直接 fallback CPU 或报错

  • 如果此时 systemctl restart triton-server,它会立刻在你面前失效


诊断:确认每一层的状态

bash 复制代码
# 1. 确认内核模块版本(预期比 580.159 旧)
cat /proc/driver/nvidia/version

# 2. 确认用户态库版本(预期 580.159)
dpkg -l | grep -E "nvidia|cuda"

# 3. 确认 DKMS 构建状态(看有没有 build error)
sudo dkms status | grep nvidia

# 4. 确认系统日志中的 API mismatch
sudo dmesg | grep -i "NVRM.*mismatch"
sudo grep NVRM /var/log/syslog

# 5. 确认 PyTorch 实际使用的设备
python -c "
import torch
print(f'CUDA available: {torch.cuda.is_available()}')
print(f'Device count: {torch.cuda.device_count()}')
"

# 6. 确认当前占用 GPU 的进程(旧 Triton 应该还在)
sudo fuser -v /dev/nvidia*

解决:重启,以及永远不要让这事再发生

在确保不严重影响业务的时间下重启

复制代码
sudoreboot

重启后内核从磁盘加载 nvidia.ko 580.159,用户态和内核态对齐,NVML 和 CUDA Runtime 双双恢复。

检查 DKMS 是否真的工作了

如果重启后问题依旧,说明 DKMS 没把模块编出来:

bash 复制代码
sudo dkms status
# 如果看到 nvidia/580.159 状态不是 installed,或内核版本不匹配:
sudo apt install linux-headers-$(uname -r)
sudo dkms autoinstall
sudo update-initramfs -u
sudo reboot

永久防御:把 NVIDIA 加入 unattended-upgrades 黑名单

bash 复制代码
sudo vim /etc/apt/apt.conf.d/50unattended-upgrades

# 在 Unattended-Upgrade::Package-Blacklist 中加入:
"nvidia-";
"libnvidia-";
"linux-modules-nvidia-";
"linux-headers-nvidia-";
"linux-image-nvidia-";
"linux-objects-nvidia-";
复制代码
然后重启服务:
复制代码
sudo systemctl restart unattended-upgrades

如果你不想彻底关闭自动更新,也可以设置更新后在不影响业务的时间段自动重启(确保新模块生效):

bash 复制代码
# 同样在 50unattended-upgrades 中
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";

结论:一次典型的静默故障

这次事件出现分层失效,危险性不在于破坏力,而在于隐蔽性****:

  • 监控层(NVML)先失效,失去观测能力;

  • 新计算层(CUDA Runtime)半失效,让人以为模型还在 GPU 跑,实际上在 CPU 上磨洋工;

  • 旧计算层(已有 CUDA Context)残留运行,给"系统正常"的假象。

故障类型 业务影响 发现难度
服务直接宕机 完全中断,用户立刻投诉 ⭐ 极易发现
GPU 静默 fallback CPU 推理延迟 ×6~10,吞吐量暴跌,但 API 仍返回 200 ⭐⭐⭐ 极难发现

Triton 服务没有崩溃,HTTP 端口还在监听,请求还在返回 200。只是每张图片的推理从 3ms 变成了 20ms,吞吐量从 1000 QPS 掉到了 100 QPS。如果你的负载均衡器没有设置 latency 告警,你可能要过几天才从用户投诉里发现异常。

真正的损失不是电费,而是:

  • 服务质量降级:用户等待时间增加

  • 资源挤占:CPU 被推理任务占满,影响其他服务

  • 排查成本 :你花了半天时间才发现 nvidia-smi 失效和 Error 804 的关联

把 NVIDIA 包加入 unattended-upgrades 黑名单,更新驱动后手动重启验证,是运维的必修课。

创作不易,禁止抄袭,转载请附上原文链接及标题

相关推荐
雨的旋律20993 小时前
keepalived + LVS NAT模式
服务器·网络·lvs
NiceCloud喜云4 小时前
Claude API PDF 文档问答实战:从原生解析到分页引用的完整方案
java·服务器·前端·网络·数据库·人工智能·pdf
Irissgwe4 小时前
二、Linux基础开发工具(2)
linux·makefile·gcc·g++·
basketball6164 小时前
Linux sed 和 awk 命令使用方法
linux·运维·chrome
一拳一个娘娘腔4 小时前
Linux SSH免密登录:从“刷卡进门”到“刷脸通行”的完整指南
linux·运维·ssh
傅科摆 _ py4 小时前
企业 / 校园 合法远程访问工具详解
服务器·网络·数据库
代码AC不AC4 小时前
【Linux】线程控制
linux·线程·线程控制
Chirp5 小时前
Windows下借助wsl2读取ext4格式磁盘
linux·windows
taocarts_bidfans5 小时前
反向海淘站点运维优化与常见技术问题排查
大数据·运维·跨境电商·独立站·反向海淘