Skip to content

实战示例:从 Hello World 到 GRPO ​

学完了概念,最好的巩固方式是读真实的代码。本章带你走读官方仓库 examples/ 与 docs/source/examples/ 中的代表性示例,从易到难。

1. Hello World + 点对点:ping_pong.py ​

入门第一课:Actor 的启动、call 广播、slice 定点调用,以及 Actor 与 Actor 互相通信。

python
from monarch.actor import Actor, current_rank, endpoint, this_host

NUM_ACTORS = 4

class ToyActor(Actor):
    def __init__(self):
        # current_rank():Actor 内部获取自己的 rank
        self.rank = current_rank().rank

    @endpoint
    def hello_world(self, msg):
        print(f"Identity: {self.rank}, {msg=}")

local_proc_mesh = this_host().spawn_procs(per_host={"gpus": NUM_ACTORS})
toy_actor = local_proc_mesh.spawn("toy_actor", ToyActor)

# 一条消息打给全部 4 个 Actor
toy_actor.hello_world.call("hey there, from script!!").get()

# 也可以逐个定点调用
futures = []
for idx in range(NUM_ACTORS):
    actor_instance = toy_actor.slice(gpus=idx)
    futures.append(actor_instance.hello_world.call_one(f"unique value: {idx}"))
for fut in futures:
    fut.get()

Ping-Pong:Actor 间消息 ​

python
class ExampleActor(Actor):
    def __init__(self, actor_name):
        self.actor_name = actor_name

    @endpoint
    def init(self, other_actor):
        # 保存对端 ActorMesh 的引用
        self.other_actor = other_actor
        # 用自己的 rank 坐标选中对端对应的那个实例
        self.other_actor_pair = other_actor.slice(**current_rank())
        self.identity = current_rank().rank

    @endpoint
    def send(self, msg):
        self.other_actor_pair.recv.call(
            f"Sender ({self.actor_name}:{self.identity}) {msg=}"
        ).get()

    @endpoint
    def recv(self, msg):
        print(f"Pong! Receiver ({self.actor_name}:{self.identity}) got {msg}")

# 两组网格、互相初始化、互发消息
actor_0.init.call(actor_1).get()
actor_1.init.call(actor_0).get()
actor_0.send.call("Ping").get()

init 端点接收另一个 ActorMesh 作为参数——Actor 引用的传递在中级教程讲过,这里是官方原版用法。

2. 并发爬虫:crawler.py ​

crawler.py 演示用 Actor 构建并发工作窃取式的爬虫:URL 队列与抓取 worker 都是 Actor,靠消息驱动。它展示了 Monarch 不只能做训练——任何需要大规模并发 + 状态隔离的任务都合适。

3. DDP 训练:distributed_tensors.py 与 slurm_ddp.ipynb ​

官方用 DDP(分布式数据并行)作为"典型 Monarch 开发流"的教学案例,三层递进:

第一层:朴素版——反传与梯度归约交错进行:

python
def train(model, input, target):
    loss = model(input, target)
    rparameters = list(reversed(list(model.parameters())))
    # grad_generator:增量反传,逐个产出参数梯度
    grads = monarch.grad_generator(loss, rparameters)
    with torch.no_grad():
        it = iter(zip(rparameters, grads))
        todo = next(it, None)
        while todo is not None:
            param, grad = todo
            grad.reduce_("dp", "sum")   # 边反传边沿 dp 维归约
            todo = next(it, None)
            param += 0.01 * grad        # 边归约边更新

第二层:模拟器先行——monarch.Simulator 让你在假想网格上验证并行策略的正确性,再上真机:

python
def simulate():
    simulator = monarch.Simulator(hosts=1, gpus=4, trace_mode="stream_only")
    mesh = simulator.mesh.rename(gpu="dp")
    with mesh.activate():
        model = Net()
        train(model, torch.rand(3, 4), torch.full((3,), 1, dtype=torch.int64))
        simulator.display()   # 可视化时间线

第三层:通信/计算重叠——monarch.Stream + borrow 把 allreduce 放到独立流上与反传重叠,模拟器确认重叠效果后再改真机代码。这个"先模拟后落地"的开发流,是 Monarch 交互式调试能力的最佳展示。

4. LLM 预训练:slurm_titan.ipynb ​

TorchTitan + Monarch 的完整 notebook:在 Slurm 集群上交互式编排 Llama 预训练。Notebook 只是一扇窗,训练 Actor 在集群上持续运行——断开重连,训练还在跑。详见《生态集成》一章。

5. 强化学习:grpo 系列 ​

grpo_sim.py、grpo_actor.py、grpo_te_sim.py、grpo_yield.py 等一组示例,完整演示 GRPO 在 Monarch 上的编排:

  • Generator(生成 rollout)、Inference(打分)、Trainer(更新策略)各是一个 ActorMesh;
  • 控制器是简单循环,Actor 引用在网格间流转;
  • _sim 后缀的版本用模拟器跑,无需 GPU 即可验证编排逻辑。

这是"单控制器 + 异构网格"范式最完整的官方样板,值得精读。

6. 其他实用示例 ​

示例一句话说明
hello_gather_mount.py最小可运行的 gather mount 用法
debugging.py远程调试套路
gpu_sharing.py多 Actor 共享 GPU 的正确姿势
rdma_pingpong/RDMA 往返基准
remotemount/远程挂载
otel_collector.pyOpenTelemetry 指标导出到外部后端
kubernetes/ / skypilot/容器与云调度部署
presentation/presentation.ipynb官方 demo notebook

动手建议 ​

bash
git clone https://github.com/meta-pytorch/monarch.git
cd monarch

# CPU 环境即可跑通大部分 Actor 示例
USE_TENSOR_ENGINE=0 uv sync
uv run python docs/source/examples/ping_pong.py

从 ping_pong.py 开始,改一点、跑一次,比读十遍文档都有效。

Monarch中文教程