流水線並行 是什麼?
Pipeline Parallelism:流水線並行 的完整解釋
將深度神經網路的不同層分配到不同的 GPU 設備上,讓多個 micro-batch 在不同層上交叉執行以提高 GPU 利用率的分佈式訓練方法。
核心概念
流水線並行(Pipeline Parallelism)的核心思想是層級的模型分割。將一個深層模型的不同層分配到不同的 GPU 設備上,形成一個線性的流水線。
考慮一個有 8 層的模型和 4 個 GPU 的情況。流水線並行將其分配為:
- GPU0:第 1-2 層
- GPU1:第 3-4 層
- GPU2:第 5-6 層
- GPU3:第 7-8 層
訓練時,一個完整的 batch 被進一步分割成多個 micro-batch(例如 4 個)。這樣可以實現流水線:
- 時間步 1:GPU0 處理 micro-batch 1
- 時間步 2:GPU0 處理 micro-batch 2,GPU1 處理 micro-batch 1 的輸出
- 時間步 3:GPU0 處理 micro-batch 3,GPU1 處理 micro-batch 2,GPU2 處理 micro-batch 1
- ...
這樣,所有 GPU 都在忙碌,提高了整體的計算利用率。
流水線並行的優勢包括:
- 降低通訊帶寬要求。設備間的通訊只發生在層邊界,通常是激活值的傳遞,通訊量相對較小。
- 適合層數多的模型。對於層數很多但每層參數不太大的模型(如某些 Transformer),流水線並行效果好。
- 易於實現和理解。流水線的邏輯相對直觀。
流水線並行的劣勢是:
- 氣泡開銷。由於流水線填充和清空的過程,會產生一定的計算浪費(氣泡)。
- 複雜的梯度同步。反向傳播需要確保梯度同步正確。
- 記憶體使用增加。需要存儲中間激活值以供反向傳播使用,特別是當 micro-batch 數多時。
運作原理
流水線並行的運作涉及前向傳播、反向傳播和梯度累積三個階段。
前向傳播階段:
- GPU0 接收輸入 batch,將其分割成多個 micro-batch。
- GPU0 對 micro-batch 1 執行前向傳播,將輸出(激活值)發送給 GPU1。
- GPU0 同時對 micro-batch 2 執行前向傳播。
- GPU1 接收來自 GPU0 的激活值,執行其層的前向傳播,將輸出發送給 GPU2。
- 這個過程持續,形成流水線,直到所有 micro-batch 都完成前向傳播。
反向傳播階段:
- 最後一個 GPU(GPU3)首先計算其層的梯度。
- 梯度沿著流水線反向傳播,每個 GPU 計算其層的梯度。
- 梯度被累積(對所有 micro-batch 的梯度求和)。
- 參數梯度用於更新該 GPU 上層的參數。
通訊同步: 在某些實現中(如 GPipe),完成一個完整 batch 的前向傳播後,才開始反向傳播,以最小化通訊開銷。在其他實現中(如 PipeDream),可能採用異步的方式,反向傳播立即開始,這可以減少流水線氣泡。
實際應用
流水線並行在訓練非常大的模型時是必不可少的。Google 的 PipeDream 項目展示了流水線並行在訓練 BERT 等大型模型上的高效性。
在邊界計算中,流水線並行用於在有限的 GPU 資源上訓練大型模型。通過將模型分割到多個 GPU,研究人員可以在沒有超大 GPU 集群的情況下訓練模型。
在雲計算中,流水線並行用於優化多租户環境下的資源利用。系統可以根據可用資源動態調整流水線深度。
在邊緣推理中,流水線並行也適用。將模型分割到多個邊緣設備上,實現分佈式推理。
在微調場景中,研究人員使用流水線並行在有限的 GPU 上微調非常大的模型,減少對昂貴 GPU 的需求。
常見誤區
一個常見的誤區是認為流水線並行沒有開銷。實際上,流水線氣泡是一個重要的開銷。當 GPU 數多或 micro-batch 數少時,氣泡比例較大,加速效果受限。
另一個誤區是認為流水線並行和張量並行不能混用。實際上,它們可以也應該混用。在許多大型模型訓練中,同時使用數據並行、流水線並行和張量並行,以實現最優的性能。
還有人誤以為流水線深度(層數)越多越好。實際上,流水線深度受到氣泡比例和記憶體的限制。太深的流水線會導致過多的氣泡和記憶體壓力。
與相關技術的比較
流水線並行與張量並行都是模型並行技術,但分割位置不同。流水線並行在層級分割,張量並行在層內分割。
與數據並行相比,流水線並行用於分割模型,而數據並行分割輸入數據。三者常一起使用形成混合並行。
與激活檢查點(Activation Checkpointing)相關,激活檢查點減少激活值的記憶體使用,支援更深的流水線或更大的 micro-batch。