feat(quant): skip max-calib forward when no activation needs data#1963
feat(quant): skip max-calib forward when no activation needs data#1963Edwardf0t1 wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughMax calibration gains configurable detection of activation-statistics requirements. When none are needed, the activation ChangesMax calibration forward control
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant max_calibrate
participant TensorQuantizer
participant forward_loop
participant WeightCalibration
max_calibrate->>TensorQuantizer: Inspect enabled activation quantizers
TensorQuantizer-->>max_calibrate: Report whether activation data is needed
alt Activation data is needed
max_calibrate->>forward_loop: Run calibration forward pass
else No activation data is needed
max_calibrate->>WeightCalibration: Skip forward pass
end
max_calibrate->>WeightCalibration: Calibrate weight tensors
🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1963 +/- ##
==========================================
- Coverage 76.39% 69.40% -6.99%
==========================================
Files 519 519
Lines 58192 58206 +14
==========================================
- Hits 44453 40397 -4056
- Misses 13739 17809 +4070
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:
|
When all enabled activation quantizers use a constant amax (constant_amax / use_constant_amax) or dynamic quantization, max calibration's forward pass collects no data-driven statistics and is pure overhead. Add _needs_activation_forward_for_max_calib() and gate the forward_loop in max_calibrate() behind a new opt-in flag skip_forward_without_activation_calib. Weight quantizers are still calibrated on the weight tensors directly via weight_only_quantize(), so results are unchanged; only the wasted forward is avoided (e.g. the nvfp4_experts_only_input_scale1 recipe). The flag defaults to False in max_calibrate() so the advanced algorithms that call it directly and always need activations (MSE, local Hessian, SmoothQuant, SVDQuant, GPTQ) are unaffected; it is enabled via MaxCalibConfig.skip_forward_without_activation_calib (default True) so only the top-level max path opts in. Also simplify a default-arg lambda in core_utils.sync_moe_expert_amax so mypy can infer its type (surfaced by the max_calibrate signature change); the forward_loop is invoked synchronously so closure capture is safe. Stacked on #1947 (depends on the constant_amax attribute). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Zhiyu Cheng <zhiyuc@nvidia.com>
be9b904 to
977b74c
Compare
|
What does this PR do?
Type of change: new feature (performance)
Addresses @realAsma's review comment on #1947: when all enabled input/KV activation quantizers use a constant amax, max calibration still runs the full
forward_loop, which is wasted — the constant/dynamic quantizers collect no data-driven statistics.This adds
_needs_activation_forward_for_max_calib(model)and gates theforward_loopinmax_calibrate():use_constant_amax, orconstant_amax. Weight quantizers are still calibrated on the weight tensors directly viaweight_only_quantize(), so results are unchanged; only the wasted forward is avoided.Safety / scoping. The gate is behind an opt-in flag
max_calibrate(..., skip_forward_without_activation_calib=False).max_calibratehas many internal callers — the advanced algorithms that always need activations (MSE, local Hessian, SmoothQuant, SVDQuant, GPTQ) call it directly and keep the defaultFalse, so they are unaffected. Only the top-levelmaxpath opts in, viaMaxCalibConfig.skip_forward_without_activation_calib(defaultTrue).Also simplifies a default-arg lambda in
core_utils.sync_moe_expert_amax(lambda m, w=weight: m(w)→lambda m: m(weight)) so mypy can infer its type — surfaced by themax_calibratesignature change; theforward_loopis invoked synchronously so closure capture is safe.Usage
Automatic for the top-level
maxpath — no user action needed. For thenvfp4_experts_only_input_scale1-kv_fp8_castrecipe (all expert inputs + KV pinned to constant amax), calibration now performs weight-only calibration and skips the model forward:To force the old behavior: set
skip_forward_without_activation_calib: falseon the max algorithm config.Testing
New CPU unit tests in
tests/unit/torch/quantization/test_calib.py:test_max_calib_skips_forward_when_all_activations_constant— forward not called; weight quantizer still gets_amax; constant input amax preserved.test_max_calib_runs_forward_when_activation_needs_data— a normal input quantizer still triggers the forward.test_max_calib_default_does_not_skip_forward— direct callers (default flag) keep running the forward.test_needs_activation_forward_ignores_disabled_and_weight_quantizers.test_max_calib_config_enables_skip_by_default.pytest tests/unit/torch/quantization/test_calib.py→ 17 passed;test_quantize_cpu.py+test_tensor_quantizer_cpu.py→ 79 passed.pre-commiton all changed files passes (ruff, mypy, bandit, …).Before your PR is "Ready for review"
CONTRIBUTING.md: N/AAdditional Information
Follow-up to #1947 (now merged) per reviewer request. Closes the optimization discussion at #1947 (comment).
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation