Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8cbe175
fix ppo value offload bugs
lilei199908 Apr 30, 2026
3ebce5a
fix ppo value offload bugs
lilei199908 Apr 30, 2026
250acde
fix ppo value offload bugs
lilei199908 Apr 30, 2026
9f9c187
fix ppo value offload bugs
lilei199908 Apr 30, 2026
9bd6779
fix ppo value offload bugs
lilei199908 Apr 30, 2026
dcc0aa0
fix ppo value offload bugs
lilei199908 Apr 30, 2026
fbf33bd
fix ppo value offload bugs
lilei199908 Apr 30, 2026
631e078
fix ppo value offload bugs
lilei199908 Apr 30, 2026
8970ecb
fix ppo value offload bugs
lilei199908 Apr 30, 2026
edc4363
fix ppo value offload bugs
lilei199908 Apr 30, 2026
d8636c5
fix ppo value offload bugs
lilei199908 Apr 30, 2026
88a3d24
fix ppo value offload bugs
lilei199908 Apr 30, 2026
811081f
fix ppo value offload bugs
lilei199908 Apr 30, 2026
5123f56
fix ppo value offload bugs
lilei199908 Apr 30, 2026
d89cf24
fix ppo value offload bugs
lilei199908 Apr 30, 2026
81afe96
fix ppo value offload bugs
lilei199908 Apr 30, 2026
3884802
fix ppo value offload bugs
lilei199908 Apr 30, 2026
59077df
fix ppo value offload bugs
lilei199908 Apr 30, 2026
179871f
fix ppo value offload bugs
lilei199908 Apr 30, 2026
6cda7ec
fix ppo value offload bugs
lilei199908 Apr 30, 2026
99165e9
fix ppo value offload bugs
lilei199908 Apr 30, 2026
bafee9a
fix ppo value offload bugs
lilei199908 Apr 30, 2026
eba4b86
fix ppo value offload bugs
lilei199908 Apr 30, 2026
a7a79bc
fix ppo value offload bugs
lilei199908 Apr 30, 2026
122a5d3
fix ppo value offload bugs
lilei199908 Apr 30, 2026
9f8e12f
fix ppo value offload bugs
lilei199908 Apr 30, 2026
6c1daae
fix ppo value offload bugs
lilei199908 Apr 30, 2026
136da90
fix ppo value offload bugs
lilei199908 Apr 30, 2026
1c6eff7
fix ppo value offload bugs
lilei199908 Apr 30, 2026
44c40ef
remove copilot instructions from git
lilei199908 May 6, 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
2 changes: 1 addition & 1 deletion .github/workflows/pr-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ jobs:
strategy:
fail-fast: false
matrix:
info: [{"num_gpus": 8, "test_file": "test_quick_start_glm4_9B.py"}, {"num_gpus": 8, "test_file": "test_glm4.7_30B_A3B_pd_mooncake.py"}, {"num_gpus": 8, "test_file": "test_qwen3_30B_A3B.py", "use_deepep": "1", "use_fp8_rollout": "1"}, {"num_gpus": 8, "test_file": "test_qwen3.6_35B_A3B_pd_mooncake.py", "use_deepep": "1"}, {"enable_eval": "0", "num_gpus": 8, "test_file": "test_qwen3_30B_A3B_r3.py", "use_deepep": "1", "use_fp8_rollout": "1"}, {"enable_eval": "0", "num_gpus": 8, "test_file": "test_qwen3_30B_A3B_r3.py"}, {"num_gpus": 8, "test_file": "test_qwen3_4B_ppo.py"}, {"num_gpus": 8, "test_file": "test_qwen3_4B_ppo_train_critic_only.py"}, {"num_gpus": 8, "test_file": "test_moonlight_16B_A3B.py"}, {"enable_eval": "0", "num_gpus": 8, "test_file": "test_moonlight_16B_A3B_r3.py"}, {"num_gpus": 8, "test_file": "test_mimo_7B_mtp_only_grad.py"}, {"num_gpus": 8, "test_file": "test_qwen2.5_0.5B_debug_rollout_then_train.py"}, {"num_gpus": 8, "test_file": "test_qwen2.5_0.5B_opd_sglang.py"}]
info: [{"num_gpus": 8, "test_file": "test_quick_start_glm4_9B.py"}, {"num_gpus": 8, "test_file": "test_glm4.7_30B_A3B_pd_mooncake.py"}, {"num_gpus": 8, "test_file": "test_qwen3_30B_A3B.py", "use_deepep": "1", "use_fp8_rollout": "1"}, {"num_gpus": 8, "test_file": "test_qwen3.6_35B_A3B_pd_mooncake.py", "use_deepep": "1"}, {"enable_eval": "0", "num_gpus": 8, "test_file": "test_qwen3_30B_A3B_r3.py", "use_deepep": "1", "use_fp8_rollout": "1"}, {"enable_eval": "0", "num_gpus": 8, "test_file": "test_qwen3_30B_A3B_r3.py"}, {"num_gpus": 8, "test_file": "test_qwen3_4B_ppo.py"}, {"num_gpus": 8, "test_file": "test_qwen3_4B_ppo_disaggregate.py"}, {"num_gpus": 8, "test_file": "test_qwen3_4B_ppo_train_critic_only.py"}, {"num_gpus": 8, "test_file": "test_moonlight_16B_A3B.py"}, {"enable_eval": "0", "num_gpus": 8, "test_file": "test_moonlight_16B_A3B_r3.py"}, {"num_gpus": 8, "test_file": "test_mimo_7B_mtp_only_grad.py"}, {"num_gpus": 8, "test_file": "test_qwen2.5_0.5B_debug_rollout_then_train.py"}, {"num_gpus": 8, "test_file": "test_qwen2.5_0.5B_opd_sglang.py"}]
defaults:
run:
working-directory: ${{ github.workspace }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/pr-test.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
{'test_file': 'test_qwen3_30B_A3B_r3.py', 'num_gpus': 8, 'use_deepep': '1', 'use_fp8_rollout': '1', 'enable_eval': '0'},
{'test_file': 'test_qwen3_30B_A3B_r3.py', 'num_gpus': 8, 'enable_eval': '0'},
{'test_file': 'test_qwen3_4B_ppo.py', 'num_gpus': 8},
{'test_file': 'test_qwen3_4B_ppo_disaggregate.py', 'num_gpus': 8},
{'test_file': 'test_qwen3_4B_ppo_train_critic_only.py', 'num_gpus': 8},
{'test_file': 'test_moonlight_16B_A3B.py', 'num_gpus': 8},
{'test_file': 'test_moonlight_16B_A3B_r3.py', 'num_gpus': 8, 'enable_eval': '0'},
Expand Down
21 changes: 17 additions & 4 deletions slime/backends/megatron_utils/actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def init(
logger.info(f"Set torch_memory_saver.memory_margin_bytes to {x}")
torch_memory_saver.memory_margin_bytes = x

(self.model, self.optimizer, self.opt_param_scheduler, loaded_rollout_id) = initialize_model_and_optimizer(
self.model, self.optimizer, self.opt_param_scheduler, loaded_rollout_id = initialize_model_and_optimizer(
args, role
)

Expand Down Expand Up @@ -159,6 +159,13 @@ def sleep(self) -> None:

clear_memory(clear_host_memory=True)
print_memory("before offload model")
if (
self.role == "actor"
and self.args.use_critic
and not self.args.colocate
and hasattr(self.weight_updater, "disconnect_rollout_engines")
):
self.weight_updater.disconnect_rollout_engines()
destroy_process_groups()

torch_memory_saver.pause()
Expand Down Expand Up @@ -549,10 +556,14 @@ def update_weights(self) -> None:
self.rollout_manager.get_updatable_engines_and_lock.remote()
)

if self.args.offload_train:
reconnect_rollout_engines = self.args.offload_train and self.args.use_critic and not self.args.colocate

if reconnect_rollout_engines:
self.wake_up()
elif self.args.offload_train:
reload_process_groups()

if num_new_engines > 0:
if num_new_engines > 0 or reconnect_rollout_engines:
self.weight_updater.connect_rollout_engines(
rollout_engines,
rollout_engine_lock,
Expand Down Expand Up @@ -587,7 +598,9 @@ def update_weights(self) -> None:
else:
self.weights_backuper.backup("old_actor")

if self.args.offload_train:
if reconnect_rollout_engines:
self.sleep()
elif self.args.offload_train:
destroy_process_groups()

def load_other_checkpoint(self, model_tag: str, path: str) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ def connect_rollout_engines(
engine_gpu_counts=engine_gpu_counts,
)

def disconnect_rollout_engines(self) -> None:
if not getattr(self, "_is_pp_src_rank", False) or self._model_update_groups is None:
return
disconnect_rollout_engines_from_distributed(
self.args, self._group_name, self._model_update_groups, self.rollout_engines
)
self._model_update_groups = None

@torch.no_grad()
def update_weights(self) -> None:
"""
Expand Down
3 changes: 0 additions & 3 deletions slime/backends/sglang_utils/sglang_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ def get_base_gpu_id(args, rank):
else:
num_actor_gpus = 0 if args.debug_rollout_only else args.actor_num_gpus_per_node * args.actor_num_nodes
start_index = (num_actor_gpus + rank * num_gpus) % args.num_gpus_per_node
if args.use_critic:
num_critic_gpus = args.critic_num_gpus_per_node * args.critic_num_nodes
start_index = (num_actor_gpus + num_critic_gpus + rank * num_gpus) % args.num_gpus_per_node
return start_index


Expand Down
3 changes: 3 additions & 0 deletions slime/utils/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -1762,6 +1762,9 @@ def slime_validate_args(args):
if args.offload_rollout is None:
args.offload_rollout = False

if args.use_critic:
args.offload_train = True

if args.eval_function_path is None:
args.eval_function_path = args.rollout_function_path

Expand Down
150 changes: 150 additions & 0 deletions tests/test_qwen3_4B_ppo_disaggregate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import os
import tempfile

import slime.utils.external_utils.command_utils as U


ENABLE_EVAL = bool(int(os.environ.get("SLIME_TEST_ENABLE_EVAL", "1")))
TIGHT_HOST_MEMORY = bool(int(os.environ.get("SLIME_TEST_TIGHT_HOST_MEMORY", "1")))

MODEL_NAME = "Qwen3-4B"
MODEL_TYPE = "qwen3-4B"
NUM_GPUS = 8


def prepare():
U.exec_command("mkdir -p /root/models /root/datasets")
U.exec_command("hf download Qwen/Qwen3-4B --local-dir /root/models/Qwen3-4B")
U.hf_download_dataset("zhuzilin/dapo-math-17k")
U.hf_download_dataset("zhuzilin/aime-2024")

U.convert_checkpoint(model_name=MODEL_NAME, megatron_model_type=MODEL_TYPE, num_gpus_per_node=NUM_GPUS)


def execute():
megatron_config = tempfile.NamedTemporaryFile("w", suffix=".yaml", delete=False)
megatron_config.write(
"""
megatron:
- name: default
role: critic
overrides:
lr: 1e-5
- name: default
role: actor
overrides:
lr: 1e-6
"""
)
megatron_config.close()

ckpt_args = f"--hf-checkpoint /root/models/{MODEL_NAME}/ " f"--ref-load /root/{MODEL_NAME}_torch_dist "

rollout_args = (
"--prompt-data /root/datasets/dapo-math-17k/dapo-math-17k.jsonl "
"--input-key prompt "
"--label-key label "
"--apply-chat-template "
"--rollout-shuffle "
"--rm-type deepscaler "
"--num-rollout 3 "
"--rollout-batch-size 8 "
"--n-samples-per-prompt 4 "
"--rollout-max-response-len 8192 "
"--rollout-temperature 0.8 "
"--global-batch-size 32 "
"--balance-data "
)

eval_args = (
f"{'--eval-interval 20 ' if ENABLE_EVAL else ''}"
"--eval-prompt-data aime24 /root/datasets/aime-2024/aime-2024.jsonl "
"--n-samples-per-eval-prompt 1 "
"--eval-max-response-len 16384 "
"--eval-top-k 1 "
)

perf_args = (
"--tensor-model-parallel-size 2 "
"--sequence-parallel "
"--pipeline-model-parallel-size 1 "
"--context-parallel-size 2 "
"--recompute-granularity full "
"--recompute-method uniform "
"--recompute-num-layers 1 "
"--use-dynamic-batch-size "
f"--max-tokens-per-gpu {2048 if TIGHT_HOST_MEMORY else 16384} "
)

ppo_args = (
"--advantage-estimator ppo "
f"{'' if TIGHT_HOST_MEMORY else '--use-kl-loss '}"
"--kl-loss-coef 0.00 "
"--kl-loss-type k1 "
"--kl-coef 0.00 "
"--entropy-coef 0.00 "
"--eps-clip 4e-4 "
"--num-critic-only-steps 1 "
"--normalize-advantages "
)

optimizer_args = (
"--optimizer adam "
"--lr 1e-6 "
"--lr-decay-style constant "
"--weight-decay 0.1 "
"--adam-beta1 0.9 "
"--adam-beta2 0.98 "
)

sglang_args = (
"--rollout-num-gpus-per-engine 2 "
"--rollout-num-gpus 4 "
"--sglang-mem-fraction-static 0.8 "
"--sglang-cuda-graph-max-bs 32 "
"--sglang-max-running-requests 512 "
"--sglang-enable-metrics "
)

ci_args = "--ci-test "

misc_args = (
# default dropout in megatron is 0.1
"--attention-dropout 0.0 "
"--hidden-dropout 0.0 "
# should be good for model performance
"--accumulate-allreduce-grads-in-fp32 "
"--attention-softmax-in-fp32 "
# need to comment this when using model with MLA
"--attention-backend flash "
"--actor-num-nodes 1 "
"--actor-num-gpus-per-node 4 "
)

train_args = (
f"--megatron-config-path {megatron_config.name} "
f"{ckpt_args} "
f"{rollout_args} "
f"{optimizer_args} "
f"{ppo_args} "
f"{U.get_default_wandb_args(__file__)} "
f"{perf_args} "
f"{eval_args} "
f"{sglang_args} "
f"{ci_args} "
f"{misc_args} "
)

U.execute_train(
train_args=train_args,
num_gpus_per_node=NUM_GPUS,
megatron_model_type=MODEL_TYPE,
)


if __name__ == "__main__":
# TODO also use typer
prepare()
for proxy_var in ("http_proxy", "https_proxy", "HTTP_PROXY", "HTTPS_PROXY"):
os.environ.pop(proxy_var, None)
execute()
2 changes: 1 addition & 1 deletion train.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def save(rollout_id):
offload_train(actor_trains_this_step)
if args.offload_rollout:
ray.get(rollout_manager.onload_weights.remote())
actor_model.update_weights()
actor_model.update_weights()

if args.offload_rollout:
ray.get(rollout_manager.onload_kv.remote())
Expand Down
Loading