版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_40087578/article/details/87186613
这里记录用pytorch 多GPU训练 踩过的许多坑   仅针对单服务器多gpu 数据并行 而不是 多机器分布式训练

一、官方思路包装模型

这是pytorch 官方的原理图  按照这个官方的原理图  修改应该参照

https://blog.csdn.net/qq_19598705/article/details/80396325

上文也用dataParallel 包装了optimizer, 对照官方原理图中第二行第二个,将梯度分发出去,将每个模型上的梯度更新(第二行第三个),然后再将更新完梯度的模型参数合并到主gpu(第二行最后一个步骤)

其实完全没必要,因为每次前向传播的时候都会分发模型,用不着反向传播时将梯度loss分发到各个GPU,单独计算梯度,再合并模型。可以就在主GPU 上根据总loss 更新模型的梯度,不用再同步其他GPU上的模型,因为前向传播的时候会分发模型。

所以 上述链接里 不用 dataParallel 包装 optimizer。

DataParallel并行计算只存在在前向传播

总结步骤:

import os
import torch
args.gpu_id="2,7" ; #指定gpu id
args.cuda = not args.no_cuda and torch.cuda.is_available() #作为是否使用cpu的判定
#配置环境 也可以在运行时临时指定 CUDA_VISIBLE_DEVICES='2,7' Python train.py
os.environ['CUDA_VISIBLE_DEVICES'] = args.gpu_id #这里的赋值必须是字符串,list会报错
device_ids=range(torch.cuda.device_count()) #torch.cuda.device_count()=2
#device_ids=[0,1] 这里的0 就是上述指定 2,是主gpu, 1就是7,模型和数据由主gpu分发

if arg.cuda:
model=model.cuda() #这里将模型复制到gpu ,默认是cuda('0'),即转到第一个GPU 2
if len(device_id)>1:
model=torch.nn.DaraParallel(model);#前提是model已经.cuda() 了

#前向传播时数据也要cuda(),即复制到主gpu里
for batch_idx, (data, label) in pbar:
if args.cuda:
data,label= data.cuda(),label.cuda();
data_v = Variable(data)
target_var = Variable(label)
prediction= model(data_v,target_var,args)
#这里的prediction 预测结果是由两个gpu合并过的,并行计算只存在在前向传播里
#前向传播每个gpu计算量为 batch_size/len(device_ids),等前向传播完了将结果和到主gpu里
#prediction length=batch_size

criterion = nn.CrossEntropyLoss()
loss = criterion(prediction,target_var) #计算loss
optimizer.zero_grad()
loss.backward()
optimizer.step()
之后调用model里的函数 继承的函数可以直接调用 例如 model.state_dict() ,model.load_state_dict(torch.load(model_path)......不受影响。但是自己写的函数 要加上.module才行  model.module.forward_getfeature(x)。自己写的函数 不可以并行运算 ,只能在主gpu中运算。DataParallel并行计算仅存在在前向传播。但可以换个思路 写进forward 里或者被forward调用,多返回几个参数不就得了 return feature,predict

二、解决多GPU 负载不均衡的问题
我的经历是主gpu 显存爆了,而其他gpu显存只用了1/5,负载不均衡到不能忍,无法再加大batch_size

参考:https://discuss.pytorch.org/t/dataparallel-imbalanced-memory-usage/22551/20(看了半天的英文才看懂。。。)

负载不均衡的原因是     loss = criterion(prediction,target_var)  计算loss 占用了大量的内存,如果我们让每个gpu单独计算loss,再返回即可解决这个问题  即 prediction,loss=model(data,target)  (#如果后边不用prediction,连prediction也不用返回,只返回loss)。每个gpu返回一个loss,合到主gpu就是一个list,要loss.mean() 或loss.sum(),推荐mean.

这样以来,所有可以在其他gpu中单独计算的都可以写进forward 里,返回结果即可。但要注意 tensor类型的数组 合并len会增加,例如prediction lenth=batchsize,但是loss这种具体的数字,合并就是list了[loss1.loss2]

效果:主GPU 会稍微高一点。多个几百M,  但是基本实现了负载均衡

例子:

#model 里的forward 的函数
def forward(self,x,target_var,args):
feature512=self.forward_GetFeature(x)
if target_var is None:
return feature512;
classifyResult = self.classifier(feature512)
# 如果用DataParallel,forward返回feature 是返回多个GPU合并的结果
# 每个GPU 返回 batchsize/n 个样本,n为GPU数

#计算loss
center_loss = self.get_center_loss(feature512, target_var,args)
criterion = nn.CrossEntropyLoss()
cross_entropy_loss = criterion(classifyResult, target_var)
#CrossEntropyLoss 已经求了softmax 分类结果直接输进去即可

loss = args.center_loss_weight * center_loss + cross_entropy_loss
prec = accuracy(classifyResult.data, target_var, topk=(1,))

# 如果是返回的标量的话,那返回过去就是list,是n个GPU的结果
# 要loss.mean() 之后 在loss.backward()
return prec[0],loss
 
————————————————
版权声明:本文为CSDN博主「lllily」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_40087578/article/details/87186613

pytorch 多GPU训练总结(DataParallel的使用)的更多相关文章

  1. Pytorch多GPU训练

    Pytorch多GPU训练 临近放假, 服务器上的GPU好多空闲, 博主顺便研究了一下如何用多卡同时训练 原理 多卡训练的基本过程 首先把模型加载到一个主设备 把模型只读复制到多个设备 把大的batc ...

  2. pytorch 指定GPU训练

    # 1: torch.cuda.set_device(1) # 2: device = torch.device("cuda:1") # 3:(官方推荐)import os os. ...

  3. pytorch 多GPU训练过程中出现ap=0情况

    原因可能是pytorch 自带的BN bug:安装nvidia apex 可以解决: $ git clone https://github.com/NVIDIA/apex $ cd apex $ pi ...

  4. Pytorch中多GPU训练指北

    前言 在数据越来越多的时代,随着模型规模参数的增多,以及数据量的不断提升,使用多GPU去训练是不可避免的事情.Pytorch在0.4.0及以后的版本中已经提供了多GPU训练的方式,本文简单讲解下使用P ...

  5. Pytorch多GPU并行处理

    可以参数2017coco detection 旷视冠军MegDet: MegDet 与 Synchronized BatchNorm PyTorch-Encoding官方文档对CGBN(cross g ...

  6. Pytorch使用分布式训练,单机多卡

    pytorch的并行分为模型并行.数据并行 左侧模型并行:是网络太大,一张卡存不了,那么拆分,然后进行模型并行训练. 右侧数据并行:多个显卡同时采用数据训练网络的副本. 一.模型并行 二.数据并行 数 ...

  7. PyTorch Tutorials 4 训练一个分类器

    %matplotlib inline 训练一个分类器 上一讲中已经看到如何去定义一个神经网络,计算损失值和更新网络的权重. 你现在可能在想下一步. 关于数据? 一般情况下处理图像.文本.音频和视频数据 ...

  8. MinkowskiEngine多GPU训练

    MinkowskiEngine多GPU训练 目前,MinkowskiEngine通过数据并行化支持Multi-GPU训练.在数据并行化中,有一组微型批处理,这些微型批处理将被送到到网络的一组副本中. ...

  9. Pytorch指定GPU的方法总结

    Pytorch指定GPU的方法 改变系统变量 改变系统环境变量仅使目标显卡,编辑 .bashrc文件,添加系统变量 export CUDA_VISIBLE_DEVICES=0 #这里是要使用的GPU编 ...

随机推荐

  1. Java爬虫的实现

    距离上一次写爬虫还是几年前了,那时候一直使用的是httpclient. 由于最近的项目又需要使用到爬虫,因此又重新查询了一些爬虫相关的框架,其中最合适的是WebMagic 官方文档:https://g ...

  2. python-基础-基础知识-变量-选择-循环

    1 基础知识 1.1 注释的分类 1.2 变量以及类型 变量定义 num1 = 100 #num1就是一个变量,就好一个小菜篮子 num2 = 87 #num2也是一个变量 result = num1 ...

  3. Leetcode447.Number of Boomerangs回旋镖的数量

    给定平面上 n 对不同的点,"回旋镖" 是由点表示的元组 (i, j, k) ,其中 i 和 j 之间的距离和 i 和 k 之间的距离相等(需要考虑元组的顺序). 找到所有回旋镖的 ...

  4. LUOGU P1779 魔鬼杀手_NOI导刊2010提高(03)

    传送门 解题思路 背包,首先先用aoe都打残然后单伤补刀,用f[i]表示AOE打了i的伤害的最小花费,g[i]表示单伤打了i的伤害的最小花费. 代码 #include<iostream> ...

  5. Centos 设置时区

    参考网址: http://jingyan.baidu.com/article/636f38bb268a82d6b84610bd.html //打开设置 tzselect //选择 )Asia → )c ...

  6. Idea代理设置与Java程序的代理设置

    最近在学习WebService的过程中,为了弄清楚发送和接收的包的数据结构,使用Fiddler抓取包的数据.开始先配置了Idea的代理设置,但执行Java代码发送请求时,依然无法在Fiddler中抓取 ...

  7. Linux学习(一):软链接和硬链接

    今天起,决定开始自学Linux命令及Shell脚本,并用Linux学习(命令行,Shell及其他知识点)这一系列记录下自己的心路历程,内容不分先后,只记录自己觉得有必要的,简单的就不记了! 第一个知识 ...

  8. day18 13.乐观锁介绍

    乐观锁是使用版本字段,悲观锁是使用数据库底层的锁机制.mysql的类型timestamp(时间戳)有一个特点:插入数据不用管我,我取系统当前默认值.timestamp插入时间会记录,修改时间也会记录. ...

  9. Laravel(PHP)使用Swagger生成API文档不完全指南 - 基本概念和环境搭建 - 简书

    在PHPer中,很多人听说过Swagger,部分人知道Swagger是用来做API文档的,然而只有少数人真正知道怎么正确使用Swagger,因为PHP界和Swagger相关的资料实在是太少了.所以鄙人 ...

  10. Vue.js @click点击无效?

    原因, 那个点击的元素, 没有在 <div id="app"></div>里面