Skip to content

Autoquant and GPTQ in support in Megatron-Core [OMNIML-3151] - #1562

Merged
jenchen13 merged 55 commits into
mainfrom
jennifchen/mcore_autoquant_gptq
Jul 2, 2026
Merged

Autoquant and GPTQ in support in Megatron-Core [OMNIML-3151]#1562
jenchen13 merged 55 commits into
mainfrom
jennifchen/mcore_autoquant_gptq

Conversation

@jenchen13

@jenchen13 jenchen13 commented May 28, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Type of change: New Feature

Autoquant and GPTQ in support in Megatron-Core

  • Add EP support to AutoQuantize
  • Register MCore support in AutoQuantize
  • Add decoder output_layer (lm head) to layerwise hook so that GPTQ can register all decoder layers & lm head
  • Split dataloader helper function out of megatron calibration utils so that AutoQuantize in Megatron-LM can reuse the same dataloader

Usage

See NVIDIA/Megatron-LM#4821 for Autoquant usage in Megatron

# For GPTQ pick a recipe that uses gptq algorithm and run mtq.quantize
# e.g. general/ptq/nvfp4_default-kv_none-gptq

Testing

Tested AutoQuant on Nemotron Nano and Ultra.
Tested GPTQ on Nano 3.
Added unit tests for both AutoQuant and GPTQ

Before your PR is "Ready for review"

Make sure you read and follow Contributor guidelines and your commits are signed (git commit -s -S).

Make sure you read and follow the Security Best Practices (e.g. avoiding hardcoded trust_remote_code=True, torch.load(..., weights_only=False), pickle, etc.).

  • Is this change backward compatible?: ✅ / ❌ / N/A
  • If you copied code from any other sources or added a new PIP dependency, did you follow guidance in CONTRIBUTING.md: ✅ / ❌ / N/A
  • Did you write any new necessary tests?: ✅ / ❌ / N/A
  • Did you update Changelog?: ✅ / ❌ / N/A
  • Did you get Claude approval on this PR?: ✅ / ❌ / N/A

Additional Information

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added lazy Megatron-Core AutoQuant integration with Megatron-specific quantization hooks and better decoder-layer discovery for layerwise calibration.
    • Improved AutoQuantize for expert-parallel (EP) models, including consistent per-layer recipe selection across DP/TP/EP.
    • Extended quant-layer grouping for NemotronH MCore fused “local_experts” linear layers.
  • Bug Fixes

    • Prevented division-by-zero when calibration inputs are empty during Hessian updates.
  • Tests

    • Added/extended unit and GPU coverage for EP AutoQuant, decoder-layer calibration discovery behavior, and zero-token Hessian no-op.

jenchen13 added 14 commits May 22, 2026 10:52
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
…izers

The branch previously short-circuited mse_calibrate's Step 2 with an early
`continue` that skipped any quantizer whose config didn't match the NVFP4
static pattern (num_bits=(2,1) + scale_bits=(4,3)). This broke main's
contract that:
  - fp8_scale_sweep=True + registered backend  -> backend factory called
  - any enabled quantizer                       -> calibrator replaced with
                                                  MseCalibrator (default)

Tests TestRegisterFP8SweepCalibrator::{
  test_mse_calibrate_dispatches_to_registered_factory,
  test_unregistered_backend_uses_default_mse_calibrator,
} regressed on this branch because they use INT8 quantizers which were
silently skipped.

Restructure so:
  1. NVFP4-static promotion runs only when applicable (gated on
     module.is_nvfp4_static)
  2. Backend factory dispatch runs for any backend with fp8_scale_sweep=True
  3. NVFP4MSECalibrator runs only for NVFP4-static + fp8_scale_sweep
  4. MseCalibrator default fallback runs for everything else (INT8, FP8,
     non-sweep NVFP4)

Also drops the misleading 'skipped non-NVFP4' warning (it implied we skip,
but we now always set a calibrator).

Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jenny Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
@jenchen13
jenchen13 requested a review from a team as a code owner May 28, 2026 21:30
@jenchen13
jenchen13 requested review from ajrasane, realAsma and sugunav14 and removed request for a team May 28, 2026 21:30
@jenchen13 jenchen13 changed the title Autoquant and GPTQ in support in Megatron-Core Autoquant and GPTQ in support in Megatron-Core [OMNIML-3151] May 28, 2026
@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

AutoQuantize now synchronizes score, cost, and final format selection across expert model parallel groups, derives weight budgets from candidate statistics, and adds Megatron-specific auto-quant and calibration hooks. update_hessian() now no-ops on zero-token input.

Changes

AutoQuantize Expert Model Parallelism and Megatron Support

Layer / File(s) Summary
EP synchronization and grouping rules
modelopt/torch/quantization/algorithms.py
get_score(), get_cost(), and final best_format selection now reduce across expert_model_parallel_group in addition to tensor and data parallel groups. A new regex groups NemotronH MCore local_experts fused linear layers.
Weight budget from candidate stats
modelopt/torch/quantization/algorithms.py, tests/unit/torch/quantization/test_autoquant.py
_get_total_weight_size_from_candidate_stats(candidate_stats) sums the no-quant candidate costs. run_search() uses it when candidate statistics are available and otherwise falls back to the prior weight-size computation. The unit test asserts max_weight_size comes from candidate costs.
Megatron auto-quant and calibration hooks
modelopt/torch/quantization/plugins/megatron.py, modelopt/torch/quantization/model_quant.py, CHANGELOG.rst
auto_quantize() now lazily imports and invokes Megatron auto-quant support registration when available. The plugin registers custom gradient-searcher callbacks, exposes get_mcore_layerwise_calibration_layers(), and registers it with LayerActivationCollector. The changelog adds the Megatron-Core support note.
Zero-token Hessian guard
modelopt/torch/quantization/utils/calib_utils.py, tests/gpu/torch/quantization/test_gptq.py
update_hessian() returns early when the flattened input has zero tokens, leaving hessian and n_samples unchanged. The GPU GPTQ test asserts the no-op behavior.
Megatron EP and calibration tests
tests/gpu_megatron/torch/quantization/plugins/test_megatron.py
Adds imports for get_batch and Megatron calibration helpers, runs MoE auto-quantization under expert parallelism, and verifies decoder-layer calibration discovery does not mutate model.decoder.layers.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested reviewers

  • ChenhanYu
  • realAsma
  • shengliangxu
🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: adding AutoQuant and GPTQ support for Megatron-Core.
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 No forbidden torch.load/allow_pickle/trust_remote_code/eval-exec/nosec/dependency anti-patterns appear in the PR’s changed code; the new Megatron import is lazy and optional.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jennifchen/mcore_autoquant_gptq

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-07-02 02:12 UTC

@coderabbitai coderabbitai Bot 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.

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.

👉 Steps to fix this

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
modelopt/torch/quantization/utils/calib_utils.py (1)

60-61: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the docstring note to reflect the new behavior.

The note states that "input must be non-empty" and "a zero-sized input causes division by zero", but the new guard clause at lines 66-67 now handles batch_size == 0 gracefully. Update the docstring to reflect that empty inputs are now supported.

📝 Proposed docstring update
-    Note: input must be non-empty (batch_size > 0); a zero-sized input causes division by zero.
+    Note: Empty inputs (batch_size == 0) are handled gracefully and return unchanged hessian/n_samples.
+          This can occur in MoE models when some experts receive no tokens.
🤖 Prompt for 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.

In `@modelopt/torch/quantization/utils/calib_utils.py` around lines 60 - 61,
Update the docstring Note to reflect that empty inputs are now supported:
replace "input must be non-empty (batch_size > 0); a zero-sized input causes
division by zero" with a sentence stating that the function now handles
batch_size == 0 via the guard clause (which returns early when batch_size == 0)
and will not raise a division-by-zero error; mention that non-empty inputs are
still processed normally. Target the docstring for the function that contains
the guard checking batch_size == 0 (the docstring immediately above that guard)
and keep the wording brief and clear.
🧹 Nitpick comments (2)
modelopt/torch/quantization/plugins/megatron.py (1)

810-837: ⚡ Quick win

Document and export the newly added public APIs.

register_megatron_autoquant_support and get_mcore_decoder_layers are public (non-underscore) but only one has a docstring, and neither is reflected in __all__.

As per coding guidelines, "Document public APIs with docstrings, including examples when useful" and "Define the public API with __all__ at the top of each module".

🤖 Prompt for 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.

In `@modelopt/torch/quantization/plugins/megatron.py` around lines 810 - 837, Add
a docstring to the newly public function get_mcore_decoder_layers describing
purpose, parameters, return type and an example, and ensure
register_megatron_autoquant_support also has appropriate public-docstring
coverage if needed; then export both symbols by adding
"register_megatron_autoquant_support" and "get_mcore_decoder_layers" to the
module's __all__ list at the top of the file so they are part of the public API
surface.
modelopt/torch/quantization/model_quant.py (1)

510-515: ⚡ Quick win

Don’t silently swallow plugin import failures.

Line 514 currently suppresses all ImportErrors, which can hide real regressions and make Megatron auto-quant support silently disappear. Emit a warning (or gate the exception type more narrowly) so failures are diagnosable.

Proposed change
     try:
         from .plugins.megatron import register_megatron_autoquant_support

         register_megatron_autoquant_support()
-    except ImportError:
-        pass
+    except ImportError as exc:
+        warnings.warn(
+            f"Skipping Megatron auto-quant support registration due to import error: {exc}",
+            RuntimeWarning,
+            stacklevel=2,
+        )
🤖 Prompt for 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.

In `@modelopt/torch/quantization/model_quant.py` around lines 510 - 515, The
current try/except around importing and calling
register_megatron_autoquant_support silently swallows ImportError; update the
block to either catch a more specific exception (e.g., ModuleNotFoundError for
the plugin import) or log a warning when import/call fails so failures are
visible; specifically wrap the import and call to
register_megatron_autoquant_support() and on failure call the module's logger or
warnings.warn/processLogger.warning with a clear message including the exception
text and that Megatron auto-quant support is disabled.
🤖 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 `@modelopt/torch/quantization/plugins/megatron.py`:
- Around line 830-831: get_mcore_decoder_layers is mutating model.decoder.layers
by appending model.output_layer which causes duplicated entries on repeated
calls; instead return a new nn.ModuleList (e.g., copy model.decoder.layers into
a fresh list/ModuleList) and append the output_layer to that new collection or
check for existence before appending so augmentation is idempotent; update
get_mcore_decoder_layers (and calls from
LayerActivationCollector.get_decoder_layers /
LayerActivationCollector._patch_all_layers) to use the non-mutating copy so
_cleanup_layers need not undo permanent changes.

---

Outside diff comments:
In `@modelopt/torch/quantization/utils/calib_utils.py`:
- Around line 60-61: Update the docstring Note to reflect that empty inputs are
now supported: replace "input must be non-empty (batch_size > 0); a zero-sized
input causes division by zero" with a sentence stating that the function now
handles batch_size == 0 via the guard clause (which returns early when
batch_size == 0) and will not raise a division-by-zero error; mention that
non-empty inputs are still processed normally. Target the docstring for the
function that contains the guard checking batch_size == 0 (the docstring
immediately above that guard) and keep the wording brief and clear.

---

Nitpick comments:
In `@modelopt/torch/quantization/model_quant.py`:
- Around line 510-515: The current try/except around importing and calling
register_megatron_autoquant_support silently swallows ImportError; update the
block to either catch a more specific exception (e.g., ModuleNotFoundError for
the plugin import) or log a warning when import/call fails so failures are
visible; specifically wrap the import and call to
register_megatron_autoquant_support() and on failure call the module's logger or
warnings.warn/processLogger.warning with a clear message including the exception
text and that Megatron auto-quant support is disabled.

In `@modelopt/torch/quantization/plugins/megatron.py`:
- Around line 810-837: Add a docstring to the newly public function
get_mcore_decoder_layers describing purpose, parameters, return type and an
example, and ensure register_megatron_autoquant_support also has appropriate
public-docstring coverage if needed; then export both symbols by adding
"register_megatron_autoquant_support" and "get_mcore_decoder_layers" to the
module's __all__ list at the top of the file so they are part of the public API
surface.
🪄 Autofix (Beta)

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: 30c2390a-c99c-4b41-8c0c-0be68734dc77

📥 Commits

Reviewing files that changed from the base of the PR and between d63bf70 and 2ba29fd.

📒 Files selected for processing (7)
  • modelopt/torch/quantization/algorithms.py
  • modelopt/torch/quantization/model_quant.py
  • modelopt/torch/quantization/nn/modules/tensor_quantizer.py
  • modelopt/torch/quantization/plugins/megatron.py
  • modelopt/torch/quantization/utils/calib_utils.py
  • tests/gpu_megatron/torch/quantization/plugins/test_megatron.py
  • tests/unit/torch/quantization/test_autoquant.py

Comment thread modelopt/torch/quantization/plugins/megatron.py Outdated
@codecov

codecov Bot commented May 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.11111% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.84%. Comparing base (a05850b) to head (054e353).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
modelopt/torch/quantization/plugins/megatron.py 84.00% 4 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #1562       +/-   ##
===========================================
+ Coverage   61.17%   76.84%   +15.67%     
===========================================
  Files         515      515               
  Lines       57207    57684      +477     
===========================================
+ Hits        34994    44328     +9334     
+ Misses      22213    13356     -8857     
Flag Coverage Δ
examples 42.91% <62.22%> (+10.08%) ⬆️
gpu 57.86% <84.44%> (+37.33%) ⬆️
regression 14.82% <8.88%> (+0.05%) ⬆️
unit 54.89% <35.55%> (-0.02%) ⬇️

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.



# GPTQ layerwise calibration support
def get_mcore_decoder_layers(model: torch.nn.Module) -> torch.nn.ModuleList | None:

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.

since we are returning both decoder layers and output layer could we rename this to better reflect that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i can rename to get_mcore_model_layers, but it's still being called by LayerActivationCollector.register_decoder_layer_support

Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>

@sugunav14 sugunav14 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.

Reviewed the GPTQ support! LGTM

Comment thread tests/gpu_megatron/torch/quantization/plugins/test_megatron.py Outdated
jenchen13 added 3 commits July 1, 2026 08:47
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
@jenchen13
jenchen13 force-pushed the jennifchen/mcore_autoquant_gptq branch from a196424 to c976a23 Compare July 1, 2026 16:33
Comment thread tests/gpu_megatron/torch/quantization/plugins/test_megatron.py Outdated
Comment thread tests/gpu_megatron/torch/quantization/plugins/test_megatron.py
Comment thread tests/gpu_megatron/torch/quantization/plugins/test_megatron.py
Comment thread tests/gpu_megatron/torch/quantization/plugins/test_megatron.py Outdated
Comment thread tests/gpu_megatron/torch/quantization/plugins/test_megatron.py
Comment thread tests/gpu_megatron/torch/quantization/plugins/test_megatron.py
Comment thread tests/gpu_megatron/torch/quantization/plugins/test_megatron.py Outdated
Comment thread tests/gpu_megatron/conftest.py Outdated
jenchen13 added 2 commits July 1, 2026 10:44
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
@jenchen13
jenchen13 force-pushed the jennifchen/mcore_autoquant_gptq branch from 77b8ed3 to 8c307de Compare July 1, 2026 17:47
jenchen13 added 2 commits July 1, 2026 11:00
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
@jenchen13
jenchen13 force-pushed the jennifchen/mcore_autoquant_gptq branch from d8b85bc to 2e5100c Compare July 1, 2026 18:15

@kevalmorabia97 kevalmorabia97 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.

@jenchen13

Copy link
Copy Markdown
Contributor Author

/ok to test 2e5100c

Comment thread modelopt/torch/quantization/algorithms.py Outdated
total_weight_size = self._cost_model.total_weight_size(
self.model.named_modules(), self._is_auto_quantize_module, self.config["cost"]
)
if self.candidate_stats:

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.

@jenchen13 why do we need the else branch here? self.candidate_stats is always set in before_search which gets called before run_search

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.

The else branch is never used.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

hmm I think i kept it for backward compatibility

Comment on lines +919 to +926
if self.candidate_stats:
total_weight_size = self._get_total_weight_size_from_candidate_stats(
self.candidate_stats
)
else:
total_weight_size = self._cost_model.total_weight_size(
self.model.named_modules(), self._is_auto_quantize_module, self.config["cost"]
)

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.

Suggested change
if self.candidate_stats:
total_weight_size = self._get_total_weight_size_from_candidate_stats(
self.candidate_stats
)
else:
total_weight_size = self._cost_model.total_weight_size(
self.model.named_modules(), self._is_auto_quantize_module, self.config["cost"]
)
total_weight_size = self._get_total_weight_size_from_candidate_stats(
self.candidate_stats
)

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.

Does this work?

@kevalmorabia97
kevalmorabia97 disabled auto-merge July 1, 2026 22:01
run_search's `else` branch recomputed the effective-bits denominator via
_cost_model.total_weight_size(live model), but candidate_stats is always
populated by before_search() (restored from checkpoint -> early return, or
built by initialize_candidate_stats), so the branch was dead. Replace it
with an assertion documenting the invariant and always derive the
denominator from candidate_stats -- the source the solver's per-layer costs
already come from, and which is DP/TP/EP-synced and merge-group aware
(unlike the live-model recompute).

Remove the now prod-dead AutoQuantizeCostModel.total_weight_size (its only
caller was that else) and rewrite its two unit tests to assert the exclusion
rule and MoE active-expert scaling directly against the production-used
primitives (module_cost_weight + _get_module_weight_numel).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
@jenchen13

Copy link
Copy Markdown
Contributor Author

/ok to test 054e353

Comment thread tests/unit/torch/quantization/test_autoquant.py
Comment thread modelopt/torch/quantization/_auto_quantize_cost.py
@jenchen13
jenchen13 merged commit 9038b71 into main Jul 2, 2026
58 checks passed
@jenchen13
jenchen13 deleted the jennifchen/mcore_autoquant_gptq branch July 2, 2026 02:12
talorabr pushed a commit that referenced this pull request Jul 7, 2026
### What does this PR do?

Type of change: New Feature

Autoquant and GPTQ in support in Megatron-Core

- Add EP support to AutoQuantize
- Register MCore support in AutoQuantize
- Add decoder `output_layer` (lm head) to layerwise hook so that GPTQ
can register all decoder layers & lm head
- Split dataloader helper function out of megatron calibration utils so
that AutoQuantize in Megatron-LM can reuse the same dataloader

### Usage
See NVIDIA/Megatron-LM#4821 for Autoquant usage
in Megatron
```python
# For GPTQ pick a recipe that uses gptq algorithm and run mtq.quantize
# e.g. general/ptq/nvfp4_default-kv_none-gptq
```

### Testing
Tested AutoQuant on Nemotron Nano and Ultra.
Tested GPTQ on Nano 3.
Added unit tests for both AutoQuant and GPTQ

### Before your PR is "*Ready for review*"

Make sure you read and follow [Contributor
guidelines](https://github.com/NVIDIA/Model-Optimizer/blob/main/CONTRIBUTING.md)
and your commits are signed (`git commit -s -S`).

Make sure you read and follow the [Security Best
Practices](https://github.com/NVIDIA/Model-Optimizer/blob/main/SECURITY.md#security-coding-practices-for-contributors)
(e.g. avoiding hardcoded `trust_remote_code=True`, `torch.load(...,
weights_only=False)`, `pickle`, etc.).

- Is this change backward compatible?: ✅ / ❌ / N/A <!--- If ❌, explain
why. -->
- If you copied code from any other sources or added a new PIP
dependency, did you follow guidance in `CONTRIBUTING.md`: ✅ / ❌ / N/A
<!--- Mandatory -->
- Did you write any new necessary tests?: ✅ / ❌ / N/A <!--- Mandatory
for new features or examples. -->
- Did you update
[Changelog](https://github.com/NVIDIA/Model-Optimizer/blob/main/CHANGELOG.rst)?:
✅ / ❌ / N/A <!--- Only for new features, API changes, critical bug fixes
or backward incompatible changes. -->
- Did you get Claude approval on this PR?: ✅ / ❌ / N/A <!--- Run
`/claude review`. NVIDIA org members can self-trigger for complex
changes; orthogonal to CodeRabbit. -->

### Additional Information
<!-- E.g. related issue. -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

* **New Features**
* Added lazy Megatron-Core AutoQuant integration with Megatron-specific
quantization hooks and better decoder-layer discovery for layerwise
calibration.
* Improved AutoQuantize for expert-parallel (EP) models, including
consistent per-layer recipe selection across DP/TP/EP.
* Extended quant-layer grouping for NemotronH MCore fused
“local_experts” linear layers.

* **Bug Fixes**
* Prevented division-by-zero when calibration inputs are empty during
Hessian updates.

* **Tests**
* Added/extended unit and GPU coverage for EP AutoQuant, decoder-layer
calibration discovery behavior, and zero-token Hessian no-op.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Jennifer Chen <jennifchen@nvidia.com>
Signed-off-by: Jenny Chen <jennifchen@nvidia.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: talora <talora@nvidia.com>
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.

6 participants