单机单卡,单机多卡,多机多卡训练代码

数据并行

PyTorch默认使用从0开始的GPU,且默认只使用0号GPU。如果要使用其他编号的GPU或者使用多块GPU,则要设置。
pytorch并行后,假设batchsize设置为64,表示每张并行使用的GPU都使用batchsize=64来计算(单张卡使用时,使用batchsize=64比较合适时,多张卡并行时,batchsize仍为64比较合适,而不是64*并行卡数)。
DataParallel 会自动拆分数据,并将作业订单发送到多个GPU上的多个模型。 在每个模型完成它们的工作之后,DataParallel 在将结果返回给你之前收集和合并结果。

使用gpu训练的两种代码方式

参考:https://blog.csdn.net/xys430381_1/article/details/106635977
https://blog.csdn.net/zqx951102/article/details/127946871
一、使用环境变量CUDA_VISIBLE_DEVICES的方式
第一步:指定gpu
直接终端中设定:

CUDA_VISIBLE_DEVICES=1 

python代码中设定:
1、使用单卡

import os
os.environ["CUDA_VISIBLE_DEVICES"] = "2"

2、使用多块卡的方法。

import os
os.environ["CUDA_VISIBLE_DEVICES"] = '0,1'

第二步:创建设备(device)
作用:将备选GPU进一步选择和指定,真正投入使用中。

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 注意如果 device = torch.device("cuda"),则环境变量CUDA_VISIBLE_DEVICES中指定的全部GPU都会被拿来使用。
# 也可以通过 "cuda:0" 、"cuda:1"等指定环境变量CUDA_VISIBLE_DEVICES中指定的多块GPU中的某一块。

注意对应关系。例如:

import os
os.environ["CUDA_VISIBLE_DEVICES"] = "2, 3, 4, 5"  # 将2, 3, 4, 5号GPU作为备选GPU

# 这样cuda:0表示使用 2 号GPU
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

第三步,将data和model放置到device上

input = data.to(device)
model = MyModule(...).to(device)
注意:如果有多个GPU,则model还需要多做一个操作(模型并行化)
第三步骤的多GPU版本如下:

input = data.to(device)
model = MyModule(...)
#模型并行化
if torch.cuda.device_count() > 1:
            print("Let's use", torch.cuda.device_count(), "GPUs!")
            model = nn.DataParallel(model)
model = model.to(device)

方法二 函数 set_device + 函数.cuda()

不过官方建议使用CUDA_VISIBLE_DEVICES,不建议使用 set_device 函数。
第一步,函数set_device设置device

import torch
gpu_id = [0, 1, 2]
torch.cuda.set_device(gpu_id)
#运行这里会报错,set_device只能传int,也就是只能用一个gpu训练?

第二部,函数.cuda()使用GPU

data.cuda()
model.cuda()

第二种方法补充:
torch.cuda.set_device(gpu_id)只能指定单个gpu
如果只需要指定一张卡,可以使用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内存;

小试牛刀:
https://github.com/rwightman/pytorch-image-models
训练代码是第二种方式,只能用1个gpu训练。
修改方法一,直接加上一句nn.DataParallel:
原始代码:

model.cuda()

修改为:

if torch.cuda.device_count() > 1:
        print("Let's use", torch.cuda.device_count(), "GPUs!")
        model = nn.DataParallel(model, device_ids=[0, 1])	##指定gpu

model.cuda()

修改前后用nvidia-smi查看gpu使用情况。

修改方法二,较复杂:

os.environ["CUDA_VISIBLE_DEVICES"] = '0,1'      
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
...
# torch.cuda.set_device(args.local_rank)
    if torch.cuda.device_count() > 1:
            print("Let's use", torch.cuda.device_count(), "GPUs!")
            model = nn.DataParallel(model)
    # model.cuda()
    model.to(device)
        # train_loss_fn = train_loss_fn.cuda()
    # validate_loss_fn = nn.CrossEntropyLoss().cuda()

    train_loss_fn = train_loss_fn.to(device)
    validate_loss_fn = nn.CrossEntropyLoss().to(device)
             # input, target = input.cuda(), target.cuda()
            input = input.to(device)
            target = target.to(device)
                 # input = input.cuda()
                # target = target.cuda()
                input = input.to(device)
                target = target.to(device)

方法一不用分布式训练不报错,用分布式训练报错:
RuntimeError: module must have its parameters and buffers on device cuda:0 (device_ids[0]) but found one of them on device: cuda:1
方法二不报错。

你可能感兴趣的:(深度学习)