3. GPU不可见问题

好,咱们接着聊GPU调度里最让人头疼的一类问题——GPU不可见。

说白了,就是你明明插着卡,系统也认了,但应用就是找不到GPU。我这些年排查下来,90%的不可见问题都出在三个地方:驱动没加载、权限不够、容器里没配好。咱们一个一个拆开讲。

GPU不可见问题排查框架 GPU不可见 驱动未加载 nvidia-smi 无输出 lsmod | grep nvidia 权限不足 设备文件权限 用户组归属 容器内无法识别 --gpus 参数 nvidia-container-runtime 排查顺序:驱动 → 权限 → 容器配置

3.1 驱动未加载——最基础的坑

先问个问题:你插上GPU后,第一件事做什么?

我个人习惯,先敲nvidia-smi。如果它报错或者没输出,那驱动大概率没跑起来。

典型症状:

  • nvidia-smi 提示 "NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver"
  • lspci | grep -i nvidia 能看到显卡,但驱动没绑定
  • lsmod | grep nvidia 返回空

为什么会这样?我遇到过好几次,最常见的原因是内核升级后驱动没重新编译。你想想看,Linux内核一升级,原来装好的驱动模块就失效了。

排查步骤:

  1. 先确认硬件是否被识别:lspci | grep -i nvidia
  2. 检查驱动模块是否加载:lsmod | grep nvidia
  3. 如果没加载,手动试试:modprobe nvidia
  4. 查看内核版本和驱动版本是否匹配:uname -r 对比 cat /proc/driver/nvidia/version

小技巧: 我习惯在装驱动前先 apt-mark hold linux-image-$(uname -r) 锁定内核版本,避免一升级就炸。

3.2 权限不足——用户没资格用GPU

驱动加载成功了,但普通用户一跑程序就报错:CUDA error: no kernel image is available for execution on the device 或者干脆 Permission denied。

嗯,这里要注意。GPU设备文件默认属于root用户和video组。普通用户如果不在video组里,就没法访问。

我曾经帮一个团队排查,他们所有容器都跑在普通用户下,结果GPU全不可用。折腾了半天,最后发现是用户没加到video组。

权限检查清单:

  • 查看设备文件权限:ls -l /dev/nvidia*
  • 确认用户组归属:groups $USER
  • 如果缺少video组:sudo usermod -aG video $USER
  • 别忘了重新登录生效

还有一个容易被忽略的点——SELinux或AppArmor。我遇到过一台CentOS机器,所有权限都对了,但GPU就是不可见。最后发现是SELinux把设备访问给拦了。临时关掉测试一下:setenforce 0,如果好了,再去配策略。

3.3 容器内无法识别GPU——Docker和Kubernetes的坑

这部分我踩过的坑最多。主机上nvidia-smi跑得好好的,一进容器就找不到GPU。

核心原因就一个: 容器默认不共享宿主机的GPU设备。你得显式告诉容器:「嘿,把GPU挂进来」。

3.3.1 Docker场景

Docker 19.03之后,官方推荐用 --gpus 参数。以前还得挂设备文件、装nvidia-docker2,现在简单多了。

# 正确用法
docker run --gpus all nvidia/cuda:11.0-base nvidia-smi

# 或者指定某张卡
docker run --gpus '"device=0,1"' nvidia/cuda:11.0-base nvidia-smi

如果你还在用老版本Docker,那得装nvidia-container-runtime:

# 安装nvidia-container-runtime
sudo apt-get install nvidia-container-runtime

# 配置Docker daemon
sudo tee /etc/docker/daemon.json <<EOF
{
  "runtimes": {
    "nvidia": {
      "path": "/usr/bin/nvidia-container-runtime",
      "runtimeArgs": []
    }
  }
}
EOF

# 重启Docker
sudo systemctl restart docker

# 运行时指定runtime
docker run --runtime=nvidia nvidia/cuda:11.0-base nvidia-smi

我个人的排查习惯:

先在宿主机上跑 nvidia-smi 确认驱动正常。然后用 docker run --gpus all --rm nvidia/cuda:11.0-base nvidia-smi 测试。如果容器里看不到,90%是runtime没配好或者Docker版本太老。

3.3.2 Kubernetes场景

K8s里GPU不可见,通常是因为没装device plugin。我见过有人手动给Pod加了 resources: nvidia.com/gpu: 1,但集群里根本没部署NVIDIA device plugin,那当然不生效。

标准做法:

  1. 确保每个GPU节点都装了NVIDIA驱动和nvidia-container-runtime
  2. 部署NVIDIA device plugin DaemonSet
  3. 在Pod的resources里声明 nvidia.com/gpu
# 部署device plugin(官方推荐)
kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.14.0/nvidia-device-plugin.yml

# Pod示例
apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  containers:
  - name: cuda-container
    image: nvidia/cuda:11.0-base
    command: ["nvidia-smi"]
    resources:
      limits:
        nvidia.com/gpu: 1  # 申请1张GPU

注意: 如果你用的是containerd而不是Docker,记得在containerd配置里加上nvidia-container-runtime的配置。我去年帮一个客户排查,他们从Docker切到containerd后GPU全不可用,就是少了这步。

3.4 快速排查表

现象 可能原因 快速验证命令 解决方案
nvidia-smi 报错 驱动未加载 lsmod | grep nvidia 重新安装或加载驱动
普通用户无法访问 权限不足 ls -l /dev/nvidia* 加入video组
容器内nvidia-smi失败 缺少--gpus参数 docker run --gpus all ... 添加--gpus或配置runtime
K8s Pod调度失败 未部署device plugin kubectl describe pod 部署NVIDIA device plugin

最后说一句: 排查GPU不可见问题,我个人的顺序永远是「驱动 → 权限 → 容器配置」。别一上来就怀疑容器,先看看宿主机上能不能用。基础打牢了,上层的问题自然好解决。