实战示例:从 Hello World 到 GRPO
学完了概念,最好的巩固方式是读真实的代码。本章带你走读官方仓库 examples/ 与 docs/source/examples/ 中的代表性示例,从易到难。
1. Hello World + 点对点:ping_pong.py
入门第一课:Actor 的启动、call 广播、slice 定点调用,以及 Actor 与 Actor 互相通信。
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 间消息
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 开发流"的教学案例,三层递进:
第一层:朴素版——反传与梯度归约交错进行:
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 让你在假想网格上验证并行策略的正确性,再上真机:
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.py | OpenTelemetry 指标导出到外部后端 |
kubernetes/ / skypilot/ | 容器与云调度部署 |
presentation/presentation.ipynb | 官方 demo notebook |
动手建议
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 开始,改一点、跑一次,比读十遍文档都有效。
