关于caffe的python写的层多GPU训练
http://blog.csdn.net/chengqishang110/article/details/52355986
之前训练faster的时候一直没有办法进行多GPU训练,以为是自己的错,今天看了/include/caffe/layers/python_layer.h发现原来这是caffe的缘故。
原来caffe在写的时候就不允许python使用多GPU训练。
深入分析:
其是主要的是python的缘故。
这里提到一个GIL。这里的GIL是 Python 的Global Interpreter Lock (全局解释器锁) 一次只允许一个thread在python解释器中运行。
什么是全局解释器锁呢?
Python代码的执行由Python虚拟机(也叫解释器主循环)来控制。Python在设计之初就考虑到要在主循环中,同时至于一个线程在执行,就像但CPU的系统中运行多个进程那样,内存中可以存放多个程序,但在任意时刻,只有一个程序在CPU中运行。同样地,虽然Python解释器可以“运行”多个线程,但在任意时刻,只有一个线程在解释器中运行。
对Python虚拟机的访问由全局解释器锁(global interpreter lock GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。在多线程环境中,Python虚拟机按以下方式执行。
- 设置GIL
- 切换到一个线程运行。
-
运行:
a. 指定数量的字节码的指令,或者
b. 线程主动让出控制(可以调用time.sleep(0)) -
把线程设置为睡眠状态。
- 解锁GIL。
- 再次重复以上所有步骤。
在调用外部代码(如C/C++扩展函数)的时候,GIL将会被锁定,知道这个函数结束为止(由于在这期间没有Python的字节码被运行,所以不会有线程切换)。编写拓展的程序员可以主动解锁GIL。不过,Python的开发人员则不用担心在这些情况下你的Python代码会被锁住【1】。
那解决办法是什么呢?就这样认命么?NO!
高手总是有的。
方案1:https://github.com/BVLC/caffe/issues/2936
提供者:naibaf7 Berkeley Vision and Learning Center member
release the GIL for the forward/backward passes in the OpenCL branch。
方案2:https://github.com/BVLC/caffe/pull/4360
提供者:alessandroferrari
Added ScopedGILRelease for easy GIL release. Modified _caffe.cpp in pycaffe accordingly.
参考文献:
【1】Python核心编程(第二版)
====================================================================================================================================================================================================
http://www.caffecn.cn/?/question/85
现在的caffe版本已经支持多GPU并行了,原理比较简单,就是每个GPU分别算一个batch,n个GPU,实际的batchsize就是n*batch,比如原来用一个GPU,batchsize设置成256,现在用4个GPU,把batchsize设置成64,和原来的一个GPU的运算是等价的。
实际使用的时候基本不用设置,和原来一样编译好就可以用了。命令就是在-gpu 后面对多个GPU号用逗号隔开,比如-gpu 1,2,3,4 就是同时使用1-4共4个GPU,GPU编号可以不连续,或者直接用-gpu all,就是使用所有的GPU。
官方的github里是这样写的
正好我也在用顺手截图
可以看到输出的log里提示了使用了两个GPU
如果你原来的batchsize是32 现在两个GPU 就改成16
====================================================================================================================================================================================================
我有三个显卡,当我使用命令 -gpu all时会出错,而使用-gpu 0,2时能正常运行,但是在log输出力我看到了
I0119 09:22:49.801615 8412 parallel.cpp:245] GPU 2 does not have p2p access to GPU 0
这个信息,意思是不是有问题?源码是parallel.cpp里的
好像2个GPU的话,组成[-1,0;0,1]两个pairs,GPU树深为1,构建两个sync,四个的话就是[-1,0;0,1;2,3;0,2],GPU树深为2,构建4个sync,三个的话应该是不行的,5个应该也是不行。。。奇数不行。。。而 I0119 09:22:49.801615 8412 parallel.cpp:245] GPU 2 does not have p2p access to GPU 0 这个输出跟GPU的个数没关系
====================================================================================================================================================================================================
https://www.zhihu.com/question/53580158
问:我用-gpu 0,-gpu 2和-gpu 0,2这三种的运行时间几乎一样,好像并没有什么并行加速效果
支持多GPU并行训练。但是单次迭代所用时间会略微加长,caffe并行主要用来拓展minibatch大小的。
问:也就是说是在保证精度的前提下,提高minibatch,从而加速???可以这样理解吗??
caffe只能这么并行提高minibatch size,把一个epoch耗时缩减到原来的 显卡数分之一。因为单次更新参数使用的样本大量增加,可以适当提高下学习率并让它加速衰减。
问:我测试下来GPU数量越多速度越慢。。什么鬼。。
卡数越多会导致梯度同步的耗时变大,目前caffe只提供了简单的p2p同步,一定程度上解决大网络单卡训练显存不足的情况,对于训练速度上没有什么优化。
====================================================================================================================================================================================================
http://blog.csdn.net/u011394059/article/details/74528849
在训练center-loss 网络时,center-loss 太大,虽然乘以一个很小的系数(0.008),还是导致loss特别大,最后loss为87.3365,为nan。
不断调整参数,最后可以训练了,然后看输出:
在gpu 0 和gpu 2之间没有p2p 交互。
stackoverflow上的problem1,说性能会下降,因为没有用到 SLI bridge,只会导致训练速度的下降,不会带来其他的问题;problem2。
找到了官方的文档multi-gpu解释,在使用多GPU时,性能会跟最差的那一个一致,并且是,实际的batchsize数为网络文件中的batchsize*gpu个数。
没开 p2p dma access 会导致计算性能下降。
使用nvidia-smi topo -m
查看,
====================================================================================================================================================================================================
https://www.zhihu.com/question/59321480
需要重做dataparallel,写bn的kernel,以及用nccl cross gpu通信
链接:https://www.zhihu.com/question/59321480/answer/198077371
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
终于搞定了Synchronized BatchNorm,来回答一下这个问题。
首先针对问题本身,目前所有的framework,包括Caffe,Torch,TF,PyTroch等等,BatchNorm的实现都是只考虑了single gpu。也就是说BN使用的均值和标准差是单个gpu算的,相当于缩小了mini-batch size。至于为什么这样实现,1)因为没有sync的需求,因为对于大多数vision问题,单gpu上的mini-batch已经够大了,完全不会影响结果。2)影响训练速度,BN layer通常是在网络结构里面广泛使用的,这样每次都同步一下GPUs,十分影响训练速度。
关于如何实现,这里不得不写一下心得,从发现问题到实现synchronize,花了将近一周的时间,一开始把这个问题想简单了,希望对大家有所帮助吧。偶然中发现自己做的task十分依赖synchronzie BN (因为在公司实习, 不方便说project)。然后开始实现:
1。 因为通常训练过程是将网络复制到不同的gpu上,然后进行forward和backward,之后只需要collect gradient,再更新主gpu上的网络,然后下一个iteration再复制一遍。在这种方式下,不同gpu的BN layer是没办法通信的。所以第一步是重做了DataParallel架构,可以enable 每层的通信。
2。 第二步就是推推公式,相信各位大神花点儿时间动动笔就搞定,我就不赘述了。然后开始编程写kernel,核心思想是每次forward 时候sync一下均值和方差,然后backward的时候sync一些grad of 均值和方差,再继续backward。
3。本身前两步搞定之后,应该一切顺利了,可是训练的时候总是跑几十个iteration就卡死。这个其实是pytorch autograd engine 的问题, 因为每个BN layer的均值和方差都是cross gpu 的grad graph,而我们又是大量使用BN,所以成个back-prop的graph破坏了pytorch grad engine。解决方案是写一个cross gpu的autograd function来handle。
大体思路是这样的,可能发paper的时候再release。不过大部分task应该不涉及这个题。
低调地update一下,我已经公开了这个PyTorch implementation, 大家可以先用,我过几天放个arxiv paper,链接: Synchronized BatchNorm
请问,synchronize对训练速度的影响具体是怎样的?
请问一下BN的均值和方差是通过moving average计算得到的把?需要在反向传播时更新grad吗?
是当前batch的running均值和方差,accumulated均值和方差只在inference的时候用,请参考这个博客Understanding the backward pass through Batch Normalization Layer
请问是基于什么框架实现的?
用PyTorch写的
你好, 这个有效果的对比吗?采用多GPU的的BN和无同步的BN对比。