DualPipe 병렬화 (DualPipe Parallelism)
DeepSeek-V3는 전문가 혼합(Mixture of Experts; MoE) 전문가(expert)가 노드 전체에 흩어진 상태에서 H800 GPU 2,048장으로 학습되었습니다. 노드 간 전문가 all-to-all 통신(communication)은 연산(compute) GPU-시간 1마다 통신 GPU-시간 1을 요구했습니다. GPU는 절반의 시간 동안 유휴(idle) 상태로 멈춰 있었습니다. DualPipe(DeepSeek, 2024년 12월)는 순방향(forward)/역방향(backward) 연산과 그것이 유발하는 all-to-all 통신을 서로 겹치는 양방향 파이프라인(bidirectional pipeline)입니다. 버블(bubble)은 줄어들고 처리량(throughput)은 올라갑니다. 이름의 "dual"이 가리키는 모델 파라미터(parameter) 복사본 두 개를 유지하는 비용은, 전문가 병렬화(Expert Parallelism)가 이미 전문가를 랭크(rank) 전체에 흩어 놓은 상황에서는 상대적으로 저렴합니다. 이 강의는 DualPipe가 실제로 어떤 일을 하는지, 그리고 Sea AI Lab의 DualPipeV 개선안이 왜 약간 더 큰 버블을 감수하면서까지 2배 파라미터 비용을 없애려 했는지 살펴보는 학습형(Learn) 워크스루입니다.
유형: Learn
언어: Python (표준 라이브러리, 스케줄 시뮬레이터)
선수 지식: Phase 10 · 05 (분산 학습, FSDP, DeepSpeed), Phase 10 · 14 (오픈 모델 아키텍처와 MoE)
예상 시간: 약 60분
학습 목표
- DualPipe의 순방향-역방향 청크(chunk)를 구성하는 네 구성 요소를 이름 짓고, 각 구성 요소가 왜 자신만의 겹침(overlap) 구간을 갖는지 설명합니다.
- 대규모 환경에서 파이프라인 버블 문제가 무엇인지, 그리고 "버블 없음(bubble-free)"이 마케팅 표현이 아니라 실무적으로 어떤 의미인지 설명합니다.
- 8개의 파이프라인 병렬화(Pipeline Parallelism; PP) 랭크와 16개의 마이크로 배치(micro-batch)에 대해 DualPipe 스케줄(schedule)을 직접 손으로 따라가 보고, 순방향 스트림과 역방향 스트림이 서로의 유휴 슬롯을 채우는지 확인합니다.
- DualPipeV(Sea AI Lab, 2025)의 절충안을 설명합니다. 즉, 2배 파라미터 복제를 없애는 대신 전문가 병렬화가 꺼져 있을 때 약간 더 큰 버블을 감수하는 선택입니다.
문제
H800 GPU 2,000장 규모에서 6,710억(671B) 파라미터 MoE 모델을 학습하면 세 가지 병목이 서로 맞물려 발생합니다.
- 메모리 압박(Memory pressure). 각 GPU는 모델의 한 조각을 들고 있습니다. 시퀀스(sequence) 길이 8,000, 레이어(layer) 61개, 헤드(head) 128개 환경에서 활성화(activation) 메모리는 어마어마하게 커집니다.
- 파이프라인 버블(Pipeline bubbles). 전통적인 파이프라인 병렬화(GPipe, 1F1B)는 자신의 스테이지(stage) 입력이나 그래디언트(gradient)를 기다리는 동안 GPU를 유휴 상태로 놓아둡니다. 스테이지가 8개일 때는 1F1B 스케줄링을 써도 GPU 시간의 약 12%가 버블로 낭비될 수 있습니다.
- 노드 간 all-to-all 통신. 전문가 병렬화를 적용한 MoE는 전문가를 여러 노드에 흩뜨립니다. 모든 순방향 패스(forward pass)는 토큰(token)을 해당 전문가로 보내는 all-to-all과, 그 결과를 다시 모으는 또 다른 all-to-all을 유발합니다. GPU 2,000장 규모에서는 연산 대 통신 비율이 손쉽게 1:1이 되어 버립니다.
각 병목에는 별도의 해법이 있습니다. 메모리에는 그래디언트 체크포인팅(gradient checkpointing), 파이프라인 버블에는 Zero Bubble(Sea AI Lab, 2023), all-to-all에는 전문가 병렬용 통신 커널(kernel)이 있습니다. DualPipe가 하는 일은 이 해법들을 한 자리에 모아 함께 작동하게 만드는 것입니다. 하나의 순방향-역방향 청크 안에서 연산과 통신을 겹치고, 파이프라인의 양 끝에서 마이크로 배치를 동시에 주입하며, 이렇게 만들어진 스케줄을 활용해 all-to-all을 연산 구간 안쪽에 숨깁니다.
논문에서 보고된 결과는 파이프라인 버블의 거의 완전한 제거와, DeepSeek-V3의 14.8조(14.8T) 토큰 학습 실행에서 95%가 넘는 GPU 가동률(utilization)입니다.
개념
파이프라인 병렬화 복습
N개의 레이어를 가진 모델을 P개의 장치(device)에 나눕니다. 장치 i는 레이어 i * N/P .. (i+1) * N/P - 1을 가집니다. 마이크로 배치는 장치 0에서 P-1까지 순방향으로 흘러가고, 그 다음 P-1에서 0까지 역방향으로 돌아옵니다. 각 장치는 이전 장치가 출력을 보내 줘야 자기 스테이지의 순방향을 시작할 수 있고, 다음 장치가 상류 그래디언트를 보내 줘야 역방향을 시작할 수 있습니다.
GPipe(Huang et al., 2019)는 마이크로 배치 하나씩만 스케줄하기 때문에 GPU 시간 대부분을 낭비합니다. 1F1B(Narayanan et al., 2021)는 여러 마이크로 배치의 순방향과 역방향을 인터리브(interleave)합니다. Zero Bubble(Qi et al., 2023)은 역방향 패스를 입력에 대한 역방향(backward-for-input; B)과 가중치에 대한 역방향(backward-for-weights; W) 두 부분으로 나누고, 이를 활용해 버블을 채우도록 스케줄합니다. Zero Bubble 이후 파이프라인은 거의 빈틈없이 채워집니다.
DualPipe는 그 다음 단계입니다. 위에 두 가지 아이디어를 더 얹습니다.
아이디어 1: 청크 분해 (chunk decomposition)
순방향 청크 하나는 네 가지 구성 요소로 쪼개집니다.
- 어텐션(Attention). Q/K/V 사영(projection), 어텐션 계산, 출력 사영.
- All-to-all dispatch. 토큰을 해당 전문가로 보내는 노드 간 통신.
- MLP. MoE 전문가 연산.
- All-to-all combine. 전문가의 출력을 다시 가져오는 노드 간 통신.
역방향 청크에는 이 각각의 그래디언트 버전이 추가됩니다. DualPipe는 all-to-all dispatch가 다음 청크의 어텐션 연산과 동시에 일어나고, all-to-all combine이 그 다음 청크의 MLP 연산과 동시에 일어나도록 스케줄합니다.
아이디어 2: 양방향 스케줄링 (bidirectional scheduling)
대부분의 파이프라인 스케줄은 스테이지 0에서 마이크로 배치를 주입하고 스테이지 P-1을 향해 흘려보냅니다. DualPipe는 양쪽 끝 모두에서 마이크로 배치를 주입합니다. 스테이지 0은 자신에서 출발한 순방향 마이크로 배치를 보고, 스테이지 P-1도 자신에서 출발한 순방향 마이크로 배치를 봅니다. 두 스트림은 가운데에서 만납니다.
이를 가능하게 하려면 장치 i가 파이프라인 앞쪽 레이어 i와 파이프라인 뒤쪽 레이어 P - 1 - i를 모두 들고 있어야 합니다. 이것이 바로 DualPipe의 "dual"이 의미하는 부분입니다. 각 장치는 두 방향을 각각 처리할 수 있도록 모델 레이어의 복사본을 두 벌 유지합니다. DeepSeek-V3 규모에서 이는 파라미터를 2배로 복제하는 비용입니다. 그러나 전문가 병렬화가 이미 MoE 전문가를 모든 랭크에 매우 얇게 분산해 둔 상태이기 때문에, 전문가가 아닌 레이어를 두 벌로 두는 비용은 상대적으로 작습니다.
핵심은 한 방향의 순방향 스트림과 반대 방향의 역방향 스트림이, 단방향 스케줄에서 버블이 생겼을 자리에 정확히 겹쳐 들어간다는 점입니다. 결과적으로 버블이 사라집니다.
손으로 따라가는 스케줄
P = 4 랭크, 마이크로 배치 8개, 그중 정방향 주입(forward) 4개와 반대 방향 주입(reverse) 4개로 나눈 경우를 살펴봅니다. 시간은 왼쪽에서 오른쪽으로 흐르고, 각 행(row)은 장치 랭크를 나타냅니다.
Time →
rank 0: F1 F2 F3 F4 F5R F6R F7R F8R B1 B2 B3 B4 ...
rank 1: F1 F2 F3 F4/F5R F6R F7R B1 B2 ...
rank 2: F1 F2 F3/F5R F4/F6R B1 ...
rank 3: F1 F2/F5R F3/F6R ...
F4/F5R 표기를 읽는 방법은 다음과 같습니다. 랭크 1은 파이프라인 좌→우 방향으로 흐르는 마이크로 배치 4의 순방향과, 우→좌 방향으로 흐르는 마이크로 배치 5의 순방향을 같은 시간 슬롯에서 함께 실행합니다. 이것이 운영 측면에서 "양방향(bidirectional)"이 갖는 의미입니다.
랭크 2에서는 두 방향의 스트림이 더 일찍 겹치기 시작하고, 랭크 0과 P-1에서는 가장 늦게 겹칩니다. 스케줄의 안정 구간(middle phase)에서는 모든 랭크가 한 방향의 순방향을 다른 방향의 역방향과 함께 실행합니다. 연산이 비어 있지 않습니다. 순방향 패스의 all-to-all dispatch는 역방향 연산 안에 숨고, all-to-all combine은 순방향 연산 안에 숨습니다. 그 결과 버블이 짓눌려 사라집니다.
버블 회계 (Bubble accounting)
표준 1F1B의 파이프라인 버블, 즉 랭크당 낭비 시간은 다음과 같이 표현됩니다.
bubble_1F1B = (P - 1) * forward_chunk_time
Zero Bubble 개선안은 이 값을 줄이지만 완전히 0으로 만들지는 못합니다. DualPipe는 마이크로 배치 개수가 파이프라인 깊이의 2배로 정확히 나누어떨어질 때 안정 구간에서 버블이 0이 됩니다. 안정 구간 바깥인 워밍업(warmup)과 쿨다운(cooldown)에는 일부 버블이 남지만, 그 크기는 마이크로 배치 개수와 함께 늘어나지 않습니다. 이것이 논문에서 강조하는 핵심 성질입니다.
마케팅 표현으로는 "bubble-free"입니다. 기술적으로 정확히 말하면 마이크로 배치 개수가 늘어도 버블이 함께 커지지 않는다는 뜻입니다. Sea AI Lab의 후속 분석(DualPipeV / Cut-in-half)은 전문가 병렬화가 병목이 아닐 때에만 완전한 0 버블이 가능하다는 점을 보여 줍니다. 전문가 병렬화에서 비롯되는 all-to-all이 있으면, 스케줄링상의 절충은 늘 어느 정도 남습니다.
DualPipeV — 개선안
Sea AI Lab(2025)은 전문가 병렬화의 통신 겹침이 핵심 과제가 아닐 때에는 2배 파라미터 복제가 낭비라는 점을 지적했습니다. DualPipeV 스케줄은 양방향 주입을 단일 파라미터 복사본 위에서 도는 "V자(V-shape)" 스케줄로 접어 넣습니다. 버블은 DualPipe보다 살짝 크지만, 메모리 절감 효과는 상당합니다. DeepSeek는 자사의 오픈 소스 DualPipe 구현체에서 전문가 병렬화 비활성 모드(EP-off mode)로 DualPipeV를 채택했습니다.
이 절충은 다음 표로 정리할 수 있습니다.
| 특성 | DualPipe | DualPipeV | 1F1B | Zero Bubble |
|---|
| 장치당 파라미터 복사본 수 | 2 | 1 | 1 | 1 |
| 마이크로 배치 대비 버블 | 일정(constant) | 작게 증가 | 증가 | 증가 |
| 연산-통신 겹침 | 완전(full) | 부분(partial) | 최소(minimal) | 부분 |
| 사용 시점 | 전문가 병렬화가 무거운 MoE | 밀집(dense) 모델 또는 전문가 병렬화가 가벼운 경우 | 기준선(baseline) | 임의의 파이프라인 |
14.8조 토큰 학습 실행에서의 의미
DeepSeek-V3의 사전학습(pre-training)은 H800 GPU 2,048장 위에서 약 280만(2.8M) GPU-시간 동안 14.8조 토큰을 소비했습니다. 만약 단순한 1F1B를 썼다면 그중 12-15%를 파이프라인 버블로 잃었을 것입니다. 환산하면 34만-42만 GPU-시간이며, 이는 70B 밀집 모델 하나를 통째로 학습할 만한 양입니다. DualPipe는 그 대부분을 회수했습니다. 내부 로그(log) 없이는 기여분을 직접 정량화하기 어렵지만, 논문이 내세우는 주장은 학습 전체 평균 GPU 가동률 95% 이상입니다.
규모가 작은 실행, 가령 GPU 1,000장 미만에서는 DualPipe가 과한 선택입니다. 파이프라인 버블이 전체 비용 대비 작고, 밀집 모델 학습은 all-to-all 병목에 잘 걸리지 않기 때문입니다. 반대로 수천 장 규모의 최첨단(frontier) MoE 학습에서는 사실상 필수입니다.
스택(stack) 안에서의 위치
- FSDP(Phase 10 · 05)와 상호 보완적입니다. FSDP는 모델 파라미터를 랭크 전체에 샤드(shard)하고, DualPipe는 랭크 전체의 연산을 스케줄합니다. 두 기법은 함께 결합해 사용할 수 있습니다.
- ZeRO-3 그래디언트 샤딩과도 호환됩니다. 다만 두 벌 복제와 관련된 부기(bookkeeping)는 ZeRO의 샤드된 그래디언트와 잘 맞물려 돌아가야 합니다.
- 클러스터 토폴로지(topology)에 맞춰 튜닝된 맞춤형 all-to-all 커널이 필요합니다. DeepSeek의 오픈 소스 커널이 사실상의 참조 구현(reference implementation)입니다.
사용해보기
code/main.py는 파이프라인 스케줄 시뮬레이터(simulator)입니다. (P, n_micro_batches, schedule)을 입력으로 받아 1F1B, Zero Bubble, DualPipe, DualPipeV 각각의 안정 구간 가동률을 출력합니다. 학습용 도구이므로, 결과 수치는 논문의 정성적 주장과는 일치하지만 실제 운영 환경에서 측정된 속도 향상(speedup)을 주장하는 값은 아닙니다.
이 시뮬레이터의 가치는 P와 마이크로 배치 수를 바꿔 가며 실행해 보면서, 1F1B에서는 버블 비율이 점점 커지는 반면 DualPipe에서는 그렇지 않다는 점을 직접 관찰하는 데 있습니다.
실제 학습 실행에 통합할 때 고려할 점은 다음과 같습니다.
- 마이크로 배치 개수로 깔끔히 나누어떨어지는 파이프라인 병렬화 깊이를 선택합니다.
- 전문가 병렬 메시(expert-parallel mesh)가 양방향 all-to-all을 지원하는지 확인합니다. DeepSeek의 커널이 참조 구현입니다.
- 처음 적용할 때는 스케줄 자체를 디버깅(debugging)하는 데 일주일 정도는 쓸 각오를 합니다. 부기가 까다롭습니다.
- 전체 합산 가동률이 아니라 랭크별 GPU 가동률을 모니터링(monitoring)합니다. DualPipe의 이점은 가장 느린 랭크(straggler)를 더 빠듯하게 만드는 데서 나옵니다.
산출물 만들기
이 강의는 outputs/skill-dualpipe-planner.md를 만들어 냅니다. 학습 클러스터 사양(GPU 개수, 토폴로지, 인터커넥트(interconnect), 모델 형상)이 주어지면, 적합한 파이프라인 병렬화 전략과 사용할 스케줄링 알고리즘, 그리고 목표 규모에서 예상되는 버블 비율을 추천합니다.
연습문제
-
(P=8, micro_batches=16, schedule=dualpipe)와 (P=8, micro_batches=16, schedule=1f1b)로 code/main.py를 실행합니다. GPU 가동률 차이를 계산하고, 학습 1M 토큰당 회수되는 GPU-시간으로 표현합니다.
-
(P=4, micro_batches=8, schedule=dualpipe)의 스케줄 표를 직접 손으로 그립니다. 각 시간 슬롯에 마이크로 배치의 ID와 방향을 표시합니다. 버블이 더 이상 존재하지 않는 첫 시간 슬롯이 어디인지 식별합니다.
-
DeepSeek-V3 기술 보고서(arXiv:2412.19437)의 Figure 5를 읽습니다. DualPipe 순방향 청크 안에서 all-to-all dispatch의 겹침 구간을 식별합니다. 연산 스케줄이 그것을 어떻게 숨기는지 설명합니다.
-
파이프라인 스테이지 P=8인 70B 밀집 모델과 파이프라인 스테이지 P=16인 671B MoE 모델에 대해 DualPipe의 2배 파라미터 오버헤드를 계산합니다. MoE 사례의 오버헤드 비율이 더 작은 이유를 보입니다. 대부분의 파라미터가 전문가에 속해 있고, 그 전문가가 큰 전문가 병렬 그룹 전체에 샤드되어 있기 때문입니다.
-
DualPipe를 2021년에 등장한 경쟁 양방향 스케줄러인 Chimera와 비교합니다. 논문의 3.4절을 근거로 삼아, Chimera에는 없고 DualPipe가 추가한 두 가지 구체적 성질을 식별합니다.
핵심 용어
| 용어 | 흔한 설명 | 실제 의미 |
|---|
| 파이프라인 버블(Pipeline bubble) | "랭크별 유휴 시간" | 파이프라인 스테이지가 자신의 입력이나 그래디언트를 기다리느라 낭비되는 GPU 사이클입니다. |
| 1F1B | "기본 파이프라인 스케줄" | 순방향 하나 / 역방향 하나를 번갈아 끼워 넣는 스케줄링입니다. DualPipe가 비교하고 이기는 기준선입니다. |
| Zero Bubble | "Sea AI Lab 2023" | 역방향을 입력 그래디언트(B)와 가중치 그래디언트(W)로 나눕니다. 파이프라인을 거의 완전히 빈틈없이 만듭니다. |
| DualPipe | "DeepSeek-V3 스케줄" | 양방향 파이프라인과 연산-통신 겹침을 결합한 방식입니다. 마이크로 배치 개수가 늘어도 버블이 함께 커지지 않습니다. |
| DualPipeV | "Cut-in-half" | 2배 파라미터 복제를 없앤 V자 형태의 개선안입니다. 그 대신 버블이 약간 더 큽니다. |
| 청크(Chunk) | "파이프라인 작업 단위" | 마이크로 배치 하나가 파이프라인 스테이지 하나를 통과하는 순방향 또는 역방향 패스입니다. |
| All-to-all dispatch | "토큰을 전문가로 보내기" | 토큰을 할당된 MoE 전문가로 라우팅(routing)하는 노드 간 통신입니다. |
| All-to-all combine | "전문가 출력 가져오기" | MLP 뒤에서 각 전문가의 출력을 다시 모으는 노드 간 통신입니다. |
| 전문가 병렬화(Expert Parallelism; EP) | "GPU 전체에 흩어진 전문가" | 서로 다른 GPU가 서로 다른 전문가를 들도록 MoE 전문가를 랭크 전체에 샤드하는 기법입니다. |
| 파이프라인 병렬화(Pipeline Parallelism; PP) | "GPU 전체에 나뉜 레이어" | 모델 레이어를 랭크 전체에 샤드합니다. DualPipe가 스케줄링하는 차원입니다. |
| 버블 비율(Bubble fraction) | "낭비된 GPU 시간" | bubble_time / total_time의 값입니다. DualPipe가 0에 가깝게 몰아가려는 지표입니다. |
더 읽을거리