《GPU Mode》
L095
2025 · 후반
High priority
transcript · failed · Monarch repo 보강
Single controller programming with Monarch
SPMD 가 분산 학습의 표준이 됐지만, RL 과 agentic 시스템은 SPMD 모델로 깔끔하지 않다 — “여러 GPU 가 동일한 일” 이 아니라 “여러 GPU 가 다른 역할”. Monarch 는 actor 모델 위에서 single controller 의 imperative 한 코드로 분산 시스템을 기술하게 해주는 PyTorch 친화 framework. Allen Wang · Colin Taylor 가 GPU Mode 청중에게 깐 디자인. transcript 가 실패해서 본 노트는 meta-pytorch/monarch repo + 일반 distributed systems 도메인 지식 기반.
Monarch
single controller
actor mesh
supervision tree
RDMA
Rust
PyTorch native
fault tolerance
A·C
Speakers
Allen Wang · Colin Taylor
Meta · PyTorch · Monarch maintainer · Rust + Python 분산 시스템 디자인
§ 01강의가 풀려는 문제· why this lecture exists
RL · agentic 시스템에서 “모든 GPU 가 같은 일” 의 가정이 깨진다
SPMD (Single Program Multiple Data) 는 학습 시대의 천재적 결정이었다. torchrun --nproc_per_node=8 한 줄이면 8 GPU 가 같은 코드를 같은 속도로. 그러나 — RL 학습, agentic 시스템, multimodal serving 에서는 GPU 마다 다른 역할이다. SPMD 가 자연스럽지 않다.
강의의 frame
“distributed PyTorch 의 다음 단계는 SPMD 의 한계를 인정하는 것이다. 모든 GPU 가 같은 코드를 도는 게 아니라, 한 controller 가 mesh of actors 를 imperative 하게 조작한다 — 마치 single machine 위 코드처럼.”
강의의 끝에 손에 잡혀야 하는 건 4개의 추상(ProcMesh, ActorMesh, broadcast, RDMA)과 1개의 패러다임 전환(SPMD → single controller). 그리고 “언제 SPMD 를 깨고 single controller 로 갈 가치가 있는가” 의 판단 기준.
“single controller 는 1990년대 MPI 시대의 패배한 모델이었다. 2025년 — RL 과 agent 가 그 모델을 다시 부른다.”학습 노트
§ 02single controller vs SPMD· two paradigms
같은 분산 시스템을 두 방식으로 — 그리고 결정적으로 다른 mental model
강의의 가장 중요한 슬라이드. 두 패러다임의 nuance 를 이 자리에서 잡지 못하면 Monarch 의 디자인이 안 풀린다.
SPMD — Single Program Multiple Data
DDP · FSDP · Megatron · torchrun
- 모든 process 가 같은 코드.
rank 만 다름.
- collective (all-reduce, all-gather) 가 1차 시민. SPMD 가정 위에서 NCCL 이 동작.
- 장점: high throughput · low overhead · 구현 단순.
- 한계: 역할이 다른 process를 표현하기 거칠다. RL 의 rollout/learner/ref 가 자연스럽게 안 맞음.
- 실패 모델: 한 rank 의 실패가 모든 rank 의 실패. 합리적 graceful degradation 이 어렵다.
- 코드 mental model: “내가 rank 0 이면 이 일을, rank 1 이면 저 일을” 의 분기로 다른 역할을 흉내.
if rank == 0: 폭발.
single controller — actor mesh
Monarch · Ray · ParamServer (~원조)
- 한 controller 가 worker mesh 를 imperative 하게 조작.
worker.compute(x) 처럼.
- actor 가 1차 시민. process 마다 다른 역할 가능.
- 장점: 역할 분리 자연스러움. fault tolerance · supervision · 유연한 토폴로지.
- 한계: high-throughput collective 가 더 비싸다. controller 가 bottleneck 될 수 있음.
- 실패 모델: actor 단위 실패가 supervision tree 위로 propagate. 한 actor 죽어도 다른 일 계속.
- 코드 mental model: “single machine 위에서 여러 객체를 조작하는 것처럼”. RDMA 와 actor 매핑이 가려진다.
왜 SPMD 가 한 시대를 지배했나
학습은 같은 일이다 — forward · backward · all-reduce. 모든 GPU 가 같은 code 를 동기화로 도는 게 자연스럽다. NCCL 이 그 가정 위에서 SOTA. 학습이 single program 이라는 가정이 컴파일러/통신 모두를 단순화한다.
그러나 RL 학습은 — rollout 은 sampler GPU, reward 는 별도 GPU, learner 는 backward GPU. 같은 코드가 아니다. SPMD 위에서 if rank in rollout_ranks: 식으로 분기하면 코드가 빠르게 망가진다. 역할 분리가 첫 시민이어야 깨끗하다.
§ 03Monarch 의 추상· process · actor · mesh
4개의 추상 — proc · actor · mesh · message
Monarch 의 코드는 결국 4개 추상 위에서 짜인다. 이 4개를 잡으면 나머지는 derivative.
L1 · ProcMesh
process 들의 grid. spawn(hosts=4, gpus_per_host=8) → 32 process 의 mesh. 자원 (GPU 수, RAM) 을 명시. “어디에서 도는가” 의 layer.
L2 · ActorMesh
ProcMesh 위에 actor 의 grid 를 올림. 각 actor 는 user-defined Python class. ActorMesh[Worker] 가 32개의 Worker actor. “무엇이 도는가” 의 layer.
L3 · message · broadcast
actor 와의 상호작용은 method 호출. workers.compute(x) 가 모든 worker 에 broadcast. 또는 특정 actor 에 unicast.
L4 · RDMA · sharded tensor
point-to-point GPU↔GPU 또는 CPU↔GPU 메모리 transfer. 분산 tensor API 로 sharding 표현. controller 코드는 single tensor 처럼 보이나 actor mesh 위에 sharded.
# pseudo-code — Monarch 패턴
from monarch import proc_mesh, Actor, endpoint
class Worker(Actor):
def __init__(self):
self.model = build_model().cuda()
@endpoint
async def forward(self, x):
return self.model(x)
@endpoint
async def sync(self, peer):
# RDMA point-to-point
await rdma.transfer(self.model, peer)
# controller 측 — single machine 처럼
async def main():
# 32 worker mesh
procs = await proc_mesh(
hosts=4, gpus_per_host=8,
)
workers = await procs.spawn(
"workers", Worker,
)
# 모든 worker 에 broadcast 호출
outputs = await workers.forward(batch)
# 한 worker 에만 unicast — index
one = await workers[0].forward(batch)
# actor 사이 RDMA
await workers[0].sync(workers[1])
패턴이 친숙한 이유
Monarch 의 controller 코드는 “single machine python 같다”. await workers.forward(batch) 가 32 GPU 위에서 도는 일임에도 코드는 list comprehension 보다 단순. SPMD 의 “모든 rank 가 같은 코드” 의 인지 부담을 single controller 로 가린다.
§ 04actor model 매핑· Erlang heritage
1980년대의 actor model 이 ML 분산 시스템에 다시 등장
Monarch 의 디자인 결정은 새로운 게 아니다 — Erlang/OTP 의 actor model 이 30년간 fault-tolerant distributed system 의 표준 방법이었다. Monarch 는 그 정신을 ML stack 에 옮긴다.
- actor = 격리된 process. 자기 state 만 관리. 다른 actor 와는 message 로만 소통.
- message passing. 공유 메모리 없음 — race condition 의 큰 부류 제거.
- let it crash. 한 actor 죽으면 — supervisor 가 새 actor 로 교체. 방어 코드 대신 단단한 격리.
- location transparency. actor 가 같은 process 안인지 다른 머신 위인지 — 호출자는 모름. controller 코드는 어느 쪽이든 같음.
FIG · actor mesh 위에서 한 actor 의 죽음fault propagation
host A
A0
A1
A2
A3
A4
A5
A6
host B
A7
A8
A9 †
A10
A11
A12
A13
host C
A14
A15
A16
A17
A18
A19
A20
host D
A21
A22
A23
A24
A25
A26
A27
A9 가 죽었다. SPMD 모델이면 모든 rank 가 함께 죽음 (또는 NCCL collective 위에서 영원히 hang). actor model 에서는 — supervisor 가 A9 의 죽음을 감지해 새 actor 로 교체, 다른 27 개 actor 는 일을 계속. controller 코드에 except ActorDied: 한 줄로 표현.
“fault tolerance 는 코드 안에서 ‘예외 처리’ 가 아니라, framework 의 default 행태여야 한다.”학습 노트
§ 05fault tolerance — supervision tree· resilience
actor 의 죽음이 위로 전파 — controller 가 결정
Monarch 의 fault tolerance 는 Erlang/OTP 의 supervision tree 를 차용. actor 가 죽으면 부모 actor (또는 supervisor) 에 통보. supervisor 가 정책에 따라 — restart, escalate, ignore.
- one-for-one: 죽은 actor 만 restart. 가장 단순. RL 의 rollout actor 가 한 개 죽었을 때.
- all-for-one: 한 actor 죽으면 같은 그룹 전체 restart. 학습의 데이터 병렬에서 한 GPU 가 ECC 에러 → 전체 batch 다시.
- rest-for-one: 죽은 actor 와 그 후속 actor 만 restart. pipeline 의 한 stage 가 망가졌을 때.
- escalate: 자식의 실패를 부모에 위임. 부모도 못 풀면 더 위로.
학습 시나리오 — supervised tree 의 자연성
RL 학습: rollout 그룹 8 actor + reward actor 1 + ref model actor 1 + learner 그룹 4 actor. rollout actor 한 개 죽음 → one-for-one 으로 restart. reward actor 죽음 → all-for-one 으로 모든 rollout 재시작 (cache 일관성). learner 한 개 죽음 → all-for-one (FSDP). 정책이 actor 그룹마다 다르게 표현 가능.
그리고 RDMA 의 자리. Monarch 는 direct GPU↔GPU memory transfer 를 1차 시민으로. NCCL collective 의 단순한 broadcast 위에 — point-to-point custom transfer. RL 의 weight sync (learner → rollout) 같은 비균질한 패턴이 자연스럽게 표현된다.
§ 06example — distributed training· walk-through
같은 학습을 SPMD 와 Monarch 로 — 코드 비교
실제 코드로 보면 Monarch 의 ergonomic 이 SPMD 대비 어떤 형태인지가 명확해진다. RL 학습의 한 step 을 두 패러다임으로.
# SPMD — 같은 코드를 모든 rank 가 실행
def train_step():
rank = dist.get_rank()
if rank in ROLLOUT_RANKS:
traj = collect_trajectory()
# trajectory 를 learner 로 전달?
# gather/scatter 가 복잡
dist.gather(traj, dst=LEARNER_RANK)
elif rank in LEARNER_RANKS:
traj = dist.gather(...)
loss = compute_loss(traj)
loss.backward()
# 새 weight 를 ROLLOUT_RANKS 로
broadcast_weights(model, ROLLOUT_RANKS)
elif rank in REWARD_RANKS:
...
# 코드가 if/elif 폭발 — 역할이 늘면 더 더러워짐
# Monarch — controller 가 imperative 하게
async def train_step(rollouts, rewards, learners):
# 1. rollout 그룹에 sample
trajs = await rollouts.collect()
# 2. reward 계산
scored = await rewards.score(trajs)
# 3. learner 가 backward
new_w = await learners.update(scored)
# 4. weight 를 rollout 으로 RDMA
await rollouts.set_weights(new_w)
# 코드가 그냥 한 흐름 — 마치 single machine
같은 일을 한다. 그러나 두 코드의 가독성이 결정적으로 다르다. Monarch 의 controller 코드는 “이 학습이 무엇을 하는지” 가 직접 읽힌다. SPMD 코드는 “이 rank 가 어떤 일을 하는지” 의 분기를 머릿속에서 풀어야 한다.
cost — 이 ergonomic 의 가격은 무엇인가
Monarch 의 per-message overhead 가 SPMD 의 NCCL collective 보다 비싸다. 대규모 학습의 hot path 인 all-reduce 같은 자리는 여전히 SPMD/NCCL 이 빠르다. Monarch 의 sweet spot 은 — collective 가 hot path 가 아닌 시스템 (RL, agent, multimodal). 또는 SPMD 와 hybrid (Monarch controller 안에서 SPMD 그룹을 actor 로).
§ 07Ray 와의 차이· positioning
같은 actor model 의 두 구현 — 다른 가정
차원
Ray
Monarch
SPMD
언어
Python + C++
Rust 코어 + Python 바인딩
PyTorch (Python + C++)
scope
general distributed Python
PyTorch / ML 특화
학습 데이터 병렬
tensor primitive
object store + serialize
distributed tensor + RDMA
torch.Tensor + collective
fault tolerance
actor restart · 정책 다양
supervision tree · Erlang-style
전체 재시작 (보통)
생태계
RLLib · Tune · Serve
PyTorch native · 신규
PyTorch · Megatron · DeepSpeed
사용 자리
RL · 일반 분산
RL · agent · 학습 운영
대규모 사전학습
성숙도
production grade
experimental
production grade
Monarch 의 차별점은 “PyTorch native”. tensor 가 1차 시민이고, RDMA 가 framework 안에 있고, supervision tree 가 actor 의 기본 행태. Ray 는 더 generic 한 distributed Python — 그래서 ML 외 영역에서도 강력하지만 ML 쪽으로는 한 layer 의 wrapping 이 필요.
Rust 코어의 의미
Monarch 가 Rust 위에 짠 결정 — 분산 시스템의 안정성/성능을 위한 typed concurrency. 그리고 Python 의 GIL 과 별개로 actor scheduler 가 도는 점. “Rust 가 ML infrastructure 의 다음 시스템 언어” 의 하나의 사례.
§ 08채택· in the wild
아직 experimental — 그러나 명확한 자리
Monarch 가 v0 단계임에도 흥미로운 자리에서 등장하기 시작.
- torchforge — PyTorch 의 agentic RL framework. Monarch 위에 actor 분산. OpenEnv (L091) 와 자연스럽게 결합.
- internal Meta workloads — 정확한 사례는 미공개. RL training run 의 일부 자리.
- research workloads — Berkeley, CMU 등의 분산 RL 연구. Ray 의 친숙함 + PyTorch native 의 타협으로 매력.
- 학습 운영 layer — L090 (resilient ML eng) 의 자동화된 형태. supervision tree 가 framework default 면 운영 코드가 줄어든다.
§ 09한계 — experimental stage· limitations
repo README 가 명시 — “bugs, incomplete features, APIs that may change”
- 대규모 학습의 hot path 가 아님 — pure data 병렬 학습은 여전히 FSDP/Megatron 이 더 빠름.
- collective 의 부분 지원 — NCCL all-reduce 같은 patterned collective 는 Monarch 안에서 actor 로 표현하면 overhead. 하이브리드가 권장.
- build 부담 — Rust nightly + cmake + CUDA 가 모두 필요. 특히 source build 가 거칠다.
- pre-built wheel — 일부 플랫폼 한정. 일반 사용자가 시도하기 아직 진입장벽.
- API 변동 가능성 — repo 가 명시. 1.0 까지 backward compat 보장 없음.
- 디버깅 도구 — actor mesh 위 분산 디버깅의 도구가 미성숙. SPMD 의 py-spy 같은 standard 가 아직.
언제 도입할 가치
1. RL/agent 시스템이고 SPMD 의 if/elif 폭발이 이미 코드에 보일 때. 2. fault tolerance 가 critical 인 운영 환경. 3. Rust 의 시스템 언어 매력이 팀의 다른 선호와 맞을 때. 셋 중 하나도 강하지 않다면 — Ray 또는 SPMD 가 더 안정적.
§ 10기억할 메모와 실습· key takeaways
다시 열었을 때 5분 안에 잡혀야 할 것
single controller vs SPMD
SPMD 는 “모든 rank 같은 코드”. single controller 는 “controller 가 mesh 를 imperative 조작”. 역할 분리 / fault 가 자연스러운 자리.
ProcMesh + ActorMesh
process grid 위에 actor grid 를 올린다. spawn(hosts=4, gpus_per_host=8) → 32 process mesh.
supervision tree
actor 가 죽으면 supervisor 에 propagate. one-for-one / all-for-one / rest-for-one 정책.
RDMA + sharded tensor
point-to-point GPU 메모리 transfer 가 framework 안에. distributed tensor 가 controller 에는 single 처럼.
location transparency
actor 가 같은 process 든 다른 머신이든 — 호출자는 모름. controller 코드는 단일 형태.
PyTorch native
tensor / NCCL / RDMA 가 1차 시민. Ray 의 generic 보다 ML 친화적.
Rust 코어
분산 scheduler 가 Rust. Python 의 GIL 과 별개. async-first.
experimental v0
API 변동 가능, build 거칠다. 1.0 이전 backward compat 보장 없음.
실습 시퀀스
- Monarch hello world — repo 의 example 로 첫 ProcMesh 띄우고 actor spawn. 가장 작은 controller 코드 한 step 실행.
- actor 죽이기 — 일부러 한 actor 안에서 raise. supervisor 가 어떻게 받는지, 다른 actor 가 어떻게 살아남는지 확인.
- broadcast vs unicast —
workers.foo() 와 workers[i].foo() 의 차이. 같은 mesh 위 두 패턴.
- RDMA transfer — actor 사이 GPU 메모리 직접 transfer. tensor 시간 측정 + NCCL all-reduce 시간 비교.
- RL toy — 4 rollout actor + 1 learner actor 의 simple GRPO. SPMD 버전과 코드 길이 비교.
Relatedtorchforge · OpenEnv (L091) — RL workload 의 채택
§ 11다른 강의로 이어지는 길· connections
분산 / RL / fault tolerance 시리즈 안에서
§ 12열린 질문· open questions
다음에 다시 들었을 때 직접 검증해야 할 것들
- transcript 가 실패해서 본 노트의 코드 예시는 repo README + 일반 actor model 패턴. 정확한 API 시그니처는 repo 의 example 코드에서.
- Ray 와의 throughput 비교 — 같은 RL workload 에서 두 framework 의 이득/손해 정량 비교가 강의에 있었을 가능성.
- FSDP 와의 hybrid — Monarch controller 안에서 SPMD 그룹을 actor 로 두는 패턴. 강의에서 어떻게 권장했는지.
- RDMA backend 의 정확한 지원 — IB / NVLink / RoCE 의 어디까지 자동인지.
- internal use 의 사례 — Meta 안에서 어떤 학습 run 에서 실제로 채택됐는지 (강의에 살짝 등장 가능성).
- 1.0 로드맵 — API freeze 시점, 빌드 단순화, 디버깅 도구 도입 일정.
검증 메모
본 노트의 supervision strategy 분류 (one-for-one 등) 는 Erlang/OTP 의 일반 용어. Monarch 의 정확한 정책 이름과 default 는 repo 의 docs 에서 확인. 본문 § 06 의 RL 시나리오는 일반화된 패턴 — 실제 torchforge 의 코드 형태와 약간 다를 수 있다.