Pytorch中多GPU训练指北
前言
在数据越来越多的时代,随着模型规模参数的增多,以及数据量的不断提升,使用多GPU去训练是不可避免的事情。Pytorch在0.4.0及以后的版本中已经提供了多GPU训练的方式,本文简单讲解下使用Pytorch多GPU训练的方式以及一些注意的地方。
这里我们谈论的是单主机多GPUs训练,与分布式训练不同,我们采用的主要Pytorch功能函数为DataParallel而不是DistributedParallel,后者为多主机多GPUs的训练方式,但是在实际任务中,两种使用方式也存在一部分交集。

使用方式
使用多卡训练的方式有很多,当然前提是我们的设备中存在两个及以上的GPU:使用命令nvidia-smi查看当前Ubuntu平台的GPU数量(Windows平台类似),其中每个GPU被编上了序号:[0,1]:

在我们设备中确实存在多卡的条件下,最简单的方法是直接使用torch.nn.DataParallel将你的模型wrap一下即可:
net=torch.nn.DataParallel(model)
这时,默认所有存在的显卡都会被使用。
如果我们机子中有很多显卡(例如我们有八张显卡),但我们只想使用0、1、2号显卡,那么我们可以:
net=torch.nn.DataParallel(model,device_ids=[0,1,2])
或者这样:

很简单的操作,这样我们就可以比较方便地使用多卡进行训练了。
另一种方法
在前言中提到过,另一种方法DistributedParallel,虽然主要的目标为分布式训练,但也是可以实现单主机多GPU方式训练的,只不过比上一种方法稍微麻烦一点,但是训练速度和效果比上一种更好。
为什么呢?
请看官方相关介绍:

nccl backend is currently the fastest and highly recommended backend to be used with Multi-Process Single-GPU distributed training and this applies to both single-node and multi-node distributed training
好了,来说说具体的使用方法(下面展示一个node也就是一个主机的情况)为:

上述的命令和我们平常的命令稍有区别,这里我们用到了torch.distributed.launch这个module,我们选择运行的方式变换为python -m,上面相当于使用torch.distributed.launch.py去运行我们的YOUR_TRAINING_SCRIPT.py,其中torch.distributed.launch会向我们的运行程序传递一些变量。
为此,我们的YOUR_TRAINING_SCRIPT.py也就是我们的训练代码中这样写(省略多余代码,只保留核心代码):

我们要注意,上述代码在运行的过程中产生了很多个,具体多少个取决你GPU的数量,这也是为什么上面需要torch.cuda.set_device(args.local_rank)设定默认的GPU,因为torch.distributed.launch为我们触发了n个YOUR_TRAINING_SCRIPT.py进程,n就是我们将要使用的GPU数量。
有一点想问的,我们每次必须要使用命令行的方式去运行吗?当然也可以一键解决,如果我们使用Pycharm,只需要配置成下面这样就可以了:

单显卡与DataParallel多显卡训练对比
最近两天训练一个魔改的mobilenetv2+yolov3,同样的优化方法同样的学习率衰减率,所有的参数都相同的情况下,发现单显卡训练的方式竟然比多显卡训练的方式收敛更快。
配置为两张1080Ti,使用Pytorch的版本为1.0.0。下图红线为使用一张1080Ti训练的情况,蓝线为使用两张1080Ti训练的情况,batchsize每张显卡设置为10,也就是说,使用两张显卡训练时的batchsize为单张显卡的两倍,同一个step时,双卡走的步数为单卡步数的两倍。这里使用的多卡训练方式为DataParallel。
但是下图可以看到,在双卡相同step的情况下,虽然红色曲线的损失相较蓝色下降的稍微慢一些,但是到了一定时候,两者的损失值会相交(此时未达到最低损失点),也就是说使用双卡和单卡训练时候loss损失收敛的速度是一样的。

更奇怪的是,下图中,在验证集中,单显卡虽然没有双显卡的准确度曲线增长迅速,但是到了某一点,单显卡的曲线会超过双显卡训练的精度,也就是说,单卡训练在前期没有双卡训练效果显著,但是到了训练中期效果就会优于双卡。

(上述两个图为训练早期和中期的展示,并没有完全训练完毕)关于为什么会这样的情况,有可能是因为训练中期所有的激活值更新幅度不是很明显(一般来说,权重值和激活值更新幅度在训练前期比较大),在不同GPU转化之间会损失一部分精度?。当然这仅仅是猜测,博主还没有仔细研究这个问题,待有结论时会在这里进行更新。
注意点
多GPU固然可以提升我们训练的速度,但弊端还有有一些的,有几个我们需要注意的点:
多个GPU的数量尽量为偶数,奇数的GPU有可能会出现中断的情况
选取与GPU数量相适配的数据集,多显卡对于比较小的数据集来说反而不如单个显卡训练的效果好
多GPU训练的时候注意机器的内存是否足够(一般为使用显卡显存x2),如果不够,建议关闭pin_memory(锁页内存)选项。
采用DistributedDataParallel多GPUs训练的方式比DataParallel更快一些,如果你的Pytorch编译时有nccl的支持,那么最好使用DistributedDataParallel方式。
关于什么是锁页内存:
pin_memory就是锁页内存,创建DataLoader时,设置pin_memory=True,则意味着生成的Tensor数据最开始是属于内存中的锁页内存,这样将内存的Tensor转义到GPU的显存就会更快一些。
主机中的内存,有两种存在方式,一是锁页,二是不锁页,锁页内存存放的内容在任何情况下都不会与主机的虚拟内存进行交换(注:虚拟内存就是硬盘),而不锁页内存在主机内存不足时,数据会存放在虚拟内存中。显卡中的显存全部是锁页内存,当计算机的内存充足的时候,可以设置pin_memory=True。当系统卡住,或者交换内存使用过多的时候,设置pin_memory=False。因为pin_memory与电脑硬件性能有关,pytorch开发者不能确保每一个炼丹玩家都有高端设备,因此pin_memory默认为False。
作者:我爱学python
链接:https://www.jianshu.com/p/bb28669018b3
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
Pytorch中多GPU训练指北的更多相关文章
- Pytorch:使用GPU训练
1.模型转为cuda gpus = [0] #使用哪几个GPU进行训练,这里选择0号GPU cuda_gpu = torch.cuda.is_available() #判断GPU是否存在可用 net ...
- pytorch中查看gpu信息
其他:windows使用nvidia-smi查看gpu信息 为什么将数据转移至GPU的方法叫做.cuda而不是.gpu,就像将数据转移至CPU调用的方法是.cpu?这是因为GPU的编程接口采用CUDA ...
- 转pytorch中训练深度神经网络模型的关键知识点
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_42279044/articl ...
- pytorch 多GPU训练总结(DataParallel的使用)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/weixin_40087578/artic ...
- Pytorch多GPU训练
Pytorch多GPU训练 临近放假, 服务器上的GPU好多空闲, 博主顺便研究了一下如何用多卡同时训练 原理 多卡训练的基本过程 首先把模型加载到一个主设备 把模型只读复制到多个设备 把大的batc ...
- pytorch中如何使用预训练词向量
不涉及具体代码,只是记录一下自己的疑惑. 我们知道对于在pytorch中,我们通过构建一个词向量矩阵对象.这个时候对象矩阵是随机初始化的,然后我们的输入是单词的数值表达,也就是一些索引.那么我们会根据 ...
- PyTorch在NLP任务中使用预训练词向量
在使用pytorch或tensorflow等神经网络框架进行nlp任务的处理时,可以通过对应的Embedding层做词向量的处理,更多的时候,使用预训练好的词向量会带来更优的性能.下面分别介绍使用ge ...
- [源码解析] PyTorch 如何使用GPU
[源码解析] PyTorch 如何使用GPU 目录 [源码解析] PyTorch 如何使用GPU 0x00 摘要 0x01 问题 0x02 移动模型到GPU 2.1 cuda 操作 2.2 Modul ...
- pytorch中tensorboardX的用法
在代码中改好存储Log的路径 命令行中输入 tensorboard --logdir /home/huihua/NewDisk1/PycharmProjects/pytorch-deeplab-xce ...
随机推荐
- HDU 2639 第K大背包问题
//状态方程和01背包类似,dp[j][k]表示背包容量为j的第k大背包的值.......... //应当注意的是此时dp[j][1.....k]应当是递减的.................... ...
- 【Pyqt5】自定义信号简单原理(易懂版),多窗口交互,传输数据,调用方法
PS:如果你想在2窗口调用1窗口的内部方法,或者在2窗口传递数据给1窗口数据,本片博客可以放心食用 主窗口: class MainWindow(QWidget,Ui_MainFrom): insert ...
- koa上传excel文件并解析
1.中间键使用 koa-body npm install koa-body --save const koaBody = require('koa-body'); app.use(koaBody({ ...
- 7 种 Javascript 常用设计模式学习笔记
7 种 Javascript 常用设计模式学习笔记 由于 JS 或者前端的场景限制,并不是 23 种设计模式都常用. 有的是没有使用场景,有的模式使用场景非常少,所以只是列举 7 个常见的模式 本文的 ...
- 三.BP神经网络
BP神经网络是包含多个隐含层的网络,具备处理线性不可分问题的能力.以往主要是没有适合多层神经网络的学习算法,,所以神经网络的研究一直处于低迷期. 20世纪80年代中期,Rumelhart,McClel ...
- 【JZOJ4811】【NOIP2016提高A组五校联考1】排队
题目描述 输入 输出 样例输入 5 4 1 2 1 3 3 4 3 5 1 4 2 4 1 2 2 5 样例输出 3 1 1 2 数据范围 样例解释 解法 可推知原树可以转换为一个序列,即优先序列: ...
- echarts radar 一些会用到了的功能记录
点击雷达图小标题进行相应操作 // options中添加,坐标轴的标签是否响应和触发鼠标事件,默认不响应. radar:{ triggerEvent: true } // 添加监听事件, 点击雷达图标 ...
- postman常用公共函数
常用公共函数: 1).判断是否超时(assertNotTimeout):var hasResponse=postman.getResponseHeader('Content-Type')?true:f ...
- iOS 9 学习系列:UIStack View
http://www.cocoachina.com/ios/20150921/13492.html 在 iOS9 中,Apple 引入了 UIStackView,他让你的应用可以通过简单的方式,纵向或 ...
- QT UI 线程为什么卡死?
我的工程是由三个线程处理不同任务构成的,其中UI用于显示,还有数据处理和数据接收发送线程. 在运行的过程中发现由于数据处理线程不及时,超过了设定的100ms,导致UI卡死,几个周期后又恢复,接着又卡死 ...