-
Notifications
You must be signed in to change notification settings - Fork 604
[OMNIML-5899] Add IQ post-training quantization recipes #2449
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
f3fca65
b9dfae3
d658c5f
57b7f88
a2849c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| # IQ1_S weight quantizer using the built-in fixed-scale codebook search. | ||
|
|
||
| # modelopt-schema: modelopt.torch.quantization.config.QuantizerAttributeConfig | ||
| num_bits: iq1_s | ||
| # Storage cost: 50 packed bytes * 8 / 256 weights. Keep in sync with IQ1_S_BLOCK_BYTES. | ||
| effective_bits: 1.5625 | ||
| block_sizes: | ||
| -1: 256 | ||
| backend: ggml | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| # IQ2_XS weight quantizer using the built-in fixed-scale codebook search. | ||
|
|
||
| # modelopt-schema: modelopt.torch.quantization.config.QuantizerAttributeConfig | ||
| num_bits: iq2_xs | ||
| # Storage cost: 74 packed bytes * 8 / 256 weights. Keep in sync with IQ2_XS_BLOCK_BYTES. | ||
| effective_bits: 2.3125 | ||
| block_sizes: | ||
| -1: 256 | ||
| backend: ggml |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| # QuantizeConfig preset for IQ1_S weight-only quantization. | ||
|
|
||
| # modelopt-schema: modelopt.torch.quantization.config.QuantizeConfig | ||
| imports: | ||
| base_disable_all: configs/ptq/units/base_disable_all | ||
| default_disabled_quantizers: configs/ptq/units/default_disabled_quantizers | ||
| iq1_s: configs/numerics/iq1_s | ||
|
|
||
| algorithm: | ||
| quant_cfg: | ||
| - $import: base_disable_all | ||
| - quantizer_name: '*weight_quantizer' | ||
| cfg: | ||
| $import: iq1_s | ||
| - quantizer_name: '*input_quantizer' | ||
| enable: false | ||
| - $import: default_disabled_quantizers |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| # QuantizeConfig preset for IQ2_XS weight-only quantization. | ||
|
|
||
| # modelopt-schema: modelopt.torch.quantization.config.QuantizeConfig | ||
| imports: | ||
| base_disable_all: configs/ptq/units/base_disable_all | ||
| default_disabled_quantizers: configs/ptq/units/default_disabled_quantizers | ||
| iq2_xs: configs/numerics/iq2_xs | ||
|
|
||
| algorithm: | ||
| quant_cfg: | ||
| - $import: base_disable_all | ||
| - quantizer_name: '*weight_quantizer' | ||
| cfg: | ||
| $import: iq2_xs | ||
| - quantizer_name: '*input_quantizer' | ||
| enable: false | ||
| - $import: default_disabled_quantizers |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
Comment on lines
+1
to
+2
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [SUGGESTION] All six new YAML files carry only the two-line SPDX header, while every other recipe YAML in the tree ( This won't be caught by CI: |
||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| # IQ1_S weight-only PTQ. | ||
|
|
||
| imports: | ||
| preset: configs/ptq/presets/model/iq1_s | ||
|
|
||
| metadata: | ||
| recipe_type: ptq | ||
| description: >- | ||
| Applies uniform GGML-compatible IQ1_S weight-only quantization to eligible linear layers. | ||
| This is not a mixed per-tensor precision preset. No calibration data is required. | ||
| quantize: | ||
| $import: preset | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| # IQ2_XS weight-only PTQ. | ||
|
|
||
| imports: | ||
| preset: configs/ptq/presets/model/iq2_xs | ||
|
|
||
| metadata: | ||
| recipe_type: ptq | ||
| description: >- | ||
| Applies uniform GGML-compatible IQ2_XS weight-only quantization to eligible linear layers. | ||
| This is not a mixed per-tensor precision preset. No calibration data is required. | ||
| quantize: | ||
| $import: preset |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -28,7 +28,7 @@ supported combinations. | |||||||||||||||||
| ### The shipped recipes | ||||||||||||||||||
|
|
||||||||||||||||||
| <details> | ||||||||||||||||||
| <summary>All 26 <code>general/ptq/</code> recipes (click to expand)</summary> | ||||||||||||||||||
| <summary>All 28 <code>general/ptq/</code> recipes (click to expand)</summary> | ||||||||||||||||||
|
|
||||||||||||||||||
| | Recipe | Model body | KV cache | Calibration | | ||||||||||||||||||
| |--------|-----------|----------|-------------| | ||||||||||||||||||
|
|
@@ -58,6 +58,8 @@ supported combinations. | |||||||||||||||||
| | `int4_blockwise_weight_only` | INT4 W4A16, block 128, weights only | none | max | | ||||||||||||||||||
| | `nvfp4_mlp_weight_only` | NVFP4 W4A16 (block 32), MLP + MoE weights only | none | max | | ||||||||||||||||||
| | `mxfp4_mlp_weight_only` | MXFP4 W4A16, MLP + MoE weights only | none | none (no calibration) | | ||||||||||||||||||
| | `iq1_s` | IQ1_S W1A16, all linears | none | GGML IQ auto search (no calibration) | | ||||||||||||||||||
| | `iq2_xs` | IQ2_XS W2A16, all linears | none | GGML IQ auto search (no calibration) | | ||||||||||||||||||
|
Comment on lines
+61
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [SUGGESTION] IQ1_S is 1.5625 bpw and IQ2_XS is 2.3125 bpw (the Suggestion: put the effective bpw in the cell so the column stays comparable:
Suggested change
Comment on lines
+61
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [SUGGESTION] The Calibration column advertises a step that does not exist. Both recipes set Why it matters: this column is what users scan to decide whether they need to supply a calibration dataset and to budget calibration time. A non-empty entry here reads as "something runs at quantize time", which will send people looking for a
Suggested change
|
||||||||||||||||||
|
|
||||||||||||||||||
| </details> | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
@@ -136,6 +138,10 @@ activations and tensor-core math are what deliver the throughput. | |||||||||||||||||
| - **`mxfp4_mlp_weight_only`** — MXFP4 weights on MLP/MoE layers only, BF16 | ||||||||||||||||||
| activations. Needs no calibration forward pass; the QAT starting point for the | ||||||||||||||||||
| GPT-OSS family (see `examples/gpt-oss`). | ||||||||||||||||||
| - **`iq1_s` / `iq2_xs`** — GGML-compatible IQ1_S or IQ2_XS weights on all linear | ||||||||||||||||||
| layers, with BF16 activations. No calibration data is required. Quantized weights must have a | ||||||||||||||||||
| final dimension divisible by 256. These recipes configure simulated weight quantization only; | ||||||||||||||||||
| packed checkpoint export is added separately. | ||||||||||||||||||
|
Comment on lines
+141
to
+144
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [SUGGESTION] Two small precision gaps in this bullet, both worth closing because the 256 constraint is the main foot-gun for these two recipes.
Suggestion — reword along these lines, and consider a shape precheck at quantize time in a follow-up: - **`iq1_s` / `iq2_xs`** — GGML-compatible IQ1_S (1.5625 bpw) or IQ2_XS (2.3125 bpw)
weights on eligible linear layers, with BF16 activations. No calibration data is
required. Every quantized weight must have a final dimension divisible by 256;
because these recipes run no calibration forward pass, a non-conforming layer is
only rejected at the first model forward, not during `mtq.quantize`. These recipes
configure simulated weight quantization only; packed checkpoint export is added
separately.
Comment on lines
+143
to
+144
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [SUGGESTION] "packed checkpoint export is added separately" will be stale the moment this merges. The PR description pins the merge order as #2448 → #2446 → #2447 (Export IQ checkpoints from HF and Megatron) → #2449. Since export lands before this PR, the sentence describes a gap that no longer exists at the time a user reads it. Phrasing that points forward to unmerged work is fine on a stacked branch but does not survive the merge — and unlike the recipe count, no test catches this drift, so it will sit in Why it matters: users reading "simulated weight quantization only" will reasonably conclude they cannot get a deployable IQ checkpoint out of these recipes and will stop there, even though Suggest either dropping the clause, or replacing it with a pointer to the export path — e.g.: - **`iq1_s` / `iq2_xs`** — GGML-compatible IQ1_S or IQ2_XS weights on all linear
layers eligible after `default_disabled_quantizers`, with BF16 activations. No
calibration data is required. Quantized weights must have a final dimension
divisible by 256.
Comment on lines
+141
to
+144
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Use a generic heading for all weight-only formats. The added recipes are 🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| --- | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[SUGGESTION]
block_sizeshere is purely declarative — nothing in the IQ path reads it.iq1_s_fake_quantdispatches straight toquantize_iq1_s, which reshapes with the module-levelIQ1_S_BLOCK_SIZE = GGML_BLOCK_SIZE(modelopt/torch/quantization/ggml/common.py:22) and never consultsquantizer.block_sizes. Likewise,TensorQuantizer._fake_quantizeshort-circuits into the backend entrypoint before theblock_sizes/amax branches are reached (modelopt/torch/quantization/nn/modules/tensor_quantizer.py:891-896).Why it matters:
effective_bitsright above got a "Keep in sync withIQ1_S_BLOCK_BYTES" note, but the256here has no such marker even though it is the same class of duplicated constant. Someone editing this to128(a reasonable-looking knob) would see no behavior change at all — the kernel would still pack 256-value super-blocks — which is a confusing silent no-op rather than an error.Suggestion: add a one-line comment mirroring the
effective_bitsnote, e.g.# Declarative only: the GGML kernel hardcodes GGML_BLOCK_SIZE. Keep in sync.Same applies toiq2_xs.yaml:10-11.