HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于

GPU 调度的常见问题

在 K8s 上跑 GPU 任务,总会遇到各种调度问题。

这篇汇总常见问题和排查方法。


问题一:GPU 资源不显示

现象

kubectl describe node gpu-node | grep nvidia
# 什么都没有

排查步骤

1. 检查 Device Plugin

kubectl get pods -n kube-system | grep nvidia

没有运行?安装 NVIDIA Device Plugin:

kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/master/nvidia-device-plugin.yml

2. 检查 Device Plugin 日志

kubectl logs -n kube-system nvidia-device-plugin-xxxx

常见错误:

failed to initialize NVML: could not load NVML library

原因:节点上没装 NVIDIA 驱动或 Container Toolkit。

3. 检查节点驱动

# SSH 到节点
nvidia-smi

如果报错,说明驱动没装好。

4. 检查容器运行时

containerd 需要配置 nvidia runtime:

# /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]
  runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia.options]
  BinaryName = "/usr/bin/nvidia-container-runtime"

问题二:Pod 无法调度

现象

kubectl get pod gpu-pod
# Pending

kubectl describe pod gpu-pod
# 0/3 nodes are available: 3 Insufficient nvidia.com/gpu

排查步骤

1. 检查集群 GPU 总量

kubectl describe nodes | grep nvidia.com/gpu

2. 检查已使用量

kubectl get pods --all-namespaces -o json | \
  jq '[.items[] | select(.spec.containers[].resources.limits["nvidia.com/gpu"]!=null)] | length'

3. 常见原因

  • GPU 被其他 Pod 占满
  • 请求的 GPU 数量超过单节点最大值
  • nodeSelector 不匹配

4. 解决方案

# 等其他任务完成
# 或者调整请求的 GPU 数量
resources:
  limits:
    nvidia.com/gpu: 1  # 减少请求数量

问题三:容器内看不到 GPU

现象

# 容器内
nvidia-smi
# NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver

排查步骤

1. 检查环境变量

echo $NVIDIA_VISIBLE_DEVICES

应该是 all 或者具体的 GPU 编号(如 0,1)。

2. 检查设备挂载

ls -la /dev/nvidia*

应该能看到 /dev/nvidia0、/dev/nvidiactl 等。

3. 检查 Pod 配置

确认请求了 GPU:

resources:
  limits:
    nvidia.com/gpu: 1

4. 检查运行时配置

可能 nvidia runtime 没配置好。在节点上测试:

docker run --rm --gpus all nvidia/cuda:12.0-base nvidia-smi

问题四:GPU 利用率低

现象

nvidia-smi
# GPU 利用率只有 10-20%

原因分析

1. 推理场景

推理本身利用率就不高(带宽瓶颈)。

解决:增加 batch size,用 Continuous Batching。

2. 数据加载慢

CPU 加载数据跟不上 GPU 计算。

解决:

  • 增加 DataLoader 的 num_workers
  • 用更快的存储
  • 数据预处理

3. 代码问题

训练循环有阻塞操作。

检查:

  • 是否有不必要的 torch.cuda.synchronize()
  • 是否有 CPU 和 GPU 之间的频繁数据传输

4. 通信瓶颈

分布式训练时,通信时间太长。

检查 NCCL 带宽:

# 在节点上跑 nccl-tests
./all_reduce_perf -b 8 -e 128M -f 2 -g 8

问题五:OOM(显存不足)

现象

CUDA out of memory. Tried to allocate 2.00 GiB

排查步骤

1. 监控显存使用

nvidia-smi -l 1
# 或
watch -n 1 nvidia-smi

2. 常见原因和解决

原因解决方案
batch size 太大减小 batch size
模型太大用量化、模型并行
显存泄漏检查代码,及时释放
KV Cache 太大限制上下文长度

3. PyTorch 显存分析

import torch
print(torch.cuda.memory_summary())

4. 显存碎片

PyTorch 会缓存显存,可能导致碎片:

torch.cuda.empty_cache()  # 清理缓存

问题六:多卡训练卡住

现象

训练开始后不动了,没有报错。

排查步骤

1. 检查是否 NCCL 问题

export NCCL_DEBUG=INFO
# 重新运行训练

看日志里有没有 NCCL 错误。

2. 常见原因

  • 某张卡通信失败
  • rank 配置错误
  • 网络不通

3. 检查网络

# 检查 IB 状态
ibstat

# 检查 GPU P2P
nvidia-smi topo -m

4. 超时设置

export NCCL_TIMEOUT=1800  # 30 分钟

问题七:拓扑不优

现象

8 卡训练,但性能只有预期的一半。

原因

Pod 被调度到拓扑不好的 GPU 上。

nvidia-smi topo -m

# 可能的输出:
#         GPU0    GPU1    GPU2    GPU3
# GPU0     X      NV12    PHB     SYS
# GPU1    NV12     X      PHB     SYS
# GPU2    PHB     PHB      X      NV12
# GPU3    SYS     SYS     NV12     X

GPU0-GPU1 是 NVLink,GPU0-GPU3 是跨 CPU(SYS),带宽差很多。

解决

1. 用 Topology Aware Scheduling

NVIDIA 的 GPU Operator 支持拓扑感知调度。

2. 手动指定 GPU

env:
- name: CUDA_VISIBLE_DEVICES
  value: "0,1,2,3"  # 指定连续的 GPU

3. 用 Volcano 的 binpack 策略

让 Pod 尽量调度到同一节点。


问题八:Device Plugin 崩溃

现象

Device Plugin Pod 不断重启。

排查

kubectl logs -n kube-system nvidia-device-plugin-xxx --previous

常见原因

  • NVML 库版本不匹配
  • GPU 硬件故障
  • 驱动版本问题

解决

  • 更新驱动和 Device Plugin 版本
  • 检查 GPU 健康状态:nvidia-smi -q
  • 禁用故障 GPU

问题九:节点重启后 GPU 丢失

现象

节点重启后,GPU 不再显示。

原因

  • 驱动没有开机自启
  • NVIDIA 服务没启动

解决

# 检查驱动模块
lsmod | grep nvidia

# 如果没有,加载模块
sudo modprobe nvidia

# 设置开机自启
sudo systemctl enable nvidia-persistenced

调试工具汇总

工具用途
nvidia-smiGPU 状态、进程、显存
nvitop交互式 GPU 监控
dcgmiNVIDIA 数据中心 GPU 管理
nvidia-smi topoGPU 拓扑
nccl-tests多卡通信带宽测试
kubectl describeK8s 资源状态

小结

GPU 调度问题速查表:

问题关键排查点
GPU 不显示Device Plugin、驱动、Container Toolkit
无法调度资源是否足够、nodeSelector
容器内没 GPU环境变量、设备挂载、运行时配置
利用率低batch size、数据加载、通信
OOM显存分析、batch size、量化
多卡卡住NCCL 日志、网络、超时
拓扑不优nvidia-smi topo、调度策略

核心方法:

  1. 看日志(kubectl logs、NCCL_DEBUG)
  2. 看状态(nvidia-smi、kubectl describe)
  3. 测试基础设施(nccl-tests、P2P 测试)

调度篇结束。下一部分讲工程化。