3.3 排障地图:GPU 容器报错的"定位-归因-处置"三板斧 第三章前两节讲了调用链和隔离边界。这一节把所有"容器能跑起来但 GPU 相关报错"的症状,归纳成一张可操作的排障地图。我的主张是:90% 的 GPU 容器故障,都能用"看设备、看驱动、看可见性"这三板斧定位,不必盲搜报错全文。 三板斧总览 板斧一·看设备:进容器跑 ,若命令不存在或报错,说明 NVIDIA Container Toolkit 没装好、或 忘了 ; 板斧二·看驱动:能 但 为 False,或报 ,说明宿主机驱动版本低于容器 CUDA 工具链的要求; 板斧三·看可见性: 看到的卡和你预期不符,说明 / 设错了,容器实际看到的不是你以为的那张卡。
第三章前两节讲了调用链和隔离边界。这一节把所有"容器能跑起来但 GPU 相关报错"的症状,归纳成一张可操作的排障地图。我的主张是:90% 的 GPU 容器故障,都能用"看设备、看驱动、看可见性"这三板斧定位,不必盲搜报错全文。
nvidia-smi,若命令不存在或报错,说明 NVIDIA Container Toolkit 没装好、或 docker run 忘了 --gpus;nvidia-smi 但 torch.cuda.is_available() 为 False,或报 CUDA driver version is insufficient,说明宿主机驱动版本低于容器 CUDA 工具链的要求;nvidia-smi 看到的卡和你预期不符,说明 CUDA_VISIBLE_DEVICES / --gpus device= 设错了,容器实际看到的不是你以为的那张卡。--gpus,容器里根本没有卡症状:容器内执行 nvidia-smi 报 command not found 或找不到设备;torch.cuda.is_available() 返回 False。
归因:启动容器时没加 --gpus all(或指定设备),NVIDIA runtime 没有把设备注入,也没有挂载 nvidia-smi 等工具。
处置:确认宿主机已装 NVIDIA Container Toolkit,并在 docker run 时显式加 --gpus '"device=0"' 之类。这是最基础也最常犯的错误,排在第一位讲。
症状:容器能起、设备也在,但一调 CUDA 就 CUDA driver version is insufficient for CUDA runtime version。
归因:宿主机 NVIDIA 驱动版本对应的"最高支持 CUDA"低于容器内 CUDA 工具链版本。记住铁律——运行时能力上限由宿主机驱动决定,不是镜像里写的版本。
处置:要么升级宿主机驱动,要么换用更低 CUDA 标签的基础镜像(如 nvidia/cuda:11.8-runtime)去匹配现有驱动。具体宿主机驱动支持到哪个 CUDA 版本,以 NVIDIA 官方"CUDA Driver"对应表为准,文中不臆造精确数值。
症状:nvidia-smi 里显示的是 0 号卡,但你明明想让容器用 3 号卡;或多容器都在抢 0 号卡导致 OOM。
归因:CUDA_VISIBLE_DEVICES 或 --gpus device= 没按预期设置,设备视图被 runtime 裁成了你不想要的集合。
处置:显式传 --gpus '"device=3"',或在入口脚本里 export CUDA_VISIBLE_DEVICES=3。注意容器内的卡序号是"被过滤后的相对序号"——比如你只给了 device=3,容器内看到的"0 号卡"实际是物理 3 号卡,这点在写多卡训练脚本时极易踩坑。
症状:想用 MPS 让多进程共享 GPU 上下文、降低开销,但实测没变化,甚至更慢。
归因:MPS 是进程级复用 CUDA 上下文的机制,必须 MPS 服务先起、容器进程挂到该服务下;若只是起了容器没配置 MPS 守护,自然不生效。MIG 则是硬件级切分,需要在驱动层用 nvidia-smi 先划好实例,容器才能用对应 profile,不是 --gpus 一句就能切出"半张卡"。
处置:MPS 参考官方 MPS 文档的启动流程;MIG 先确认硬件支持(消费级卡多不支持),再用 nvidia-smi mig 系列命令划分。具体命令以你所用版本官方说明为准,本文不编造。
所有 GPU 容器故障,本质都落在三层之一:设备注入层(Toolkit/--gpus)、驱动兼容层(宿主驱动 vs 镜像 CUDA)、可见性层(CUDA_VISIBLE_DEVICES)。拿到报错先别急著搜全文,而是问自己"它坏在哪一層"——这比背命令有用得多。下一章我们把这些原理直接落到训练与推理的真实案例上。