gpumode · 강의 아카이브
《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 분산 시스템 디자인
강의 번호
L095
스피커
Allen Wang · Colin Taylor
학습 우선순위
High · 정독
자막 상태
failed · repo 보강
§ 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 에 옮긴다.

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.

학습 시나리오 — 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 단계임에도 흥미로운 자리에서 등장하기 시작.

§ 09한계 — experimental stage· limitations

repo README 가 명시 — “bugs, incomplete features, APIs that may change”

언제 도입할 가치

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 보장 없음.

실습 시퀀스

  1. Monarch hello world — repo 의 example 로 첫 ProcMesh 띄우고 actor spawn. 가장 작은 controller 코드 한 step 실행.
  2. actor 죽이기 — 일부러 한 actor 안에서 raise. supervisor 가 어떻게 받는지, 다른 actor 가 어떻게 살아남는지 확인.
  3. broadcast vs unicastworkers.foo()workers[i].foo() 의 차이. 같은 mesh 위 두 패턴.
  4. RDMA transfer — actor 사이 GPU 메모리 직접 transfer. tensor 시간 측정 + NCCL all-reduce 시간 비교.
  5. RL toy — 4 rollout actor + 1 learner actor 의 simple GRPO. SPMD 버전과 코드 길이 비교.
Repometa-pytorch/monarch · 69.6% Rust
Relatedtorchforge · OpenEnv (L091) — RL workload 의 채택
§ 11다른 강의로 이어지는 길· connections

분산 / RL / fault tolerance 시리즈 안에서

§ 12열린 질문· open questions

다음에 다시 들었을 때 직접 검증해야 할 것들

검증 메모

본 노트의 supervision strategy 분류 (one-for-one 등) 는 Erlang/OTP 의 일반 용어. Monarch 의 정확한 정책 이름과 default 는 repo 의 docs 에서 확인. 본문 § 06 의 RL 시나리오는 일반화된 패턴 — 실제 torchforge 의 코드 형태와 약간 다를 수 있다.

← Lecture 094tvm-ffi Lecture 096 →TLX