Skip to content

Make freeze_mtp an explicit override of the automatic MTP freeze - #2784

Merged
yueshen2016 merged 2 commits into
mainfrom
yueshen/freeze-mtp-tristate
Oct 31, 2026
Merged

yueshen2016 merged 2 commits into
mainfrom
yueshen/freeze-mtp-tristate

Conversation

@yueshen2016

@yueshen2016 yueshen2016 commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Type of change: Bug fix (follow-up to #2770)

Addresses @danielkorzekwa's review of #2770:

  • freeze_mtp=False could not keep the MTP head training (comment). The MTP head was still frozen whenever the LM loss was skipped and the student was quantized except for its MTP head, because the setting was OR-ed with that automatic rule. freeze_mtp is now three-state:

    freeze_mtp MTP-specific parameters and MTP loss
    None (default, omitted) The existing automatic rule: frozen and disabled only when kd_loss_alpha == 1.0 and the student is quantized except for its MTP head
    True Frozen and disabled
    False Trained

    On the CLI, examples/megatron_bridge/distill.py takes --freeze_mtp / --no-freeze_mtp (argparse.BooleanOptionalAction), and omitting both keeps the automatic rule. YAML configs pass through DistillationConfig unchanged.

  • The helper's name hid what it checks (comment). _mtp_excluded_from_quantization is renamed _has_quantized_backbone_with_unquantized_mtp: it is true when the model has MTP submodules and enabled quantizers, none of them inside MTP. It now inspects only the student, so a teacher's MTP head can no longer make it true. The reason for the automatic freeze moved next to where the setting is resolved.

freeze_mtp=False changes meaning: it used to mean "automatic", and now it keeps the MTP head training. Omitting the field keeps the previous behavior. freeze_mtp was added in #2770 and is not in a release yet.

"Freeze" covers the MTP-specific parameters only. The embedding and output layer that the MTP head shares with the backbone keep training through the main loss.

Usage

python examples/megatron_bridge/distill.py ... --freeze_mtp     # freeze the MTP head
python examples/megatron_bridge/distill.py ... --no-freeze_mtp  # train it
python examples/megatron_bridge/distill.py ...                  # automatic (previous default)

Testing

tests/gpu_megatron/torch/distill/plugins/test_distill_megatron.py passes on GB300 (28 passed):

  • test_skip_lm_loss_with_mtp covers omitted, True and False. It includes the regression case: a quantized backbone with an unquantized MTP head, kd_loss_alpha=1.0 and freeze_mtp=False, where the MTP loss stays active and the MTP parameters stay trainable.
  • test_freeze_mtp_training_step, which replaces test_freeze_mtp_with_quantized_mtp, runs forward, KD backward and an AdamW step across quantized and unquantized MTP heads and all three settings. It checks that the MTP head gets gradients exactly when it is not frozen, that a frozen head is bit-identical after the step, and that the backbone always trains. The attached TensorQuantizers are quantization-state fixtures; the test does not quantize numerics.
  • test_has_quantized_backbone_with_unquantized_mtp covers the renamed helper.

Before your PR is "Ready for review"

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Megatron distillation now supports --freeze_mtp and --no-freeze_mtp to explicitly freeze or keep the student’s MTP parameters trainable. Freezing also disables MTP loss.
    • If neither option is specified, MTP is frozen only when LM loss is skipped and the student’s backbone is quantized while its MTP components are not.
  • Documentation
    • Updated the changelog and command-line help to describe the options and default behavior.

freeze_mtp=False could not keep the MTP head training: it was frozen anyway
when the LM loss was skipped and only the backbone was quantized. freeze_mtp
is now None by default, which keeps that automatic rule; True and False are
authoritative (--freeze_mtp / --no-freeze_mtp). The rule's helper is renamed
to _has_quantized_backbone_with_unquantized_mtp, after what it checks, and
inspects only the student.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Yue <yueshen@nvidia.com>
@yueshen2016
yueshen2016 requested review from a team as code owners October 13, 2026 20:45
@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between aa1ff9f and c2328aa.

Files selected for processing: 4
  • CHANGELOG.rst
  • examples/megatron_bridge/distill.py
  • modelopt/torch/distill/plugins/megatron.py
  • tests/gpu_megatron/torch/distill/plugins/test_distill_megatron.py
Files skipped from review as they are similar to previous changes: 1
  • CHANGELOG.rst

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 10 remain after this review.

Walkthrough

Megatron distillation now supports explicit MTP freeze and unfreeze settings. When the setting is unset, the code determines whether to skip MTP loss from the LM-loss and quantization state.

Changes: Megatron MTP Freeze Control

Layer / File(s) Summary
Tri-state freeze option
CHANGELOG.rst, examples/megatron_bridge/distill.py, modelopt/torch/distill/plugins/megatron.py
The CLI supports --freeze_mtp and --no-freeze_mtp. DistillationConfig.freeze_mtp now defaults to None; the changelog and option help describe the explicit choices and conditional default.
MTP freeze resolution and tests
modelopt/torch/distill/plugins/megatron.py, tests/gpu_megatron/torch/distill/plugins/test_distill_megatron.py
The quantization check requires a quantized backbone and an unquantized MTP module. Explicit freeze values control MTP loss skipping; when unset, skipping depends on LM-loss skipping and that quantization check. Tests cover loss behavior, parameter gradients, and parameter updates.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant Config as DistillationConfig
  participant Predicate as Quantization predicate
  participant Loss as MTP loss logic
  Config->>Loss: Provide freeze_mtp and kd_loss_alpha
  Loss->>Predicate: Check backbone and MTP quantization
  Predicate-->>Loss: Return quantization state
  Loss->>Loss: Resolve whether to skip MTP loss
Loading

Possibly related PRs

Suggested reviewers: kevalmorabia97

Merge Risk: Minimal · up to c2328

The three-state freeze control is ready to merge with normal checks.

Pre-merge checks: Passed 6
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title states the main change: freeze_mtp becomes an explicit override of the automatic MTP freeze. The raw summary confirms this. freeze_mtp changes from a bool defaulting to False into a three-st…
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Security Anti-Patterns Passed PASS. The pull request changes only examples/megatron_bridge/distill.py and modelopt/torch/distill/plugins/megatron.py among the covered production Python files. The added code contains no `torch.…
Full details: Title check

Explanation

The title states the main change: freeze_mtp becomes an explicit override of the automatic MTP freeze. The raw summary confirms this. freeze_mtp changes from a bool defaulting to False into a three-state setting (None, True, False). When unset, the automatic rule still applies. Explicit True and False override it. The CHANGELOG, the CLI flags (--freeze_mtp and --no-freeze_mtp), the DistillationConfig field, the helper rename to _has_quantized_backbone_with_unquantized_mtp, and the tests all match this title.

Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 5 functions across 3 files. (1 skipped: 1 unsupported.)

Full details: Security Anti-Patterns

Explanation

PASS. The pull request changes only examples/megatron_bridge/distill.py and modelopt/torch/distill/plugins/megatron.py among the covered production Python files. The added code contains no torch.load(..., weights_only=False), numpy.load(..., allow_pickle=True), hardcoded trust_remote_code=True, eval()/exec(), or # nosec. It also adds no changes to pyproject.toml or requirements.txt. The changed test file is excluded by SECURITY.md.

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@cjluo-nv cjluo-nv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bot review (gpt-6.1-sol) — DM the bot to share feedback.

LGTM: the tri-state override is correct and well covered; the justified edits to existing tests require human sign-off.

Needs action:

  • Confirm the existing-test updates in tests/gpu_megatron/torch/distill/plugins/test_distill_megatron.py: default-behavior cases now use None, and the renamed training-step test preserves prior coverage while adding override cases.

No action needed:

  • Automatic detection now excludes the teacher, and the CLI passes all three states through unchanged.
  • Tests were inspected, not executed; the PR reports its GB300 run is pending.

@yueshen2016
yueshen2016 requested review from a team and AAnoosheh October 13, 2026 20:48
@yueshen2016

Copy link
Copy Markdown
Contributor Author

/claude review

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-10-31 18:59 UTC

@codecov

codecov Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 76.16%. Comparing base (2bb126f) to head (c2328aa).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
modelopt/torch/distill/plugins/megatron.py 88.88% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2784      +/-   ##
==========================================
- Coverage   80.29%   76.16%   -4.14%     
==========================================
  Files         675      675              
  Lines       77278    85297    +8019     
==========================================
+ Hits        62054    64964    +2910     
- Misses      15224    20333    +5109     
Flag Coverage Δ
examples-diffusers 19.84% <0.00%> (-0.01%) ⬇️
examples-gpt-oss 13.46% <0.00%> (+<0.01%) ⬆️
examples-hf_ptq 23.47% <0.00%> (-0.04%) ⬇️
examples-llm_distill 13.53% <0.00%> (-0.01%) ⬇️
examples-llm_eval 17.25% <0.00%> (-0.01%) ⬇️
examples-llm_qat 17.38% <0.00%> (-0.04%) ⬇️
examples-llm_sparsity 16.72% <0.00%> (-0.01%) ⬇️
examples-megatron_bridge 26.36% <88.88%> (-0.26%) ⬇️
examples-specdec_bench 13.23% <0.00%> (+<0.01%) ⬆️
examples-speculative_decoding 17.49% <0.00%> (-0.07%) ⬇️
examples-torch_onnx 21.10% <0.00%> (-0.03%) ⬇️
examples-torch_trt 15.20% <0.00%> (-0.01%) ⬇️
examples-vllm_serve 17.47% <0.00%> (-0.01%) ⬇️
gpu 54.91% <55.55%> (-4.62%) ⬇️
regression 14.98% <0.00%> (-0.01%) ⬇️
unit 62.60% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@danielkorzekwa danielkorzekwa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good work, much clearer now with freeze-mtp=None default state

…istate

Signed-off-by: Yue <yueshen@nvidia.com>

# Conflicts:
#	CHANGELOG.rst
@yueshen2016
yueshen2016 enabled auto-merge (squash) October 31, 2026 18:42
@yueshen2016
yueshen2016 merged commit c92993c into main Oct 31, 2026
49 of 50 checks passed
@yueshen2016
yueshen2016 deleted the yueshen/freeze-mtp-tristate branch October 31, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants