06. Communication-compute overlap — 오버랩은 마법이 아니라 조건부 스케줄이다
이 장의 핵심 질문
- "통신을 연산 뒤에 숨긴다(오버랩)"는 말은 통신 byte를 없애는 것이 아니다. 그럼 정확히 무엇인가?
- 오버랩이 성립하는 조건과 성립하지 않는 조건은 각각 무엇인가?
- "오버랩으로 통신을 공짜로 만들었다"는 주장을 어떻게 비판적으로 읽는가?
앞 장과의 연결 — 03–05장에서 병렬화 축마다 collective(all-reduce·p2p·all-to-all)가 "새 비용"으로 생겼다. 이 장은 그 비용을 줄이려는 대표 기법인 오버랩을, 원칙 1(조건을 함께 못박기)에 따라 정확히 규정한다. 이 장으로 첫 묶음(①·병렬화·통신)을 닫는다.
먼저: overlap이 뭔가요?
통신-연산 오버랩(communication-compute overlap) 은 device가 통신을 진행하는 동안 그와 무관한 연산을 동시에 수행하게 해, 통신 대기 시간을 연산 시간 뒤에 "숨기는" 스케줄링 기법이다.
일상 비유: 요리사가 물을 끓이는(통신) 동안 가만히 기다리는 대신 채소를 써는(연산) 것. 물 끓이기 자체가 빨라진 건 아니다. 다만 그 시간에 다른 일을 해서 전체 소요 시간이 줄었다. 여기엔 전제가 있다: 끓이기와 썰기가 서로를 기다리지 않아야 한다(의존성 없음), 그리고 손이 남아 있어야 한다(자원 여유).
📌 핵심 — 오버랩은 byte를 없애지 않는다 — 오버랩해도 통신량(전송해야 할 바이트)은 그대로다. 줄어드는 것은 통신이 임계 경로(critical path)에 얹히는 시간이다. 통신이 연산 뒤에 완전히 숨으면 "통신 시간이 0처럼 보이지만", 이는 연산이 통신보다 길고 둘이 독립일 때만 그렇다. 이 전제가 깨지면 오버랩 이득은 사라진다.
오버랩이 성립하는 조건 / 성립하지 않는 조건
원칙 1에 따라, "오버랩이 지연을 줄인다"를 조건과 함께 못박는다.
성립 조건
- 독립성(independence) — 숨기려는 통신과 겹칠 연산이 서로의 결과를 기다리지 않아야 한다. 통신 결과가 곧바로 필요한 연산은 겹칠 수 없다.
- 자원 여유(resource headroom) — 통신과 연산이 서로 다른 하드웨어 자원(연산 유닛 vs 통신 엔진/DMA)을 쓰고, 둘 다 동시에 돌릴 여유가 있어야 한다. 통신이 연산 자원(예: SM의 일부)을 잡아먹으면 연산이 느려져 이득이 상쇄된다.
- 연산이 통신보다 충분히 길어야 — 숨기려면 숨을 곳(연산 시간)이 통신 시간보다 커야 한다. 통신이 연산보다 길면 통신 일부만 숨고 나머지는 임계 경로에 남는다.
성립하지 않는(또는 약해지는) 조건
- 의존 사슬이 촘촘할 때 — 각 통신 결과가 바로 다음 연산의 입력이면(예: 매 레이어 all-reduce 직후 그 값을 즉시 사용), 겹칠 독립 연산이 없다.
- 연산이 짧을 때 — 작은 배치·짧은 시퀀스라 연산 시간이 통신보다 짧으면, 통신이 삐져나와 임계 경로에 남는다.
- 통신이 자원을 경합할 때 — 통신 엔진이 연산 유닛과 자원을 다투면(2번 위반), 오버랩해도 연산이 느려져 순이득이 준다.
- 통신 자체가 병목일 때 — all-to-all(05장)처럼 통신량이 크고 패브릭 경합이 심하면, 숨길 수 있는 양을 넘어선다.
flowchart TB
Q{"통신을 연산 뒤에<br/>숨길 수 있는가?"}
Q -->|"통신 결과가<br/>즉시 필요? (의존)"| NO1["숨길 독립 연산 없음<br/>→ 오버랩 실패"]
Q -->|"연산 < 통신 시간?"| NO2["통신이 삐져나옴<br/>→ 부분만 숨음"]
Q -->|"통신이 연산 자원 경합?"| NO3["연산이 느려짐<br/>→ 순이득 감소"]
Q -->|"독립 + 연산 충분히 김 +<br/>자원 여유"| YES["통신이 연산 뒤에 숨음<br/>→ 임계 경로에서 통신 시간 감소<br/>(단, byte는 그대로)"]
classDef question fill:#fff3c4,stroke:#d4a017,color:#000
classDef bad fill:#ffd6d6,stroke:#dc2626,color:#000
classDef good fill:#d1f0d1,stroke:#16a34a,color:#000
class Q question
class NO1,NO2,NO3 bad
class YES good
⚠️ 경계 혼동 주의 — "숨겼다"와 "없앴다" — 오버랩을 설명할 때 "통신을 없앴다/공짜로 만들었다"는 표현은 부정확하다. 통신은 여전히 일어나고 대역폭을 쓴다. 정확히는 "임계 경로에서 통신 대기가 (조건이 맞을 때) 줄었다"이다. 이 구분은 성능 주장을 검증할 때 결정적이다.
왜 이것이 "조건부 스케줄"인가
오버랩은 하드웨어가 자동으로 보장하는 것이 아니라, 스케줄러(엔진·라이브러리·커널)가 통신과 연산을 겹치도록 배치할 때 성립한다. 그 배치가 가능한지는 위의 조건(의존성·자원·시간 비율)에 달렸다. 그래서 같은 시스템이라도 워크로드에 따라 오버랩 이득이 크게 달라진다: 배치가 크고 시퀀스가 길면(연산이 김) 잘 숨고, 작으면 못 숨는다.
이것이 이 안내서가 오버랩을 "조건부 스케줄"이라 부르는 이유다. "오버랩을 지원한다"는 기능의 존재이지, 모든 워크로드에서 이득이 난다는 보장이 아니다.
🔬 증거 읽기 — 오버랩 주장 검증 — "오버랩으로 통신을 M% 숨겼다 / 통신을 사실상 제거했다"는 주장을 만나면 확인하라:
- (a) 어떤 워크로드(배치·시퀀스 길이)에서 측정했나 — 연산이 긴 조건이면 유리하게 나온다.
- (b) 어떤 병렬화 축의 통신인가 — all-reduce(TP)는 상대적으로 숨기기 쉽고, all-to-all(MoE)은 어렵다.
- (c) 통신량(byte)은 그대로인가 — "숨김"과 "제거"를 혼동한 주장인지.
- (d) 자원 경합 효과를 포함했나 — 통신이 연산 자원을 잡아먹은 손실을 뺐는가.
이 조건이 다르면 다른 배포의 "M%"와 비교 불가다(15장). 특히 오버랩 이득은 워크로드 의존성이 커서 벤치 조건 없이는 옮길 수 없다.
SHARP 등 하드웨어 오프로드와의 관계
02장에서 NCCL 2.27이 SHARP(스위치 내 연산 오프로드)를 지원한다고 했다. SHARP는 통신 자체를 스위치에서 일부 처리해 통신 시간·자원 점유를 줄이려는 접근으로, 오버랩(스케줄로 숨기기)과는 다른 층위의 완화책이다. 둘은 배타적이지 않다: 통신을 더 빠르게(SHARP) 하면서 남은 통신을 연산 뒤에 숨길(오버랩) 수 있다. 다만 SHARP의 실제 이득은 하드웨어·메시지 크기·topology에 의존하므로(02장 근거표), 특정 배포 수치는 조건 의존이다.
⚖️ 절충 — 오버랩·SHARP 같은 통신 완화는 통신 비용을 줄이지만, 구현·튜닝 복잡도와 워크로드 의존성을 늘린다. "이 기능을 켜면 항상 빨라진다"가 아니라 "이런 조건에서 이만큼 완화된다"로 읽어야 한다. 통신을 근본적으로 줄이는 것은 오히려 병렬화 축·topology 설계(02–05장)이며, 오버랩은 그 위에서의 조건부 개선이다.
첫 묶음(①) 정리 — 배포 D1까지 무엇을 얹었나
이 묶음(01–06)에서 배포 D0 → D1로 오며 얹은 것:
flowchart LR
D0["D0<br/>1 GPU·1 replica"] -->|"01: 세 한계 분리<br/>capacity/latency/traffic"| P1["문제 진단"]
P1 -->|"02: link/fabric/software<br/>scale-up vs scale-out"| P2["통신 배관"]
P2 -->|"03: TP<br/>가중치 shard, all-reduce"| P3["레이어 안 나눔"]
P3 -->|"04: PP/DP/SP/CP<br/>축별 통신"| P4["여러 축 겹침"]
P4 -->|"05: MoE/EP<br/>total vs activated, all-to-all"| P5["전문가 나눔"]
P5 -->|"06: 오버랩<br/>조건부 스케줄"| D1["D1: 병렬화된<br/>다중 device 엔진"]
classDef base fill:#cfe2ff,stroke:#2563eb,color:#000
classDef step fill:#ffe0b2,stroke:#e07b00,color:#000
classDef done fill:#d1f0d1,stroke:#16a34a,color:#000
class D0 base
class P1,P2,P3,P4,P5 step
class D1 done
이제 배포 D1은 "큰 모델을 여러 device·노드에 나눠 돌리는 병렬화된 엔진"이다. 하지만 아직 요청이 서비스가 되는 경로(요청을 어디로 보내고, 어떤 계약으로 응답을 보장하는가)가 없다. 다음 묶음(②·07–10)이 그것을 채운다.
이 묶음에서 확립한 재사용 어휘(뒤 묶음에서 계속 쓰임): shard/replicate/collective 골격, all-reduce/p2p/all-to-all, scale-up/scale-out, TP degree, total/activated, 오버랩의 조건.
이 장에서 배운 것
- 오버랩은 통신 byte를 없애는 것이 아니라, 통신이 임계 경로에 얹히는 시간을 (조건이 맞을 때) 줄이는 스케줄링이다.
- 성립 조건은 독립성 + 자원 여유 + 연산이 통신보다 충분히 김. 이 중 하나라도 깨지면 이득이 줄거나 사라진다.
- 의존 사슬이 촘촘하거나(즉시 필요한 통신), 연산이 짧거나(작은 배치), 통신이 자원을 경합하거나, 통신 자체가 병목(all-to-all)이면 오버랩이 약해진다.
- "숨겼다"와 "없앴다/공짜로 만들었다"는 다르다. 통신은 여전히 대역폭을 쓴다.
- 오버랩은 워크로드 의존성이 크다. "지원한다"는 기능의 존재이지 모든 조건에서의 이득 보장이 아니다. SHARP 같은 오프로드는 다른 층위의 완화책으로 병행 가능하다.
🔎 이 장의 '지지하지 않는 결론' + 'unknown으로 남겨야 할 것'
- 지지하지 않는 결론 — "오버랩을 켜면 통신이 공짜가 된다"는 지지되지 않는다. 이득은 독립성·자원·시간 비율 조건에 달렸고, 워크로드에 따라 0에 가까울 수 있다.
- unknown으로 남길 것 — 특정 배포·워크로드에서 오버랩이 실제로 숨긴 비율과 SHARP의 실제 이득은 벤치 조건(배치·시퀀스·topology·버전) 없이는
unknown. 일반적 "M%"는 옮기지 않는다.
✍️ 확인 문제
- "오버랩으로 all-reduce 통신을 사실상 없앴다"는 문장에서 부정확한 단어는 무엇이고, 정확히 어떻게 고쳐 말해야 하는가? 통신 byte와 임계 경로 시간을 구분해 답하라.
- (조건 유형) 같은 시스템이 배치가 클 때는 오버랩 이득이 크고 작을 때는 거의 없다. 왜 그런지 성립 조건(특히 "연산이 통신보다 충분히 김")으로 설명하라. 이 사실이 "오버랩 이득 M%" 주장을 벤치 조건 없이 옮기면 안 되는 이유와 어떻게 연결되는가?
- all-reduce(TP)와 all-to-all(MoE) 중 어느 통신이 오버랩으로 숨기기 더 어려운가? 통신량·패브릭 경합·의존성 관점에서 근거를 대라.
이것으로 첫 묶음(①·병렬화·통신)을 마친다. 다음 묶음(②)에서는 병렬화된 엔진이 요청을 받는 서비스가 될 때 필요한 것 — prefill/decode 분리, KV 전송·계층화, 라우팅·오토스케일링, SLO·capacity 계약 — 을 다룬다.
다음 → 07. Prefill-decode disaggregation — phase를 떼면 무엇이 줄고 무엇이 새로 생기는가