写在最前面
小白跑代码,碰到out of memory了,batch size 从1024降到了32才不报错,但是跑了一个星期,实在受不了了,于是疯狂收集资料看看怎么用多卡训练,以下是我所看博客的总结,有错之处请提出并多多指教!
最初,百度 多卡训练,给到最多的词条都是教你怎么使用DataParallel
DataParallel确实是用于数据并行,但是机理到底是什么?一机多卡到底发生了什么?并行处理代码到底怎么写?直接用DataParallel怎么报的错我不会改?接下来一一细说!
分布式训练,其实分为模型并行和数据并行。
模型并行
其实就是模型太大,一张卡无法带动,就需要把模型分块放入到其他卡上面。
数据并行
每张卡加载一样的模型,只是把数据进行划分放入到卡上进行并行计算。
比较详细的参考代码:pytorch并行训练–W3Cschool
Pytorch并行训练的两个API
-
torch.nn.DataParallel (DP)
- 原理 -- 将一个batch的数据平分到每张卡上面 -- 模型复制到每张卡上面(每张卡上模型一样,模型没有被分割) -- 每个GPU分别得到输出,将输出发回主GPU上 -- 在主GPU上,通过损失函数计算loss,利用backward求导,得到损失梯度 -- 得到的损失梯度,分发到所有GPU上 -- 反向传播计算参数梯度 -- 所有梯度回传到主GPU,通过梯度更新模型权重
-
torch.nn.DistributedDataParallel (DDP)
- 和DP不同的是,没有主GPU,每个GPU执行相同的任务。 - 比DP更快 - 支持模型并行(一个模型太大,没办法放在一张卡上跑,需要分割模型放在多个卡上跑)
**(理解) 梯度下降:整体梯度下降(整个数据集),随机梯度下降(一条数据更新),mini-batch梯度下降(用一个batch更新)
我们常用的mini-batch梯度下降,是指每次更新用一个batch的数据量更新。从下面的伪代码可以看到,其实就是用这个batch每条数据算出梯度
取平均数再去更新参数。
总的来说,就是用batch得到的梯度代替整体。
所以batch size 大好还是小好?
上面说了batch得到的梯度代替整体,也就是局部表示整体。如果batch size太小,就不能很好的表示样本总体,梯度波动大,难以收敛。太大的话,一次性载入数据就会有困难,而且收敛更快,确定的下降方向早就基本确定loss.backward():就是将loss反向传播,计算 d(loss) / dx ,并保存到x.grad中