Skip weight quantizers with no stored weight in fold_weight - #2132
Skip weight quantizers with no stored weight in fold_weight#2132babyplutokurt wants to merge 1 commit into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthrough
ChangesWeight folding safety
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Warning
CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.
Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/unit/torch/quantization/test_tensor_quant_cpu.py`:
- Around line 344-350: Update the test around qlinear.fold_weight() to snapshot
qlinear.weight_quantizer.amax before folding, then assert afterward that the
calibration value is unchanged. Keep the existing enabled-state assertion and
use the captured value to verify the skipped quantizer retains its data.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 88c010b9-7b55-4229-a416-950f55267b79
📒 Files selected for processing (3)
CHANGELOG.rstmodelopt/torch/quantization/nn/modules/quant_module.pytests/unit/torch/quantization/test_tensor_quant_cpu.py
cb1cb5d to
44e0d34
Compare
cjluo-nv
left a comment
There was a problem hiding this comment.
Bot review (gpt-5.6-sol) — DM the bot to share feedback.
Straightforward, well-scoped fix. fold_weight now skips missing/non-tensor stored weights before dereferencing them, preserving the forward-time quantizer needed by Megatron tied-output layers. The regression test reproduces the weight=None shape and verifies the quantizer and calibration state remain intact, and the changelog entry is under the current development release.
|
/ok to test 44e0d34 |
|
/claude review |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2132 +/- ##
==========================================
- Coverage 78.73% 78.14% -0.60%
==========================================
Files 522 522
Lines 60342 60344 +2
==========================================
- Hits 47508 47153 -355
- Misses 12834 13191 +357
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| if not isinstance(weight, torch.Tensor): | ||
| # e.g. Megatron tied-embedding output_layer: weight is None and | ||
| # borrowed at forward time, so there is nothing stored to fold. | ||
| continue |
There was a problem hiding this comment.
[SUGGESTION] The skip is the right call, but it introduces the first documented exception to an invariant that two other places in the tree assert on: after fold_weight, no weight quantizer is enabled.
examples/vllm_serve/fakequant_worker.py:146-150raisesRuntimeError("... is still enabled after fold_weight — double-quantization would corrupt activations.")for any still-enabled weight-quantizer state key.modelopt/torch/export/plugins/vllm_fakequant_hf.py:128-140(_check_all_weight_quantizers_disabled) raises before writing metadata.
I traced this and believe it is currently unreachable: both are HF/vLLM-side paths, and vLLM's ParallelLMHead ties by sharing the embedding tensor (allocated weight), not by weight = None, so neither will see a skipped pair. Megatron's output_layer never flows through those checkers. So this is not a blocking issue.
Still, worth a line in the fold_weight docstring exception you added — something like "such quantizers stay enabled, so callers that assert all weight quantizers are disabled after folding must special-case them" — so the next person hitting one of those RuntimeErrors can find the reason here instead of re-deriving it. A pointer in the inline comment to _check_all_weight_quantizers_disabled would work equally well.
Claude review summaryScope: full review (trigger comment carried no scoping instructions). The PR touches 3 files — Findings: CRITICAL: 0 · IMPORTANT: 0 · SUGGESTION: 1 What I verified
I did not execute the test suite in this environment (the sandbox declined the Suggestion (non-blocking)One inline comment on Separately, and outside this diff: Risk assessmentLow. Nine added lines, purely additive, guarding a dereference that previously raised unconditionally. The behavior change is confined to modules whose stored weight is not a tensor — a set that was 100% crashing before — so every path that worked prior to this PR is bit-identical after it. Well-scoped, correctly narrow, and matched by a regression test that fails without the fix. |
On Megatron-Core models with tied word embeddings, the output_layer is
built with skip_weight_param_allocation: it stores weight = None and
borrows the embedding weight at forward time, while ModelOpt still
attaches a weight_quantizer to it. fold_weight matched the pair on the
*_weight_quantizer attribute name and fake_quant alone, then dereferenced
weight.data, crashing with:
AttributeError: 'NoneType' object has no attribute 'data'
Skip pairs whose weight attribute is not a tensor and leave their
quantizer untouched: there is nothing stored to fold, and the shared
weight keeps being quantized at forward time through the still-enabled
quantizer. The embedding module folds its own stored weight as before.
HF models are unaffected; they express tying as a shared tensor rather
than None, which is why the crash only surfaced on Megatron.
Fixes NVIDIA#2131
Signed-off-by: babyplutokurt <attaboykurt.yang@gmail.com>
44e0d34 to
8606f41
Compare
|
Added the docstring suggestion from claude. Also rebased on latest main already and re-push |
1 similar comment
|
Added the docstring suggestion from claude. Also rebased on latest main already and re-push |
Skip weight quantizers with no stored weight in
fold_weightWhat does this PR do?
Type of change: Bug fix
Fixes #2131.
On Megatron-Core models with tied word embeddings
(
share_embeddings_and_output_weights=True), theoutput_layeris built withskip_weight_param_allocation: it storesweight = Noneand borrows the embeddingweight at forward time, while ModelOpt still attaches a
weight_quantizerto it.QuantModule.fold_weightmatches the pair on the*_weight_quantizerattribute nameand
fake_quantalone, then dereferencesweight.data, somtq.fold_weightcrashes:This PR skips pairs whose weight attribute is not a tensor and leaves their quantizer
untouched: there is nothing stored to fold, and the shared weight keeps being
quantized at forward time through the still-enabled quantizer (the embedding module
folds its own stored weight as before). HF models are unaffected — they express tying
as a shared tensor rather than
None, which is why the crash only surfaced onMegatron.
Usage
Testing
test_fold_weight_skips_none_weightintests/unit/torch/quantization/test_tensor_quant_cpu.pybuilds the tied-layer shape(a converted
QuantLinearwithweight = None) — it reproduces the exactAttributeErroratquant_module.py:145without the fix and passes with it,asserting the skipped quantizer stays enabled with its
_amaxintact.Before your PR is "Ready for review"
CONTRIBUTING.md: N/A/claude review)Additional Information
Related issue: #2131. Downstream workaround that this fix would let us drop:
NVIDIA-NeMo/RL#3441 (
nemo_rl/modelopt/models/policy/workers/weight_folding.py).Summary by CodeRabbit
Bug Fixes
Tests