Closed jasperzhong closed 3 years ago
想把pipeline做好还真是件复杂的事情. GPipe简单化处理了,效果还不错.
一共有K个设备. 最naive的做法就是图b. 但这样效率太低了. 所以GPipe提出了图c,把一个mini-batch拆成M个micro-batch. 作者说当 M >= 4 * K 的时候,产生的bubble可以忽略不计. 嘛. 看上去mini-batch可以弄大点.
为什么说这件事比较复杂呢?
总之主要难点还是如何做partition. 感觉需要一个搜索.
实验还可以.
这个breakdown不错. bubble overhead才4.1%.
section 6有些惊喜. model parallelism初衷是支持大模型. 但是naive的方法资源利用率太低了. 解决办法通常有两个办法:
今天重读了这篇论文,收获不小. 温故而知新.
GPipe的core idea很简单:
除此之外,有一个重要的优化,就是recomputation——只保存partition boundaries的output activations. 这样peak activation memory的空间复杂度从O(N L / K)降低到O(N + (L / K) (N / M)),其中N是指保存的output activations,因为每个micro-batch都要保存,所以总的batch数量还是N,而L/K是这个partition的layer层数,N/M是micro-batch size,(L/K)*(N/M)就是在这个partition上做一个micro-batch的output activation size.
其实对比其他parallelism方法,可以发现Pipeline parallelism引入的通信开销是很低的,仅需要传输boundary的activations & gradients w.r.t. activations即可. 而tensor model parallelism以及data parallelism,还需要引入很多all-reduce.
这个实验注意一下. 训练Big Transformer的实验. T(L, H, A). L是层数,H是hidden size,A是#attention heads. 对比T(24, 8192, 16)和T(12, 16384, 32)就会发现,deeper model表现要比wider model更好.
另外和 #167 对比,GPipe是同步更新,其weight update semantics没变. 而Pipedream是异步更新,虽然降低了bubble size,但是却需要引入多份model weights. 其实不太划得来. 因为文中表明了bubble size其实不是个很大的问题.
有个ablation实验吸引了我的注意. 看上去M >> K是个不错的configuration. 也就是说,Pipeline要尽可能多stage(K大),然后尽可能pipelined(M大).
https://papers.nips.cc/paper/2019/file/093f65e080a295f8076b1c5722a46aa2-Paper.pdf