在 A100 80 GB 上限制容器可见 GPU 的 UUID
解读
国内大厂(阿里、腾讯、字节)的 GPU 训练集群普遍采用 NVIDIA A100 80 GB 作为主力卡,单节点 8 卡通过 NVSwitch 全互联。面试时考官想确认你能否在 共享集群 场景下,用 Docker 把指定 GPU UUID 暴露给容器,避免任务抢占、满足调度器(K8s/Volcano/Slurm)的 硬隔离 要求,同时保证 驱动版本 470+、nvidia-container-toolkit 已安装。答不出 UUID 级隔离会被视为“只会单机跑脚本”。
知识点
- GPU UUID 概念:每块 A100 的 UUID 全球唯一,可通过
nvidia-smi -L查看,格式如GPU-66dd05f6-6b7c-3c78-9d93-d5c9f9a8e7f2。 - Docker 19.03+ 原生支持:
--gpus参数可接device=列表,支持 UUID、索引、MIG 切片三种写法。 - nvidia-container-runtime:在 runc 之前注入
nvidia-container-toolkit,把指定 GPU 字符设备(/dev/nvidia*)挂载到容器 cgroups 的devices.allow,实现 内核级屏蔽。 - 多卡训练常见坑:
- 索引顺序随驱动加载变化,索引≠物理位置;
- MIG 模式下 UUID 会变,需用
nvidia-smi -L -mig确认; - 未设置
NVIDIA_VISIBLE_DEVICES时默认可见全卡,违反安全规范。
- 国内合规:等保 2.0 要求“资源隔离可审计”,UUID 级隔离是 审计直接证据。
答案
步骤如下,全部在 CentOS 7.9 + Docker 20.10 + NVIDIA Driver 470.129 验证通过:
- 查询目标卡 UUID
nvidia-smi -L | grep A100 # 输出:GPU-66dd05f6-6b7c-3c78-9d93-d5c9f9a8e7f2 (UUID) - 启动容器并限定可见 GPU
说明:docker run -it --rm --gpus device=GPU-66dd05f6-6b7c-3c78-9d93-d5c9f9a8e7f2 \ -v /data:/data tensorflow/tensorflow:2.11.0-gpu python--gpus device=<UUID>可写多块,逗号分隔;- 容器内执行
nvidia-smi只能看到被指定的卡,其他卡完全消失; - 若使用 docker-compose,写法:
services: train: image: tensorflow/tensorflow:2.11.0-gpu deploy: resources: reservations: devices: - driver: nvidia count: 0 device_ids: ['GPU-66dd05f6-6b7c-3c78-9d93-d5c9f9a8e7f2'] capabilities: [gpu]
- 验证隔离
在容器外另起需要 4 卡的作业,确认 未被占用的卡仍可被调度,实现 硬隔离。
拓展思考
- MIG 场景:A100 80 GB 可切分成 7 个 10 GB 实例,UUID 变为
MIG-<GPU-UUID>/<gpu-instance-id>/<compute-instance-id>,此时需用nvidia-smi mig -cgi 0,1,2 -gi 0预先创建切片,再用--gpus device=MIG-xxx指定。 - K8s 设备插件:国内阿里 ACK、腾讯 TKE 均已支持 GPU UUID 级调度,通过
nvidia.com/gpu: "1"加node-lable=gpu-uuid=xxx实现,但底层仍依赖上述 Docker 参数。 - 故障排查:若容器仍能看到全卡,99% 是
/etc/docker/daemon.json中default-runtime未设为nvidia,或nvidia-container-toolkit版本低于 1.9。 - 性能调优:限定 UUID 后可把 NUMA 节点与 GPU 绑定(
--cpuset-mems=0对应 GPU0),避免跨 NUMA 访存,提升 2~3% 训练吞吐。