Repository navigation
fix(weight-update): sync and check drafts only when the trainer trains MTP - #4043
Conversation
…s MTP Only the Megatron HF weight iterator narrowed weight_update_selector to "target"; FSDP and torchtitan kept "all". Every update session from them restored and postprocessed a speculative draft that received no weights, and p2p connect raised NotImplementedError for EAGLE3, STANDALONE, separate draft checkpoints and multi-layer EAGLE drafts. The weight checker snapshotted and reset_tensors every runner with a hard-coded "all" at engine init, so a draft the sync leaves out stayed scrambled for the run unless --check-weight-update-selector target was passed by hand. weight_update_selector(args) now derives the selector from --enable-mtp-training, the MTP training intent the parent commit gates Megatron's MTP layers on and rejects on FSDP and torchtitan, for every backend and for each trainer's args. --check-weight-update-selector defaults to it, and the server cell snapshots and resets exactly the runners the checker compares. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
Brings in 045f983 (MTP layers built only under --enable-mtp-training), which the selector rule here already follows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@claude review always |
…tor-from-mtp-intent Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
I reviewed this PR and didn't find any bugs. Because it reworks weight-sync selector logic shared across backends (Megatron/FSDP/torchtitan), the updater's connect/update_weights paths, and the server cell's equality-check gating, a human look would still be worthwhile.
What was reviewed: the new weight_update_selector(args) in session.py and its call sites in updater.py; the removal of the per-iterator weight_update_selector attribute from hf_weight_iterator/init.py and megatron_utils/hf_weight_iterator.py; server_cell.py's snapshot/reset_tensors now using args.check_weight_update_selector instead of a hardcoded "all"; and the arguments.py defaulting logic (including import-cycle risk, which is absent). Also checked the multi-policy case where a trainer's own enable_mtp_training could diverge from the base args used to default check_weight_update_selector — this is the PR's documented, accepted behavior (checker uses base args, each trainer's sync uses its own args), not a new bug.
Extended reasoning...
The diff relocates the weight-sync "which engine runners to cover" decision from a per-backend class attribute into a single session-level function keyed on --enable-mtp-training, threads it through WeightUpdater.connect/update_weights, and makes server_cell's post-update equality check (snapshot/reset_tensors) follow the same selector instead of a hardcoded "all"; arguments.py now defaults --check-weight-update-selector to that function's result. No injection/auth/data-exposure surface is touched; the risk is purely behavioral correctness of weight sync and the equality checker across Megatron/FSDP/torchtitan and multi-policy setups. Decided to defer rather than approve because this is cross-backend, behavior-changing infra code with a documented but non-trivial multi-policy edge case, even though no bug was found.
…tor-from-mtp-intent Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…trained MTP layers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/rerun-test tests/e2e/megatron/test_qwen3_5_35B_A3B/test_spec_nor3_fp8_sgl_tp4_meg_tp2cp2.py |
|
/rerun-test tests/e2e/megatron/test_glm47_flash/test_spec_mtptrain_nor3_bf16_sgl_tp2_meg_tp1pp2_p2p.py |
|
/rerun-test tests/e2e/megatron/test_glm47_flash/test_nospec_nor3_fp8_deepep_sgl_dpattn1x4_meg_tp2cp1_bshd.py |
|
/rerun-test tests/e2e/megatron/test_mimo_7B_mtp_only_grad.py |
|
/rerun-test tests/e2e/megatron/test_qwen3_5_35b_a3b_lora_ci.py |
|
✅ |
|
✅ |
|
✅ |
|
✅ |
|
✅ |
Summary
Weight syncs and the weight checker covered speculative drafts the trainer never updates
Symptom & Reproduction
"all", so sglang restores, then postprocesses, a draft that gets no weights; p2pconnectraisesNotImplementedErrorfor EAGLE3, STANDALONE, separate draft checkpoints or multi-layer EAGLE (p2p: update speculative drafts from trained MTP weights #3985 (comment)).--check-weight-update-equalthe server cell scrambles every runner at engine init, so a draft the sync leaves out stays random for the run.test_the_checker_snapshots_and_resets_only_the_runners_it_comparesfails on the parent commit, where snapshot plusreset_tensorsget"all"while the checker compares"target"; it passes here.Root Cause
MegatronHfWeightIteratorBase.__init__alone narrowedweight_update_selectorto"target".FSDPHfWeightIteratorandTitanHfWeightIteratorkept the base default"all".ServerCell._tick_when_initializinghard-codedselector="all"for snapshot andreset_tensors.--check-weight-update-selectordefaulted to"all", independent of the sync.Fix
One rule,
weight_update_selector(args)inweight_update/session.py:"target"when a speculative algorithm is set without--enable-mtp-training, else"all". The parent PR gates Megatron's MTP layers on that intent and rejects it on FSDP and torchtitan, so the rule holds on every backend without a per-backend hook.connectandbegin_weight_update.--check-weight-update-selectordefaults to it at argument validation; the server cell snapshots and resets that selector, so reset covers exactly what compare checks.Megatron syncs are unchanged, since the parent PR builds MTP layers exactly when
--enable-mtp-trainingis set, including trainer overrides and Bridge LoRA. An explicit--check-weight-update-selectoroverrides the default.Verification
tests/fast/backends,tests/fast/utils/test_arguments.py,tests/fast/ray/rollout,tests/fast/launch_scripts,tests/fast/examples,tests/fast/e2e,tests/fast/test_train*.py: 4440 passed on theradixark/miles:devimage (CPU); the 10 failures (a secret-argument check against the image's newer sglang router flags, a missingtapmodule, 8helm templatecases missing themiles-commonchart dependency) fail identically onmain.test_weight_update_selector.py(moved frommegatron_utils/, samestage-b-cpuregistration) covers trained, frozen and external drafts.test_megatron_config.pytrainer-override tests andtest_an_explicit_zero_becomes_megatrons_no_mtp_valuecover the parent PR's rule that keeps this selector true per trainer.Review Focus
server_cell.py: snapshot andreset_tensorsnow follow--check-weight-update-selector; a runner outside it is neither scrambled nor checked.Generated with Claude Code