Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
4d17e8a
add mtp support
zanderjiang Jun 3, 2026
1a9d791
decoupled CE loss for MTP weight update
zanderjiang Jun 5, 2026
c25ddd5
update megatron model wrapper, pass in position ids for MTP
zanderjiang Jun 5, 2026
45931e6
add mtp spec-decode config, tests, spec decoding acceptance rate logging
zanderjiang Jun 6, 2026
15f757f
fix spec decode config not passing through to inference engine ray wr…
zanderjiang Jun 7, 2026
99b65aa
update model capture for Mamba Models
zanderjiang Jun 8, 2026
64799a0
reorganize tests, improve CE loss to be more memory efficient
zanderjiang Jun 8, 2026
98202fe
fix bug, mtp storing student logits across microbatches, causing OOM
zanderjiang Jun 8, 2026
7ba31fc
add top k soft CE loss
zanderjiang Jun 8, 2026
2440d28
fix oom
zanderjiang Jun 10, 2026
ca33d92
fix roll mismatch in Hard CE, k > 1 mtp support
zanderjiang Jun 10, 2026
8493141
add test cases and running scripts
zanderjiang Jun 10, 2026
2e824f0
fix trainer slow bug
zanderjiang Jun 15, 2026
cad26fc
fix vllm metrics logger throughput calculation using step time
zanderjiang Jun 15, 2026
4037dc6
Merge branch 'NovaSky-AI:main' into logger
zanderjiang Jun 15, 2026
8e6b355
fix logging
zanderjiang Jun 16, 2026
b82dcfb
separate eval against train rollout metrics
zanderjiang Jun 16, 2026
ecc628a
Merge branch 'logger' of https://github.com/zanderjiang/SkyRL into lo…
zanderjiang Jun 16, 2026
a94e546
Merge branch 'NovaSky-AI:main' into logger
zanderjiang Jun 16, 2026
c07d1d1
Merge branch 'NovaSky-AI:main' into logger
zanderjiang Jun 16, 2026
b0183f4
format comments
zanderjiang Jun 16, 2026
082e471
remove legacy code
zanderjiang Jun 16, 2026
ad96002
Merge origin/main into mtp
zanderjiang Jun 16, 2026
5802b90
reduce comments
zanderjiang Jun 17, 2026
8c9d7eb
support sequence packing with mtp
zanderjiang Jun 18, 2026
34315ff
Merge branch 'NovaSky-AI:main' into logger
zanderjiang Jun 23, 2026
5c477db
[mtp] Add full separate MTP optimizer + isolated DDP grad buffer (C-f…
zanderjiang Jun 24, 2026
57f14a0
Move train/eval rollout timing into VLLMMetricsScraper window API
zanderjiang Jun 24, 2026
f750215
[mtp] Fix C-full hidden() to actually exclude the MTP head from the p…
zanderjiang Jun 24, 2026
30a4997
[mtp] Disable Megatron's native in-forward MTP loss via call-site mon…
zanderjiang Jun 24, 2026
eae60f5
[mtp] Add SKYRL_DISABLE_SPEC debug guard (train MTP head, plain rollout)
zanderjiang Jun 24, 2026
b1a2c2d
Merge branch 'logger' into mtp
zanderjiang Jun 24, 2026
d1b89d9
adjust training scripts to dedicated folder
zanderjiang Jun 25, 2026
94e8c8a
Merge branch 'NovaSky-AI:main' into mtp
zanderjiang Jun 25, 2026
ad5665e
Merge branch 'NovaSky-AI:main' into mtp
zanderjiang Jun 25, 2026
edfd8eb
remove 2b script, update comments
zanderjiang Jun 25, 2026
933b751
Merge branch 'mtp' of https://github.com/zanderjiang/SkyRL into mtp
zanderjiang Jun 25, 2026
f69e38a
simpliy commentation
zanderjiang Jun 25, 2026
dfae339
Merge origin/main into mtp (vLLM 0.23.0 + scraper throughput fix)
zanderjiang Jun 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 165 additions & 0 deletions examples/train/megatron/run_megatron_dapo_mimo_7b_rl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
set -x

# Colocated DAPO training+generation for XiaomiMiMo/MiMo-7B-RL (dense) on DAPO with
# Megatron. This is the non-speculative-decoding counterpart of
# run_megatron_dapo_mimo_7b_rl_specdecode.sh: MTP training + vLLM MTP speculative decoding are
# disabled, everything else (DAPO knobs, model, parallelism, sampling) is kept identical so the
# two runs are directly comparable.
#
# The backbone is a plain Qwen2-style dense transformer (36 layers, full attention,
# `attention_bias: true`), so there are NO GDN / linear-attention layers. Two consequences:
# (a) megatron sample packing IS supported, so we set remove_microbatch_padding=true for better
# throughput; (b) we drop the `gdn_prefill_backend` vLLM engine kwarg -- it does nothing here.
#
# Runs on 1 node of 8xH100s (80GB each).
#
# Prepare data onto the fast local disk first:
# DATA_DIR=/mnt/local_storage/data/dapo bash examples/train/algorithms/dapo/prepare_dapo_data.sh
# Then launch:
# bash examples/train/megatron/run_megatron_dapo_mimo_7b_rl.sh

MODEL_NAME="XiaomiMiMo/MiMo-7B-RL"
# Use the fast, non-persistent local disk for data (not the ~/default quota).
DATA_DIR="/mnt/local_storage/data/dapo"
TRAIN_FILE="$DATA_DIR/dapo-math-17k-cleaned.parquet"
TEST_FILE="$DATA_DIR/aime-2024-cleaned.parquet"
NUM_NODES=1
NUM_GPUS_PER_NODE=8
# One vLLM engine per GPU (TP=1). A single MiMo-7B copy is ~14GB in bf16, which fits
# comfortably per engine alongside KV cache at gpu_memory_utilization=0.5 (the policy is offloaded
# during generation under colocate_all).
NUM_INFERENCE_ENGINES=8
INFERENCE_ENGINE_TENSOR_PARALLEL_SIZE=1
LOGGER="wandb" # change to "console" to print to stdout

CLIP_RATIO_LOW=0.2
CLIP_RATIO_HIGH=0.28
# use token mean loss reduction
LOSS_REDUCTION="token_mean"
# applies overlong filtering (but not soft overlong punishment)
APPLY_OVERLONG_FILTERING=true
# apply soft overlong punishment with custom trainer impl in main_dapo.py
OVERLONG_BUFFER_LEN=$((1024 * 4))
OVERLONG_BUFFER_PENALTY_FACTOR=1.0

# other DAPO parameters
USE_KL_LOSS=false
TEMPERATURE=1.0
TOP_P=1.0
EVAL_TOP_P=0.7
CLIP_RATIO_C=10.0
MAX_PROMPT_LENGTH=$((1024 * 2))
MAX_RESPONSE_LENGTH=$((1024 * 8))
# MiMo-7B-RL has max_position_embeddings=32768, so 2K prompt + 8K response fits with room to spare.

# repro run parameters
TRAIN_BATCH_SIZE=32
MINI_BATCH_SIZE=32
N_SAMPLES_PER_PROMPT=8
EVAL_N_SAMPLES_PER_PROMPT=16
ENFORCE_EAGER=true # cuda graphs can cause some instability
LR=1e-6

# megatron config -- MiMo-7B-RL is a dense model, so no expert parallelism.
# TP=4: 7B params + Adam states + 8K-token activations fit at micro batch 1 with headroom.
# TP>1 auto-enables sequence parallelism, sharding activations/vocab-logits across the TP group.
# TP=4, PP=1, CP=1 => DP=2. TP stays within the single-node NVLink domain. (7B is smaller than the
# Qwen3.5-9B recipe, so TP=2 => DP=4 likely also fits and gives more throughput -- try it if you
# have headroom.)
MEGATRON_TP=4
MEGATRON_PP=1
MEGATRON_CP=1
MEGATRON_EP=1
MEGATRON_ETP=null

# optimizer offload -- OFF by default (with colocate_all the inference engine is
# offloaded during training, so the full 80GB is available for the optimizer).
# Flip to true if you hit OOM in the optimizer step / grad sync.
OPTIMIZER_OFFLOAD=false
OPTIMIZER_OFFLOAD_FRACTION=1.0

# TIS parameters
TIS_IMP_RATIO_CAP=2.0
TIS_TYPE=token


# MiMo flags -- plain Qwen2-style dense attention (no GDN), so sample packing is supported and no
# special vLLM prefill backend is needed.
REMOVE_MICROBATCH_PADDING=true
DISTRIBUTED_EXECUTOR_BACKEND="mp"
export _SKYRL_USE_NEW_INFERENCE=0
export VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS=1800

uv run --isolated --extra megatron -m examples.train.algorithms.dapo.main_dapo \
data.train_data="['$TRAIN_FILE']" \
data.val_data="['$TEST_FILE']" \
trainer.algorithm.advantage_estimator="grpo" \
trainer.algorithm.policy_loss_type="dual_clip" \
trainer.algorithm.overlong_buffer_len=$OVERLONG_BUFFER_LEN \
trainer.algorithm.overlong_buffer_penalty_factor=$OVERLONG_BUFFER_PENALTY_FACTOR \
trainer.algorithm.loss_reduction=$LOSS_REDUCTION \
generator.inference_engine.enforce_eager=$ENFORCE_EAGER \
generator.apply_overlong_filtering=$APPLY_OVERLONG_FILTERING \
generator.sampling_params.temperature=$TEMPERATURE \
generator.sampling_params.top_p=$TOP_P \
generator.eval_sampling_params.top_p=$EVAL_TOP_P \
generator.eval_sampling_params.temperature=$TEMPERATURE \
generator.eval_sampling_params.max_generate_length=$MAX_RESPONSE_LENGTH \
trainer.algorithm.use_kl_loss=$USE_KL_LOSS \
trainer.algorithm.clip_ratio_c=$CLIP_RATIO_C \
trainer.policy.model.path="$MODEL_NAME" \
trainer.placement.colocate_all=true \
trainer.strategy=megatron \
generator.inference_engine.distributed_executor_backend="$DISTRIBUTED_EXECUTOR_BACKEND" \
trainer.placement.policy_num_nodes=$NUM_NODES \
trainer.placement.policy_num_gpus_per_node=$NUM_GPUS_PER_NODE \
generator.inference_engine.num_engines=$NUM_INFERENCE_ENGINES \
generator.inference_engine.tensor_parallel_size=$INFERENCE_ENGINE_TENSOR_PARALLEL_SIZE \
trainer.policy.megatron_config.tensor_model_parallel_size=$MEGATRON_TP \
trainer.policy.megatron_config.pipeline_model_parallel_size=$MEGATRON_PP \
trainer.policy.megatron_config.context_parallel_size=$MEGATRON_CP \
trainer.policy.megatron_config.expert_model_parallel_size=$MEGATRON_EP \
trainer.policy.megatron_config.expert_tensor_parallel_size=$MEGATRON_ETP \
trainer.policy.megatron_config.optimizer_config_kwargs.overlap_cpu_optimizer_d2h_h2d=$OPTIMIZER_OFFLOAD \
trainer.policy.megatron_config.optimizer_config_kwargs.use_precision_aware_optimizer=$OPTIMIZER_OFFLOAD \
trainer.policy.megatron_config.optimizer_config_kwargs.optimizer_cpu_offload=$OPTIMIZER_OFFLOAD \
trainer.policy.megatron_config.optimizer_config_kwargs.optimizer_offload_fraction=$OPTIMIZER_OFFLOAD_FRACTION \
trainer.algorithm.off_policy_correction.tis_ratio_type=$TIS_TYPE \
trainer.algorithm.off_policy_correction.token_tis_ratio_clip_high=$TIS_IMP_RATIO_CAP \
trainer.remove_microbatch_padding=$REMOVE_MICROBATCH_PADDING \
trainer.epochs=10 \
trainer.algorithm.eps_clip_low=$CLIP_RATIO_LOW \
trainer.algorithm.eps_clip_high=$CLIP_RATIO_HIGH \
trainer.eval_batch_size=1024 \
trainer.eval_before_train=false \
trainer.eval_interval=5 \
trainer.update_epochs_per_batch=1 \
trainer.train_batch_size=$TRAIN_BATCH_SIZE \
trainer.policy_mini_batch_size=$MINI_BATCH_SIZE \
trainer.micro_forward_batch_size_per_gpu=1 \
trainer.micro_train_batch_size_per_gpu=1 \
trainer.ckpt_interval=-1 \
trainer.max_prompt_length=$MAX_PROMPT_LENGTH \
generator.sampling_params.max_generate_length=$MAX_RESPONSE_LENGTH \
trainer.policy.optimizer_config.lr=$LR \
trainer.policy.optimizer_config.num_warmup_steps=5 \
trainer.policy.optimizer_config.weight_decay=0.1 \
trainer.policy.optimizer_config.max_grad_norm=1.0 \
generator.inference_engine.backend=vllm \
generator.inference_engine.run_engines_locally=true \
generator.inference_engine.weight_sync_backend=nccl \
generator.inference_engine.async_engine=true \
generator.batched=true \
environment.env_class=aime \
generator.n_samples_per_prompt=$N_SAMPLES_PER_PROMPT \
generator.eval_n_samples_per_prompt=$EVAL_N_SAMPLES_PER_PROMPT \
generator.inference_engine.gpu_memory_utilization=0.5 \
trainer.logger="$LOGGER" \
trainer.project_name="mimo_7b_rl_dapo" \
trainer.run_name="nosd_dapo_mimo_7b_rl_megatron_tp${MEGATRON_TP}_pp${MEGATRON_PP}_cp${MEGATRON_CP}" \
trainer.export_path="/mnt/local_storage/exports/dapo_mimo_7b_rl_megatron_tp${MEGATRON_TP}_pp${MEGATRON_PP}_cp${MEGATRON_CP}" \
trainer.hf_save_interval=300 \
trainer.resume_mode=latest \
trainer.max_ckpts_to_keep=3 \
trainer.ckpt_path="/mnt/local_storage/ckpts/dapo_mimo_7b_rl_megatron_tp${MEGATRON_TP}_pp${MEGATRON_PP}_cp${MEGATRON_CP}" \
$@
156 changes: 156 additions & 0 deletions examples/train/megatron/run_megatron_dapo_qwen3.5_9b.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
set -x

# Colocated DAPO training+generation for Qwen3.5-9B (dense) on DAPO with Megatron.
# Runs on 1 node of 8xH100s (80GB each).
#
# NOTE: verify the exact HF repo id for the 9B model before running
# (e.g. `hf download Qwen/Qwen3.5-9B` / check https://huggingface.co/Qwen).
#
# Prepare data onto the fast local disk first:
# DATA_DIR=/mnt/local_storage/data/dapo bash examples/train/algorithms/dapo/prepare_dapo_data.sh
# Then launch:
# bash examples/train/megatron/run_megatron_dapo_qwen3.5_9b.sh

MODEL_NAME="Qwen/Qwen3.5-9B"
# Use the fast, non-persistent local disk for data (not the ~/default quota).
DATA_DIR="/mnt/local_storage/data/dapo"
TRAIN_FILE="$DATA_DIR/dapo-math-17k-cleaned.parquet"
TEST_FILE="$DATA_DIR/aime-2024-cleaned.parquet"
NUM_NODES=1
NUM_GPUS_PER_NODE=8
# 9B is ~4.5x the 2B: a single full-weight copy is ~18GB in bf16. Use inference
# TP=2 (4 engines) so each engine's weights are halved (~9GB/GPU) and there is
# more headroom for KV cache during generation. TP=2 comm stays on NVLink.
NUM_INFERENCE_ENGINES=8
INFERENCE_ENGINE_TENSOR_PARALLEL_SIZE=1
LOGGER="wandb" # change to "console" to print to stdout

CLIP_RATIO_LOW=0.2
CLIP_RATIO_HIGH=0.28
# use token mean loss reduction
LOSS_REDUCTION="token_mean"
# applies overlong filtering (but not soft overlong punishment)
APPLY_OVERLONG_FILTERING=true
# apply soft overlong punishment with custom trainer impl in main_dapo.py
OVERLONG_BUFFER_LEN=$((1024 * 4))
OVERLONG_BUFFER_PENALTY_FACTOR=1.0

# other DAPO parameters
USE_KL_LOSS=false
TEMPERATURE=1.0
TOP_P=1.0
EVAL_TOP_P=0.7
CLIP_RATIO_C=10.0
MAX_PROMPT_LENGTH=$((1024 * 2))
MAX_RESPONSE_LENGTH=$((1024 * 8))

# repro run parameters
TRAIN_BATCH_SIZE=32
MINI_BATCH_SIZE=32
N_SAMPLES_PER_PROMPT=8
EVAL_N_SAMPLES_PER_PROMPT=16
ENFORCE_EAGER=true # cuda graphs can cause some instability
LR=1e-6

# megatron config -- Qwen3.5-9B is a dense model, so no expert parallelism.
# TP=4 (up from 2 on the 2B): 9B params + Adam states + 8K-token activations
# need more sharding to fit at micro batch 1. TP>1 auto-enables sequence
# parallelism, sharding activations/vocab-logits across the TP group.
# TP=4, PP=1, CP=1 => DP=2. TP stays within the single-node NVLink domain.
MEGATRON_TP=4
MEGATRON_PP=1
MEGATRON_CP=1
MEGATRON_EP=1
MEGATRON_ETP=null

# optimizer offload -- OFF by default (with colocate_all the inference engine is
# offloaded during training, so the full 80GB is available for the optimizer).
# Flip to true if you hit OOM in the optimizer step / grad sync.
OPTIMIZER_OFFLOAD=false
OPTIMIZER_OFFLOAD_FRACTION=1.0

# TIS parameters
TIS_IMP_RATIO_CAP=2.0
TIS_TYPE=token

# Qwen3.5 flags
REMOVE_MICROBATCH_PADDING=false # sample packing is not yet supported for GDN layers in megatron - see: https://github.com/NVIDIA/Megatron-LM/pull/2644
ENGINE_INIT_KWARGS='{"gdn_prefill_backend": "triton"}' # see https://github.com/vllm-project/vllm/issues/36921#issuecomment-4109702738
DISTRIBUTED_EXECUTOR_BACKEND="mp"
export _SKYRL_USE_NEW_INFERENCE=0
export VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS=1800

uv run --isolated --extra megatron -m examples.train.algorithms.dapo.main_dapo \
data.train_data="['$TRAIN_FILE']" \
data.val_data="['$TEST_FILE']" \
trainer.algorithm.advantage_estimator="grpo" \
trainer.algorithm.policy_loss_type="dual_clip" \
trainer.algorithm.overlong_buffer_len=$OVERLONG_BUFFER_LEN \
trainer.algorithm.overlong_buffer_penalty_factor=$OVERLONG_BUFFER_PENALTY_FACTOR \
trainer.algorithm.loss_reduction=$LOSS_REDUCTION \
generator.inference_engine.enforce_eager=$ENFORCE_EAGER \
generator.apply_overlong_filtering=$APPLY_OVERLONG_FILTERING \
generator.sampling_params.temperature=$TEMPERATURE \
generator.sampling_params.top_p=$TOP_P \
generator.eval_sampling_params.top_p=$EVAL_TOP_P \
generator.eval_sampling_params.temperature=$TEMPERATURE \
generator.eval_sampling_params.max_generate_length=$MAX_RESPONSE_LENGTH \
trainer.algorithm.use_kl_loss=$USE_KL_LOSS \
trainer.algorithm.clip_ratio_c=$CLIP_RATIO_C \
trainer.policy.model.path="$MODEL_NAME" \
trainer.placement.colocate_all=true \
trainer.strategy=megatron \
generator.inference_engine.distributed_executor_backend="$DISTRIBUTED_EXECUTOR_BACKEND" \
trainer.placement.policy_num_nodes=$NUM_NODES \
trainer.placement.policy_num_gpus_per_node=$NUM_GPUS_PER_NODE \
generator.inference_engine.engine_init_kwargs="$ENGINE_INIT_KWARGS" \
generator.inference_engine.num_engines=$NUM_INFERENCE_ENGINES \
generator.inference_engine.tensor_parallel_size=$INFERENCE_ENGINE_TENSOR_PARALLEL_SIZE \
trainer.policy.megatron_config.tensor_model_parallel_size=$MEGATRON_TP \
trainer.policy.megatron_config.pipeline_model_parallel_size=$MEGATRON_PP \
trainer.policy.megatron_config.context_parallel_size=$MEGATRON_CP \
trainer.policy.megatron_config.expert_model_parallel_size=$MEGATRON_EP \
trainer.policy.megatron_config.expert_tensor_parallel_size=$MEGATRON_ETP \
trainer.policy.megatron_config.optimizer_config_kwargs.overlap_cpu_optimizer_d2h_h2d=$OPTIMIZER_OFFLOAD \
trainer.policy.megatron_config.optimizer_config_kwargs.use_precision_aware_optimizer=$OPTIMIZER_OFFLOAD \
trainer.policy.megatron_config.optimizer_config_kwargs.optimizer_cpu_offload=$OPTIMIZER_OFFLOAD \
trainer.policy.megatron_config.optimizer_config_kwargs.optimizer_offload_fraction=$OPTIMIZER_OFFLOAD_FRACTION \
trainer.algorithm.off_policy_correction.tis_ratio_type=$TIS_TYPE \
trainer.algorithm.off_policy_correction.token_tis_ratio_clip_high=$TIS_IMP_RATIO_CAP \
trainer.remove_microbatch_padding=$REMOVE_MICROBATCH_PADDING \
trainer.epochs=10 \
trainer.algorithm.eps_clip_low=$CLIP_RATIO_LOW \
trainer.algorithm.eps_clip_high=$CLIP_RATIO_HIGH \
trainer.eval_batch_size=1024 \
trainer.eval_before_train=false \
trainer.eval_interval=5 \
trainer.update_epochs_per_batch=1 \
trainer.train_batch_size=$TRAIN_BATCH_SIZE \
trainer.policy_mini_batch_size=$MINI_BATCH_SIZE \
trainer.micro_forward_batch_size_per_gpu=1 \
trainer.micro_train_batch_size_per_gpu=1 \
trainer.ckpt_interval=50 \
trainer.max_prompt_length=$MAX_PROMPT_LENGTH \
generator.sampling_params.max_generate_length=$MAX_RESPONSE_LENGTH \
trainer.policy.optimizer_config.lr=$LR \
trainer.policy.optimizer_config.num_warmup_steps=5 \
trainer.policy.optimizer_config.weight_decay=0.1 \
trainer.policy.optimizer_config.max_grad_norm=1.0 \
generator.inference_engine.backend=vllm \
generator.inference_engine.run_engines_locally=true \
generator.inference_engine.weight_sync_backend=nccl \
generator.inference_engine.async_engine=true \
generator.batched=true \
environment.env_class=aime \
generator.n_samples_per_prompt=$N_SAMPLES_PER_PROMPT \
generator.eval_n_samples_per_prompt=$EVAL_N_SAMPLES_PER_PROMPT \
generator.inference_engine.gpu_memory_utilization=0.5 \
trainer.logger="$LOGGER" \
trainer.project_name="qwen3_5_dapo_2" \
trainer.run_name="nosd_dapo_qwen3_5_9b_megatron_tp${MEGATRON_TP}_pp${MEGATRON_PP}_cp${MEGATRON_CP}" \
trainer.export_path="/mnt/local_storage/exports/dapo_qwen3_5_9b_megatron_tp${MEGATRON_TP}_pp${MEGATRON_PP}_cp${MEGATRON_CP}" \
trainer.hf_save_interval=300 \
trainer.resume_mode=latest \
trainer.max_ckpts_to_keep=3 \
trainer.ckpt_path="/mnt/local_storage/ckpts/dapo_qwen3_5_9b_megatron_tp${MEGATRON_TP}_pp${MEGATRON_PP}_cp${MEGATRON_CP}" \
$@
Loading
Loading