docker pull to a running GRPO training job on Qwen3-4B. It
assumes an 8-GPU node (H100 / H200 / B-series) and roughly 200 GB of disk. For other
models, see Models.
A Miles job combines two engines: SGLang
generates responses from the current policy (the rollout), and
Megatron-LM updates the policy from those
responses (the training). In this recipe both share the same 8 GPUs.
1. Start the container
On the host:--gpus all exposes the GPUs, --ipc=host and --shm-size=32g
give NCCL and Ray the shared memory they need, and --network=host lets you reach
the Ray dashboard from the host.
That drops you into a shell inside the container. The image ships with Miles at
/root/miles and Megatron-LM at /root/Megatron-LM. Refresh the editable install
so you run the latest main:
2. Download model and data
Three artifacts are needed: the model you will train, a training prompt set, and an evaluation set.3. Convert to Megatron format
Megatron consumes atorch_dist checkpoint, not the raw HuggingFace directory. The
source line below loads MODEL_ARGS, the Megatron-side description of the
architecture (layer count, hidden sizes, attention layout); the converter uses it to
map the HuggingFace weights into a sharded torch_dist checkpoint.
--hf-checkpoint).
4. Launch training
CKPT_ARGS, ROLLOUT_ARGS,
GRPO_ARGS, and so on) and is meant to be read and edited — it is the canonical
place to change hyperparameters. When launched, it starts a local Ray cluster and
submits train.py as a Ray job. The run is colocated (--colocate): the four
SGLang engines (2 GPUs each) and the Megatron trainer share the same 8 GPUs,
alternating between generation and training phases.
A few defaults worth knowing on a first run:
- Checkpoints are written to
/root/Qwen3-4B_miles/every 20 rollouts (--save-interval 20). - The policy is evaluated on AIME-2024 every 20 rollouts (
--eval-interval 20). - If the run dies, relaunch the same script —
--loadpoints at the save directory, so training resumes from the last checkpoint. - The Ray dashboard at
http://localhost:8265shows per-worker logs and GPU usage.
rollout/raw_reward is the mean reward of the freshly scored responses — the number
to watch. The step line reports each optimizer step, and the two perf lines time
the generation side (perf/rollout_time) and the training side
(perf/actor_train_time) of the iteration. The same metrics go to wandb when
--use-wandb is set.
5. What’s happening
Each iteration runs the same four steps:- Sample
rollout-batch-sizeprompts from the dataset and let the SGLang engines generaten-samples-per-promptcandidate responses for each. - Score every response with the reward function —
--rm-type deepscalerin this recipe, a rule-based verifier that compares the model’s final answer against the dataset label. - Compute the GRPO objective from the scored responses and step the optimizer. The
frozen reference model provides the optional KL regularization term (this recipe
sets
--kl-loss-coef 0.00, so the term is off). - Push the updated weights back to the SGLang engines. In this colocated recipe the
trainer and the engines share the same GPUs, so each rank gathers its weight shards
over NCCL, converts them to the HuggingFace layout, and hands them to its local
engine through IPC — no network transfer is involved. Disaggregated runs choose a
transport with
--update-weight-transfer-modeinstead: the defaultbroadcastsends the weights from the trainer to the engines over NCCL, whilep2pwrites them point-to-point over RDMA (via the Mooncake transfer engine) rather than using a collective;p2pcannot be combined with--colocate.
Inspecting a run
Next steps
- Core concepts — the model behind rollout / actor / reference.
- Training script walkthrough — an annotated tour through every argument group in a launch script, plus colocation, dynamic sampling, partial rollout, and BF16+FP8 inference.
- Training backends — Megatron vs FSDP.
- Customization — plug in custom rollout / reward.
- Models — recipes for Qwen3.5, GLM5.2, DeepSeek V4, Kimi K2.6, and more.

