流水线并行:1F1B、虚拟段与气泡

流水线并行:1F1B、虚拟段与气泡

💡 原文中文,约3600字,阅读约需9分钟。
📝

内容提要

本文介绍流水线并行中气泡的产生与优化。将模型按层切段、批次分微批后,段间等待形成气泡。四代调度各改一点:GPipe先全前向再全反向,显存高;1F1B改交替执行,减少在途激活;Interleaved 1F1B切细段降气泡,但增通信;Zero Bubble拆反向填气泡。气泡占比约(P−1)/m,显存峰值随段数变化。

🔎

延伸解读

气泡与显存的权衡

流水线并行中,气泡占比与在途激活量是一对矛盾。GPipe 通过增大微批数 m 来摊薄气泡,但每个 rank 需保存全部 m 份激活,显存压力大。1F1B 通过交替执行前向和反向,将峰值激活限制在 P 份以内,但气泡占比不变。Interleaved 1F1B 通过虚拟段 V 降低气泡,却增加了通信次数和显存占用。理解这一权衡有助于根据硬件资源选择合适的调度策略。

显存压力的不均衡分布

推导显示,1F1B 调度下,rank 0 峰值需保存 P 份激活,而最后一个 rank 仅需 1 份,显存压力集中在流水线前段。这种不均衡为优化提供了空间,例如可将前段 rank 的激活迁移至后段空闲显存。虚拟段会加剧这种不均衡,如 P=8、V=2 时,rank 0 峰值激活相当于 11.5 份完整激活,比 V=1 时多近一半。

气泡并非完全浪费

文章指出,气泡时间可被利用:只要存在不依赖流水线顺序的计算,如多模态模型的视觉编码器,就可填充气泡。这意味着在实际系统设计中,可通过任务调度或模型结构设计来减少气泡的负面影响,提升整体效率。

Q&A

什么是流水线并行中的气泡?它是如何产生的?

在流水线并行中,模型按层切成P段,每段放在一张卡上,一个batch切成m个micro-batch依次流过各段。由于段间存在依赖,后面的段需要等待前面的段完成前向,前面的段需要等待后面的段完成反向,这种等待时间就是气泡。

GPipe和1F1B调度有什么区别?

GPipe先执行所有micro-batch的前向,再执行所有反向,导致每个rank需要保存所有m个micro-batch的激活,显存占用高。1F1B在warmup后交替执行前向和反向,使得每个rank同时保存的激活数量有上界(最多P份),从而降低显存压力,但气泡占比不变。

Interleaved 1F1B如何减少气泡?它有什么代价?

Interleaved 1F1B通过引入虚拟段(V>1),让每个rank持有V段不连续的层,micro-batch在流水线中循环V次,每段前向长度变为原来的1/V,从而将气泡占比从(P-1)/m降低到(P-1)/(mV)。代价是段间通信次数乘以V,且warmup变长导致在途激活增加,显存压力增大。

Zero Bubble调度是如何工作的?

Zero Bubble将反向传播拆分为对输入梯度的计算和对权重梯度的计算。对输入梯度的计算必须立即传给上一段,而对权重梯度的计算不依赖下游,可以推迟。通过将对权重梯度的计算填入气泡,理论上可以将气泡占比降至接近零。

气泡占比的理论公式是什么?如何推导?

以1F1B为例,rank 0在warmup后需要等待第一个micro-batch的反向从最后一段传回,等待时间为(P-1)(tf+tb)。总时间为m(tf+tb)+(P-1)(tf+tb),因此气泡占比为(P-1)/(m+P-1),近似为(P-1)/m。

在1F1B调度中,每个rank在途激活的份数是多少?为什么?

在1F1B调度中,rank r在warmup阶段先做P-1-r个前向,然后进入交替阶段。交替阶段每次先前向再反向,因此峰值时rank r保存的激活份数为P-r。例如rank 0保存P份,rank P-1保存1份。

流水线并行中减少气泡的两种主要方法是什么?

根据气泡占比公式(P-1)/(mV),减少气泡的方法有两种:一是增大micro-batch数量m,二是增大虚拟段数V(即使用Interleaved 1F1B)。

🏷️

标签

➡️

继续阅读