CUDA_VISIBLE_DEVICES 是什么
这个环境变量控制进程能看到哪些 GPU,以及这些卡在进程内的编号顺序。它解决两类问题:隔离(一个进程只用指定的卡,避免互抢)与重排(把物理卡映射成逻辑零号,让代码不必感知机器上插了几张卡)。进程在启动时读取该变量,运行中修改无效,子进程会继承父进程的可见集合。
常用写法
常用写法
# 只让进程看到物理 2 号卡(进程内编号为 0)
CUDA_VISIBLE_DEVICES=2 nvidia-smi
# 物理 0 与 3 号卡映射为进程内的 0 与 1
CUDA_VISIBLE_DEVICES=0,3 python run.py
# 按 UUID 固定映射,避免重启或换卡后序号漂移
CUDA_VISIBLE_DEVICES=GPU-xxxxxxxx-xxxx python run.py
# 核对生效结果:进程内看到的设备数量与名称
CUDA_VISIBLE_DEVICES=1 python -c "import torch; print(torch.cuda.device_count())"写法对照
| 写法 | 效果 | 适用情形 |
|---|---|---|
| 单个编号 | 只暴露一张卡,进程内编号为 0 | 单卡任务与压测 |
| 逗号分隔编号 | 暴露多张并按书写顺序重排 | 多卡任务固定映射关系 |
| 空字符串 | 屏蔽全部 GPU,进程只能看到 CPU | 保证 CPU 任务不误占显存 |
| UUID 列表 | 按设备唯一标识暴露 | 长期运行的编排与多机部署 |
| 不设置 | 进程看到全部设备 | 默认情形,容易互抢 |
基本信息
| 生效时机 | 进程启动时读取,运行中修改无效 |
|---|---|
| 生效范围 | 当前进程及其派生的子进程 |
| 编号口径 | 进程内的逻辑编号,与物理编号不一定一致 |
| 替代做法 | 容器只映射需要的卡,或在代码里显式指定设备 |
典型使用场景
- 单机多卡隔离:不同服务各占指定卡,避免显存互相侵占
- 指定卡跑任务:调试时只在空闲卡上运行,不影响线上服务
- 容器内只暴露部分卡:与编排配合时由运行参数控制可见设备
- 屏蔽 GPU 跑 CPU 任务:避免预处理脚本意外分配显存
- 复现环境:用 UUID 固定映射,保证每次运行对应同一张物理卡
变量只影响可见集合,不会自动帮你限制显存:想让两个进程共用一张卡还需要各自设置显存预算,否则仍会互相挤占。
长期运行的编排建议用 UUID 而不是序号:驱动重置、更换或重新枚举设备后,序号与物理卡的对应关系可能变化。