添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

使用pytorch DDP(DistributedDataParallel,分布式数据并行)可以进行多卡训练,涉及到模型保存与加载问题时,一般会涉及到以下两种需求:

  1. 将多卡训练的模型保存到磁盘。
  2. 从磁盘加载模型,在多卡上继续训练。

如何无bug且高效的解决以上需求 ?(假设训练设备为“单机4卡”)

对于需求1,由于DDP在多卡中维护了相同的模型参数(通过在4张GPU上确保模型初始化以及广播相同的梯度来保证4张卡中的模型参数是完全相同的),因此只需要在其中一张卡保存模型即可:

def save_checkpoint(local_rank, ddp_model, path):
    #只在GPU 0 上保存模型
    if local_rank== 0:
        state = {
            'model': ddp_model.module.state_dict(),
            'optimizer': optimizer.state_dict(),
        torch.save(state, path)

对于需求2,一般会使用torch.load()方法从磁盘加载文件:

def load_checkpoint(path):
    checkpoint = torch.load(path)
    model = Net()
    model.load_state_dict(checkpoint['model'])
    model = DDP(model, device_ids=[gpu])
    return model

但是此时往往会遇到多进程在GPU0上占用过多显存的问题:

使用nvidia-smi命令:

上图中,在所有使用GPU0的进程中,除了PID为62250的进程外,还存在其他三个进程,而这三个进程还分别使用GPU1\2\3。这三个额外进程在GPU0占用了725MB*3的显存空间,这可能会导致GPU0在训练时出现爆显存的问题。

在DDP中,会为每张卡单独创建一个进程:

上图的情况是正常的,每个进程只会使用与其对应的一张显卡。

该问题出现的原因是:torch.load()的不正确使用。

在pytorch对 torch. load() 方法的 官方文档 中,有以下说明:

If map_location is missing, torch.load will first load the module to CPU and then copy each parameter to where it was saved

意思是,如果map_location参数是空的,则torch.load方法会先把模型加载到CPU,然后把模型参数复制到 保存它的地方 (根据上文,保存模型的位置恰好是GPU 0)。

跑在GPU1上的进程在执行到torch.load方法后,会先加载模型到CPU,之后该进程顺理成章地调用GPU0,把一部分数据复制到GPU0,也就出现了前面图中的问题。

与其说是bug,倒不如说没仔细阅读文档。

两种解决方法方法。

一,将map_location指定为CPU:

def load_checkpoint(path):
    #加载到CPU
    checkpoint = torch.load(path,map_location='cpu')
    model = Net()
    model.load_state_dict(checkpoint['model'])
    model = DDP(model, device_ids=[gpu])
    return model

二,将map_location指定为local_rank对应的GPU:

def load_checkpoint(path):
    #加载到CPU
    checkpoint = torch.load(path,map_location='cuda:{}'.format(local_rank))
    model = Net()
    model.load_state_dict(checkpoint['model'])
    model = DDP(model, device_ids=[gpu])
    return model
本文主要解决 pytorch 在进行 模型 训练 出现 GPU 的0卡 占用 显存 比其他卡要多的 问题 。 如下图所示:本机 GPU 卡为TITAN RTX, 显存 24220M,batch_size = 9,用了三张卡。第0卡 显存 占用 24207M,这 仅仅是刚开始运行,数据只是少量的移到显卡上,如果数据在多点,0卡的 显存 肯定撑爆。 出现 0卡 显存 更高的原因:网络在反向传播的 候,计算loss的梯度默认都在0卡上计算。因此会比其他显卡多用一些 显存 ,具体多用多少,主要还要看网络的结构。 因此,为了防止训练由于 out of memory
某次训练 深度学习 模型 使用 *** roberta-large 模型 作为基础模块,起初 使用 DataParallel *** 的方式,进行单机多卡训练,卡数为2,每张卡 显存 为10G。 训练期间发现,无法 使用 较大的batch_size,batch_size最大为4。同 ,训练 间增加到3个小 一个epoch, 间开销太大。 观察 GPU 利用 显存 率,0卡 占用 显存 明显比1卡 占用 的要多,这也是*** DataParallel *** 这种模式的弊端。 *** DataParallel *** 数据传输过程包括: 模型 并行 模型 并行主要应用于 模型 相比 显存 来说更大,一块 device 无法 加载 的场景,通过把 模型 切割为几个部分,分别 加载 到不同的 device 上。比如早期的 AlexNet,当 限于显卡, 模型 就是分别 加载 在两块显卡上的。 这个是日常会应用的比较多的情况。每一个 device 上会 加载 一份 模型 ,然后把数据分发到每个 device 并行进行计算,加快训练速度。 如果要再细分,又可以分
感谢知乎作者 https://www.zhihu.com/question/67209417/answer/866488638 在 使用 DDP 进行单机多卡分布式训练 出现 了在 加载 预训练权重 显存 不够的现象,但是相同的代码单机单卡运行并不会 出现 问题 ,后来发现是在多卡训练 ,额外 出现 了3个进程同 占用 了0卡的部分 显存 导致的,而这3个进程正是另外3张卡load进来的数据,默认这些数据被放在了0卡上。解决的方法是把load进来的数据放在cpu(也就是内存)里。 # 原来代码,load进的数据放在 gpu 里 # pre
1. 搭建自己的简单二分类网络, 使用 pytorch 训练和测试; 2. 将 pytorch 训练的pth 模型 转换成ONNX,并编码测试; 3. 含训练和测试数据,含训练ok的pth 模型 和ONNX 模型 ,含完整python和C++实现; 4. 使用 方法:首先运行“TrainTestConvertOnnx.py”执行“训练数据读入、 模型 训练、 模型 测试、导出onnx”,再运行“TestOnnx.cpp”测试onnx(需要配置OpenCV);
在公司用多卡训练 模型 ,得到权值文件后保存,然后回到实验室,没有多卡的环境,用单卡训练, 加载 模型 出错,因为单卡机器上,没有 使用 DataParallel来 加载 模型 ,所以会 出现 加载 错误。 DataParallel包装的 模型 在保存 ,权值参数前面会带有module字符,然而自己在单卡环境下,没有用DataParallel包装的 模型 权值参数不带module。本质上保存的权值文件是一个有序字典。 1.在单卡环境下,用DataParallel包装 模型 。 2.自己重写Load函数,灵活。 from collections import OrderedDict def myOwnLoa
如果在python内调用 pytorch 有可能 显存 GPU 占用 不会被自动释放,此 需要加入如下代码 torch.cuda.empty_cache() 我们来看一下官方文档的说明 Releases all unoccupied cached memory currently held by the caching allocator so that those can be used in other GPU application and visible in nvidia-smi. empty_cache() doesn’t increase the amount of GPU me
问题 描述 首先说明: 由于我的测试集很大, 因此需要对测试集进行分批次推理. 在写代码的 候发现进行训练的 候大概 显存 占用 了2GB左右, 而且训练过程中 显存 占用 量也基本上是不变的. 而在测试的 候, 发现 显存 在每个batch数据推理后逐渐增加, 直至最后导致爆 显存 , 程序fail. 这里放一下我测试的代码: y, y_ = torch.Tensor(), torch.Tensor() for batch in tqdm(loader): x, batch_y =
PyTorch 是一个流行的 深度学习 框架,支持 使用 单个 GPU 或多个 GPU s进行训练和测试。在 使用 单个 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 进行训练和测试的方法。具体 使用 哪种方法,需要根据硬件和应用场景的要求进行选择。
玩转CIFAR10—Pytorch复现LeNet,AlexNet,VGG,GoogLeNet,MobileNet,ResNet,DenseNet,Vision Transformer等模型(持续更新) 在VS Code中使用jupyter notebook,输出过多时show more显示不正常,出现乱码问题的解决方案