【Pytorch】服务器Slurm上单/多GPU模型训练及保存加载

一、多GPU模型训练

1、Pytorch多GPU模型训练原理

用简单的话描述一下,以8个GPU为例。首先将模型放到主GPU上,并该模型在其余7个GPU上都复制一份;接着一个batch_size为64的数据传进来时,数据会被分为8份(每份的batch_size为8),这8份数据分别放到8个GPU上;8个GPU分别计算loss,最后loss会被汇总到主GPU上进行反向传播。
在这里插入图片描述

2、Pytorch实现
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

CUDA_DEVICES = 0, 1, 2, 3, 4, 5, 6, 7
os.environ["CUDA_VISIBLE_DEVICES"] = "0, 1, 2, 3, 4, 5, 6, 7"

if torch.cuda.device_count() > 1:
    net = torch.nn.DataParallel(net, device_ids=CUDA_DEVICES)
    cudnn.benchmark = True
net = net.to(device)

这里的的关键就是设置CUDA_DEVICESos.environ["CUDA_VISIBLE_DEVICES"],以及net = torch.nn.DataParallel(net, device_ids=CUDA_DEVICES)
其他就跟单GPU一样可以愉快地训练了。

二、多GPU模型保存和加载

众所周知,多GPU训练的模型和单GPU训练模型的区别在于多了一层module,因此有的说要在保存的时候

torch.save({
            'epoch': epoch,
            'state_dict': net.module.state_dict(),
            'optimizer': optimizer.state_dict(),
            ...
            }, PATH)

如果保存时没有加上module,加载时就要建一个新的字典来读取参数

state_dict = torch.load('checkpoint.pt')  # 模型可以保存为pth文件,也可以为pt文件。
# create new OrderedDict that does not contain `module.`
from collections import OrderedDict
new_state_dict = OrderedDict()
for k, v in state_dict.items():
    name = k[7:]  # remove `module.`,表面从第7个key值字符取到最后一个字符,正好去掉了module.
    new_state_dict[name] = v #新字典的key值对应的value为一一对应的值。 
# load params
model.load_state_dict(new_state_dict) # 重新加载这个模型。

反正我是通通失败了…报错

RuntimeError: Error(s) in loading state_dict for DataParallel:
    Unexpected running stats buffer(s) "module. ...........................

直到我看到了博客 的第3点!统统不要,统统不要,只要在加载模型之前nn.DataParallel了,保存和加载同单GPU训练时一样的。
保存

torch.save({
            'epoch': epoch,
            'state_dict': net.state_dict(),
            'optimizer': optimizer.state_dict(),
            ...
            }, PATH)

加载

checkpoint = torch.load(CHECKPOINT_PATH)
net.load_state_dict(checkpoint['state_dict'])

注:当然也与可能是因为服务器上用了srun命令,这样是可以的。Anyway,前两种方式都值得一试。

三、Slurm命令使用

服务器上用的是Slurm管理系统,就说一下srun命令

srun --partition=XXX
     --mpi=pmi2
     --gres=gpu:8
     -n1
     --ntasks-per-node=1
     --job-name=TEST
     --kill-on-bad-exit=1
     python main.py 

参数说明

  • –gres=gpu:8:使用的GPU数
  • –ntasks-per-node=1:单个节点最多的进程个数
  • -n1:作业总的进程数。首先会根据-n和–ntasks-per-node来决定分配多少个节点,再根据–gres决定每个节点使用的GPU数

四、代码

详细代码release在github上,关于cifar10的训练,支持单/多GPU训练以及模型加载继续训练。

想要用单/多GPU训练,只要修改可见的GPU

CUDA_DEVICES = 0, 1, 2, 3, 4, 5, 6, 7
os.environ["CUDA_VISIBLE_DEVICES"] = "0, 1, 2, 3, 4, 5, 6, 7"

以及srun中的所述三个参数

srun --partition=XXX
     --mpi=pmi2
     --gres=gpu:8
     -n1
     --ntasks-per-node=1
     --job-name=TEST
     --kill-on-bad-exit=1
     python main.py 

想要加载模型继续训练,在代码中修改模型所在文件夹

fold = 'XXXXX' 

然后加入--resume即可

python main.py --resume

Pytorch网站

resources

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyTorch是一个流行的深度学习框架,支持使用单个GPU或多个GPUs进行训练和测试。在使用单个GPU时,需要将模型和数据加载GPU上。使用单个GPU进行训练和测试的示例代码如下: 示例代码如下: ```python #将模型加载GPU device = torch.device('cuda:0') #选择第一个GPU model.to(device) #将数据加载GPU x = x.to(device) y = y.to(device) #在GPU上进行前向传播 y_pred = model(x) #计算损失 loss = criterion(y_pred, y) #在GPU上进行反向传播 loss.backward() #更新权重 optimizer.step() ``` 使用多个GPU可以加快训练和测试的速度。PyTorch提供了两种多GPU的方法:DataParallel和DistributedDataParallel(DDP)。其中,DataParallel是在单台机器上使用多个GPU的方法,而DDP是在多台机器上使用多个GPU的方法。 使用DataParallel时,可以将模型和数据加载到单个GPU上,然后使用torch.nn.DataParallel将模型复制到其他GPU上。使用DataParallel进行训练和测试的示例代码如下: 示例代码如下: ```python #将模型加载GPU device = torch.device('cuda:0') #选择第一个GPU model.to(device) #使用DataParallel将模型复制到其他GPU上 if torch.cuda.device_count() > 1: model = nn.DataParallel(model) #将数据加载GPU x = x.to(device) y = y.to(device) #在GPU上进行前向传播 y_pred = model(x) #计算损失 loss = criterion(y_pred, y) #在GPU上进行反向传播 loss.backward() #更新权重 optimizer.step() ``` 使用DDP时,需要在多台机器上安装PyTorch和NCCL库,并按照官方文档中的说明进行配置。使用DDP进行训练和测试的示例代码如下: ```python #在每个进程中选择一个GPU device = torch.device('cuda', rank % torch.cuda.device_count()) #使用DistributedDataParallel初始化模型 model = nn.parallel.DistributedDataParallel(model, device_ids=[device]) #在GPU上进行前向传播 y_pred = model(x) #计算损失 loss = criterion(y_pred, y) #在GPU上进行反向传播 loss.backward() #更新权重 optimizer.step() ``` 以上就是PyTorch使用单个GPU和多个GPU进行训练和测试的方法。具体使用哪种方法,需要根据硬件和应用场景的要求进行选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值