关于caffe的python写的层多GPU训练


关于caffe的python写的层多GPU训练

http://blog.csdn.net/chengqishang110/article/details/52355986

之前训练faster的时候一直没有办法进行多GPU训练,以为是自己的错,今天看了/include/caffe/layers/python_layer.h发现原来这是caffe的缘故。 
python_layer.h 
原来caffe在写的时候就不允许python使用多GPU训练。

深入分析:

其是主要的是python的缘故。 
这里提到一个GIL。这里的GIL是 Python 的Global Interpreter Lock (全局解释器锁) 一次只允许一个thread在python解释器中运行。

什么是全局解释器锁呢?

Python代码的执行由Python虚拟机(也叫解释器主循环)来控制。Python在设计之初就考虑到要在主循环中,同时至于一个线程在执行,就像但CPU的系统中运行多个进程那样,内存中可以存放多个程序,但在任意时刻,只有一个程序在CPU中运行。同样地,虽然Python解释器可以“运行”多个线程,但在任意时刻,只有一个线程在解释器中运行。

对Python虚拟机的访问由全局解释器锁(global interpreter lock GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。在多线程环境中,Python虚拟机按以下方式执行。

  1. 设置GIL
  2. 切换到一个线程运行。
  3. 运行: 
    a. 指定数量的字节码的指令,或者 
    b. 线程主动让出控制(可以调用time.sleep(0))

  4. 把线程设置为睡眠状态。

  5. 解锁GIL。
  6. 再次重复以上所有步骤。 
    在调用外部代码(如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里是这样写的

1.jpg


正好我也在用顺手截图

2.jpg


可以看到输出的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对训练速度的影响具体是怎样的?

张航
张航 (作者) 回复openblack (提问者)4 个月前
您问的是实现的效率问题吗,我的implemention,4卡是时候慢了20%,主要慢在了synchronization上了
GuangxingHan
GuangxingHan3 个月前

请问一下BN的均值和方差是通过moving average计算得到的把?需要在反向传播时更新grad吗?

张航
张航 (作者) 回复GuangxingHan3 个月前

是当前batch的running均值和方差,accumulated均值和方差只在inference的时候用,请参考这个博客Understanding the backward pass through Batch Normalization Layer

lixin liu
lixin liu2 个月前

请问是基于什么框架实现的?

张航
张航 (作者) 回复lixin liu2 个月前

用PyTorch写的

lixin liu
lixin liu回复张航 (作者)2 个月前
需要改框架底层?
张航
张航 (作者) 回复lixin liu2 个月前
需要重做dataparallel,写bn的kernel,以及用nccl cross gpu通信
Huaijin
Huaijin28 天前

你好, 这个有效果的对比吗?采用多GPU的的BN和无同步的BN对比。

张航
张航 (作者) 回复Huaijin19 天前
上大网,比如resnet152,不sync gpu很影响效果,每个gpu只能过2张图


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM