pytorch之多GPU使用——#CUDA_VISIBLE_DEVICES使用 #torch.nn.DataParallel() #报错解决

本文详细介绍了在PyTorch中如何利用多GPU进行训练,包括如何设置CUDA_VISIBLE_DEVICES环境变量来指定使用哪些GPU,如何通过torch.nn.DataParallel进行数据并行计算,以及处理相关报错的解决方案。同时,强调了主卡设置的重要性,并提供了检查GPU可用性及状态的函数使用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要讲单机多卡(单主机多GPUs训练)

使用多卡训练的方式有很多,当然前提是我们的设备中存在多个GPU:使用命令nvidia-smi查看当前Ubuntu平台的GPU数量,其中每个GPU被编上了序号:[0,1,2,3]
在这里插入图片描述

0. 显卡编号(什么是主卡)

在默认情况下,标号为0的显卡为主卡,如主机中有4块显卡,那么每张显卡的默认标号为[0,1,2,3]。

如何将其他显卡设置为主卡呢?

通过os.environ["CUDA_VISIBLE_DEVICES"]指定所要使用的显卡,如:

os.environ["CUDA_VISIBLE_DEVICES"] = "3,2,0,1"
model = torch.nn.DataParallel(model, device_ids=[0,2,3]).cuda()

此时,3号显卡就变成了主卡,在使用torch.nn.DataParallel指定运算显卡时,显卡的对应关系如下:

实际显卡编号----->运算显卡编号
    3     ----->     0(主卡)
    2     ----->     1
    0     ----->     2
    1     ----->     3

1. 使用所有存在的显卡

在存在多卡的条件下,最简单的方法是直接使用torch.nn.DataParallel将你的模型wrap一下即可:

net = torch.nn.DataParallel(model)

这时,默认所有存在的显卡都会被使用

2. 指定编号使用显卡

如果有很多显卡(例如我们有4张显卡),但只想使用0、1、2号显卡,那么可以:

net = torch.nn.DataParallel(model, device_ids=[0, 1, 2])

或者:

os.environ["CUDA_VISIBLE_DEVICES"] = ','.join(map(str, [0,1,2])) # 一般在程序开头设置
# 等价于os.environ["CUDA_VISIBLE_DEVICES"] = '0,1,2'
net = torch.nn.DataParallel(model)

CUDA_VISIBLE_DEVICES 表示当前可以被python环境程序检测到的显卡


如果只需要指定一张卡,可以使用torch.cuda.set_device(1)指定gpu使用编号
(不建议用这个方法)

torch.cuda.set_device(1)
print(torch.cuda.device_count()) #可用GPU数量

(我的机器是4卡,所以print结果是:4,说明用torch.cuda.set_device(1)指定,不会改变可见的显卡)
后面还可以用torch.nn.DataParallel(model, device_ids=[1, 2])进行指定,但是必须包含set_device(1)指定的device:1的设备,缺点是仍然会存在占用一些device:0的gpu内存;

3. os.environ[“CUDA_VISIBLE_DEVICES”]详解

3.1. [“CUDA_VISIBLE_DEVICES”]使用

CUDA_VISIBLE_DEVICES 表示当前可以被python环境程序检测到的显卡

os.environ["CUDA_VISIBLE_DEVICES"] = ','.join(map(str, [0,1,2])) # 一般在程序开头设置
# 等价于os.environ["CUDA_VISIBLE_DEVICES"] = '0,1,2'

 

os.environ["CUDA_VISIBLE_DEVICES"] = '1,2'进行指定使用设备
这样会修改pytorch感受的设备编号,pytorch感知的编号还是从device:0开始。如上则把1号显卡改为device:0,1号显卡改为device:1,使用时应该这么写:

os.environ["CUDA_VISIBLE_DEVICES"] = '1,2'
torch.nn.DataParallel(model, device_ids=[0,1])

3.2. 关于设置[“CUDA_VISIBLE_DEVICES”]无效的解决

不生效的原因是,这一行代码放置的位置不对。
一定要把os.environ['CUDA_VISIBLE_DEVICES']='1'放在所有访问GPU的代码之前。

torch.cuda.device_count()

4. torch.cuda主要函数

4.1. torch.cuda.is_available()判断GPU是否可用

import torch
print(torch.cuda.is_available())

可用即为:True

4.2. torch.cuda.device_count()查看可用GPU数量

os.environ["CUDA_VISIBLE_DEVICES"] = '0,1,2'
print(torch.cuda.device_count())

结果应该为:3

4.3. torch.cuda.current_device()查看当前使用的GPU序号

os.environ["CUDA_VISIBLE_DEVICES"] = '1,2'
print(torch.cuda.current_device())

结果应该是:0
这样就证明了我们上面说的,os.environ["CUDA_VISIBLE_DEVICES"] = '1,2'进行指定使用设备,会修改pytorch感受的设备编号,pytorch感知的编号还是从device:0开始

4.4 其他一些函数

查看指定GPU的容量、名称

torch.cuda.get_device_capability(device)
torch.cuda.get_device_name(device)

清空程序占用的GPU资源

torch.cuda.empty_cache()

为GPU设置随机种子

torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)

5. 报错AssertionError: Invalid device id

对模型进行gpu指定编号多gpu训练,必须要有所指定编号的gpu,不然会报AssertionError: Invalid device id错误

报错示例1:

os.environ["CUDA_VISIBLE_DEVICES"] = '0,1' # 一般在程序开头设置
net = torch.nn.DataParallel(model,device_ids=[1, 2])

CUDA_VISIBLE_DEVICES 表示当前可以被python环境程序检测到的显卡,可见的只有0,1号显卡。
而使用torch.nn.DataParallel(model, device_ids=[1, 2])指定gpu编号会出现AssertionError: Invalid device id错误
原因:2号显卡没有设置被可见。

报错示例2:

os.environ["CUDA_VISIBLE_DEVICES"] = '1,2' # 一般在程序开头设置
net = torch.nn.DataParallel(model,device_ids=[1, 2])

os.environ["CUDA_VISIBLE_DEVICES"] = '1,2'进行指定使用设备
这样会修改pytorch感受的设备编号,pytorch感知的编号还是从device:0开始
程序应该这么改:

os.environ["CUDA_VISIBLE_DEVICES"] = ','.join(map(str, [1,2])) # 一般在程序开头设置
net = torch.nn.DataParallel(model,device_ids=[0, 1])

6. 报错RuntimeError: module must have its parameters and buffers on device cuda:1 (device_ids[0]) but found

PyTorch框架下,使用torch.nn.DataParallel进行多卡并行计算中可能会遇到该问题,是由于在多卡运算时主卡设置所导致。在多卡并行计算时,所使用的显卡中必须包含主卡,否则就会产生该问题。

如下代码中,主卡没有参与运算,就会导致该错误。

os.environ["CUDA_VISIBLE_DEVICES"] = '0,1,2,3' #这里主卡就是机器0号卡
model = torch.nn.DataParallel(model, device_ids=[1,2,3]).cuda()
<think>我们正在讨论如何设置环境变量CUDA_VISIBLE_DEVICES使用GPU(例如&#39;0,1&#39;)。根据引用[1]和引用[2],我们可以通过种方式设置这个环境变量。 目标:设置CUDA_VISIBLE_DEVICES环境变量为&#39;0,1&#39;,使得程序能够使用第0号和第1号GPU。 方法: 1. 临时设置(在命令行中设置,仅对当前会话有效) 2. Python运行时设置(在代码中设置) 3. 永久设置(修改系统配置文件) 注意:设置环境变量必须在程序使用CUDA之前进行,否则设置可能无效。 下面详细介绍每种方法: ### 1. 临时设置(命令行中设置) 在运行程序之前,在命令行中设置环境变量。 - **Linux/macOS**: ```bash export CUDA_VISIBLE_DEVICES=0,1 python your_script.py ``` 或者写在一行: ```bash CUDA_VISIBLE_DEVICES=0,1 python your_script.py ``` - **Windows (命令提示符)**: ```cmd set CUDA_VISIBLE_DEVICES=0,1 python your_script.py ``` 或者使用PowerShell: ```powershell $env:CUDA_VISIBLE_DEVICES="0,1" python your_script.py ``` ### 2. Python运行时设置 在Python脚本的开头(在导入任何使用CUDA的库之前)设置环境变量。 ```python import os os.environ["CUDA_VISIBLE_DEVICES"] = "0,1" # 设置可见的GPU为0和1 # 然后导入其他库 import torch ... # 验证设置 print("可见的GPU数量:", torch.cuda.device_count()) # 应该输出2 ``` 注意:必须在导入任何使用CUDA的库(如PyTorch、TensorFlow)之前设置,否则可能无效。 ### 3. 永久设置 将环境变量设置添加到系统配置文件中,这样每次启动终端都会自动设置。 - **Linux/macOS**: 在用户主目录下的`.bashrc`(或`.zshrc`,如果你使用zsh)文件中添加: ```bash export CUDA_VISIBLE_DEVICES=0,1 ``` 然后运行`source ~/.bashrc`(或`source ~/.zshrc`)使其立即生效。 - **Windows**: 1. 打开“系统属性”(可以通过右键点击“此电脑”->“属性”->“高级系统设置”) 2. 点击“环境变量”按钮 3. 在“用户变量”或“系统变量”中,点击“新建” 变量名:`CUDA_VISIBLE_DEVICES` 变量值:`0,1` 4. 点击“确定”保存,并重启所有命令行窗口。 ### 验证设置 无论使用哪种方法,设置后都可以在程序中验证: ```python import torch print(torch.cuda.device_count()) # 应该输出2,表示可见的GPU数量 print(torch.cuda.get_device_name(0)) # 输出第一块GPU的名称 print(torch.cuda.get_device_name(1)) # 输出第二块GPU的名称 ``` 注意:在设置了`CUDA_VISIBLE_DEVICES`后,程序中的GPU索引会重新映射。例如,物理上的GPU0和GPU1在程序中会被视为`cuda:0`和`cuda:1`,而其他GPU则不可见。 ### 重要提醒 - 设置环境变量后,程序只会看到指定的GPU。例如,设置`CUDA_VISIBLE_DEVICES=0,1`,那么程序会认为只有两块GPU(索引0和1),而这两块GPU实际上对应物理GPU0和1。 - 在PyTorch中,如果使用GPU训练(如`DataParallel`或`DistributedDataParallel`),通常需要设置这个环境变量或者通过`torch.cuda.set_device`来指定设备。 ### 相关问题 1. 如何查看当前系统中有哪些可用的GPU? 2.PyTorch中如何使用GPU进行数据并行训练? 3. 如何在不同GPU上运行不同的程序? 4. 设置CUDA_VISIBLE_DEVICES后,为什么程序还是使用了未指定的GPU? 5. 如何在Docker容器中设置CUDA_VISIBLE_DEVICES? 希望这些信息能帮助你设置GPU环境。</think>在深度学习或并行计算中,通过设置环境变量 `CUDA_VISIBLE_DEVICES` 使用GPU(如 &#39;0,1&#39;)的详细方法如下: --- ### 一、核心原理 设置 `CUDA_VISIBLE_DEVICES="0,1"` 会: 1. 仅使物理 GPU 0 和 1 对程序可见 2. 在程序中重映射为逻辑设备 `cuda:0` 和 `cuda:1` 3. 隐藏其他所有 GPU(如物理 GPU 2,3 等不可访问)[^1][^2] --- ### 二、三种设置方法 #### 方法1:命令行临时设置(推荐) **Linux/macOS**: ```bash CUDA_VISIBLE_DEVICES=0,1 python your_script.py ``` **Windows CMD**: ```cmd set CUDA_VISIBLE_DEVICES=0,1 && python your_script.py ``` **Windows PowerShell**: ```powershell $env:CUDA_VISIBLE_DEVICES="0,1"; python your_script.py ``` > ✅ 优点:无需修改代码,进程级隔离 > ⚠️ 注意:必须在首次调用 CUDA 前设置[^2] --- #### 方法2:Python 代码内设置 ```python import os os.environ["CUDA_VISIBLE_DEVICES"] = "0,1" # 必须在导入torch前设置! import torch print(f"可见GPU数量: {torch.cuda.device_count()}") # 输出2 # 验证设备映射 print(torch.cuda.get_device_name(0)) # 物理GPU0的名称 print(torch.cuda.get_device_name(1)) # 物理GPU1的名称 ``` > ✅ 适用场景:需要动态控制GPU的代码 > ⚠️ 警告:必须在导入任何 CUDA 相关库前设置[^2] --- #### 方法3:系统永久设置 **Linux/macOS**: 1. 编辑 `~/.bashrc` 或 `~/.zshrc` 2. 添加:`export CUDA_VISIBLE_DEVICES="0,1"` 3. 执行 `source ~/.bashrc` **Windows**: 1. Win+R → 输入 `sysdm.cpl` → 高级 → 环境变量 2. 新建系统变量: - 变量名:`CUDA_VISIBLE_DEVICES` - 变量值:`0,1` 3. 重启所有终端 > ✅ 优点:对所有程序生效 > ⚠️ 注意:可能影响其他 CUDA 应用 --- ### 三、关键验证步骤 1. **查看实际设备映射**: ```python import torch print(torch.cuda.device_count()) # 应输出2 print(torch.cuda.get_device_name(0)) # 物理GPU0的名称 print(torch.cuda.get_device_name(1)) # 物理GPU1的名称 ``` 2. **监控 GPU 使用**: ```bash watch -n 1 nvidia-smi # Linux实时监控 ``` 输出应显示只有 GPU 0 和 1 有活动进程 --- ### 四、使用场景示例 #### GPU 数据并行训练 (PyTorch) ```python import torch import torch.nn as nn # 设置可见GPU(或在命令行设置) os.environ["CUDA_VISIBLE_DEVICES"] = "0,1" model = MyModel() if torch.cuda.device_count() > 1: print(f"使用 {torch.cuda.device_count()} 块GPU") model = nn.DataParallel(model) # 自动并行到所有可见GPU model.to(&#39;cuda&#39;) # 自动使用cuda:0和cuda:1 ``` --- ### 五、常见问题解决 1. **设置无效**: - 确认在导入 CUDA 库前设置 - 检查 GPU 索引是否有效(`nvidia-smi` 验证) - 重启终端/IDE 使环境变量生效 2. **显存不足**: ```python # 清空显存缓存 torch.cuda.empty_cache() ``` 3. **设备映射混乱**: ```python # 明确指定设备 device0 = torch.device("cuda:0") device1 = torch.device("cuda:1") ``` --- ### 六、最佳实践建议 1. 优先使用命令行设置(避免代码硬编码) 2. GPU 训练时配合 `torch.nn.DataParallel` 3. 复杂任务使用 `torch.distributed` 替代 `DataParallel` 4. 监控工具推荐: - `gpustat`(Linux) - `nvitop`(跨平台) > 注意:`CUDA_VISIBLE_DEVICES` 是 CUDA 底层机制,适用于 PyTorch、TensorFlow 等所有 CUDA 加速框架[^1][^2]。 --- ### 相关问题 1. 如何查看当前系统中所有可用的 GPU 设备信息? 2. PyTorch 中 `DataParallel` 和 `DistributedDataParallel` 有何区别? 3.GPU 显存不足时,有哪些优化策略? 4. 如何在 Docker 容器中正确配置 GPU 环境? 5. GPU 训练时如何实现负载均衡?
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值