From 92f5e74207ad4c3edc703100333ae96bbc688e17 Mon Sep 17 00:00:00 2001 From: realAsma Date: Mon, 6 Jul 2026 19:55:03 +0000 Subject: [PATCH 01/19] Add LAQ (Learnable Amax Quantization) algorithm Fold in the FSDP2 amax dtype fix and LAQ pre-scale quantization control. Signed-off-by: realAsma --- .../nvfp4_laq_frozen-mse_init-fp8_kv.yml | 52 +++ .../nvfp4_laq_post-mse_init-fp8_kv.yml | 53 +++ .../nvfp4_laq_pre-mse_init-fp8_kv.yml | 53 +++ .../nvfp4_laq_pre_post-mse_init-fp8_kv.yml | 54 ++++ ...vfp4_laq_pre_post_tied-mse_init-fp8_kv.yml | 54 ++++ .../kernels/quantization/gemm/fp4_kernel.py | 93 +++++- modelopt/torch/quantization/config.py | 76 +++++ modelopt/torch/quantization/conversion.py | 12 +- modelopt/torch/quantization/mode.py | 14 + modelopt/torch/quantization/model_calib.py | 181 ++++++++++- .../nn/modules/tensor_quantizer.py | 226 ++++++++++++- .../plugins/transformers_trainer.py | 25 ++ modelopt/torch/quantization/tensor_quant.py | 58 ++++ tests/gpu/torch/quantization/test_fsdp2.py | 45 +++ tests/gpu/torch/quantization/test_laq_cuda.py | 202 ++++++++++++ tests/unit/recipe/test_laq_recipes.py | 125 ++++++++ tests/unit/torch/quantization/test_laq.py | 301 ++++++++++++++++++ 17 files changed, 1599 insertions(+), 25 deletions(-) create mode 100644 examples/llm_qat/configs/quantize/nvfp4_laq_frozen-mse_init-fp8_kv.yml create mode 100644 examples/llm_qat/configs/quantize/nvfp4_laq_post-mse_init-fp8_kv.yml create mode 100644 examples/llm_qat/configs/quantize/nvfp4_laq_pre-mse_init-fp8_kv.yml create mode 100644 examples/llm_qat/configs/quantize/nvfp4_laq_pre_post-mse_init-fp8_kv.yml create mode 100644 examples/llm_qat/configs/quantize/nvfp4_laq_pre_post_tied-mse_init-fp8_kv.yml create mode 100644 tests/gpu/torch/quantization/test_laq_cuda.py create mode 100644 tests/unit/recipe/test_laq_recipes.py create mode 100644 tests/unit/torch/quantization/test_laq.py diff --git a/examples/llm_qat/configs/quantize/nvfp4_laq_frozen-mse_init-fp8_kv.yml b/examples/llm_qat/configs/quantize/nvfp4_laq_frozen-mse_init-fp8_kv.yml new file mode 100644 index 00000000000..9a4406961f4 --- /dev/null +++ b/examples/llm_qat/configs/quantize/nvfp4_laq_frozen-mse_init-fp8_kv.yml @@ -0,0 +1,52 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 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. + +metadata: + recipe_type: ptq + description: NVFP4 LAQ frozen amax (static, both pre+post non-learnable), MSE init with FP8 scale sweep, FP8 KV cache. +quantize: + algorithm: + method: laq + learnable_amax: [] + tied_amax: false + scale_algorithm: + method: mse + fp8_scale_sweep: true + quant_cfg: + - quantizer_name: '*' + enable: false + - quantizer_name: '*weight_quantizer' + enable: true + cfg: + block_sizes: + -1: 16 + type: static + scale_bits: e4m3 + num_bits: e2m1 + - quantizer_name: '*input_quantizer' + enable: true + cfg: + block_sizes: + -1: 16 + type: dynamic + scale_bits: e4m3 + num_bits: e2m1 + - quantizer_name: '*[kv]_bmm_quantizer' + enable: true + cfg: + num_bits: e4m3 + axis: + - quantizer_name: '*lm_head*' + enable: false diff --git a/examples/llm_qat/configs/quantize/nvfp4_laq_post-mse_init-fp8_kv.yml b/examples/llm_qat/configs/quantize/nvfp4_laq_post-mse_init-fp8_kv.yml new file mode 100644 index 00000000000..34169be85e6 --- /dev/null +++ b/examples/llm_qat/configs/quantize/nvfp4_laq_post-mse_init-fp8_kv.yml @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 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. + +metadata: + recipe_type: ptq + description: NVFP4 LAQ post-only learnable amax (W4A16), MSE init with FP8 scale sweep, FP8 KV cache. +quantize: + algorithm: + method: laq + learnable_amax: + - post + tied_amax: false + scale_algorithm: + method: mse + fp8_scale_sweep: true + quant_cfg: + - quantizer_name: '*' + enable: false + - quantizer_name: '*weight_quantizer' + enable: true + cfg: + block_sizes: + -1: 16 + type: static + scale_bits: e4m3 + num_bits: e2m1 + - quantizer_name: '*input_quantizer' + enable: true + cfg: + block_sizes: + -1: 16 + type: dynamic + scale_bits: e4m3 + num_bits: e2m1 + - quantizer_name: '*[kv]_bmm_quantizer' + enable: true + cfg: + num_bits: e4m3 + axis: + - quantizer_name: '*lm_head*' + enable: false diff --git a/examples/llm_qat/configs/quantize/nvfp4_laq_pre-mse_init-fp8_kv.yml b/examples/llm_qat/configs/quantize/nvfp4_laq_pre-mse_init-fp8_kv.yml new file mode 100644 index 00000000000..6a8056f9795 --- /dev/null +++ b/examples/llm_qat/configs/quantize/nvfp4_laq_pre-mse_init-fp8_kv.yml @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 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. + +metadata: + recipe_type: ptq + description: NVFP4 LAQ pre-only learnable amax (W4A16), MSE init with FP8 scale sweep, FP8 KV cache. +quantize: + algorithm: + method: laq + learnable_amax: + - pre + tied_amax: false + scale_algorithm: + method: mse + fp8_scale_sweep: true + quant_cfg: + - quantizer_name: '*' + enable: false + - quantizer_name: '*weight_quantizer' + enable: true + cfg: + block_sizes: + -1: 16 + type: static + scale_bits: e4m3 + num_bits: e2m1 + - quantizer_name: '*input_quantizer' + enable: true + cfg: + block_sizes: + -1: 16 + type: dynamic + scale_bits: e4m3 + num_bits: e2m1 + - quantizer_name: '*[kv]_bmm_quantizer' + enable: true + cfg: + num_bits: e4m3 + axis: + - quantizer_name: '*lm_head*' + enable: false diff --git a/examples/llm_qat/configs/quantize/nvfp4_laq_pre_post-mse_init-fp8_kv.yml b/examples/llm_qat/configs/quantize/nvfp4_laq_pre_post-mse_init-fp8_kv.yml new file mode 100644 index 00000000000..7f2bee8d335 --- /dev/null +++ b/examples/llm_qat/configs/quantize/nvfp4_laq_pre_post-mse_init-fp8_kv.yml @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 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. + +metadata: + recipe_type: ptq + description: NVFP4 LAQ pre+post learnable amax (W4A16), MSE init with FP8 scale sweep, FP8 KV cache. +quantize: + algorithm: + method: laq + learnable_amax: + - pre + - post + tied_amax: false + scale_algorithm: + method: mse + fp8_scale_sweep: true + quant_cfg: + - quantizer_name: '*' + enable: false + - quantizer_name: '*weight_quantizer' + enable: true + cfg: + block_sizes: + -1: 16 + type: static + scale_bits: e4m3 + num_bits: e2m1 + - quantizer_name: '*input_quantizer' + enable: true + cfg: + block_sizes: + -1: 16 + type: dynamic + scale_bits: e4m3 + num_bits: e2m1 + - quantizer_name: '*[kv]_bmm_quantizer' + enable: true + cfg: + num_bits: e4m3 + axis: + - quantizer_name: '*lm_head*' + enable: false diff --git a/examples/llm_qat/configs/quantize/nvfp4_laq_pre_post_tied-mse_init-fp8_kv.yml b/examples/llm_qat/configs/quantize/nvfp4_laq_pre_post_tied-mse_init-fp8_kv.yml new file mode 100644 index 00000000000..01a2c1dac80 --- /dev/null +++ b/examples/llm_qat/configs/quantize/nvfp4_laq_pre_post_tied-mse_init-fp8_kv.yml @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 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. + +metadata: + recipe_type: ptq + description: NVFP4 LAQ pre+post tied learnable amax (W4A16), MSE init with FP8 scale sweep, FP8 KV cache. +quantize: + algorithm: + method: laq + learnable_amax: + - pre + - post + tied_amax: true + scale_algorithm: + method: mse + fp8_scale_sweep: true + quant_cfg: + - quantizer_name: '*' + enable: false + - quantizer_name: '*weight_quantizer' + enable: true + cfg: + block_sizes: + -1: 16 + type: static + scale_bits: e4m3 + num_bits: e2m1 + - quantizer_name: '*input_quantizer' + enable: true + cfg: + block_sizes: + -1: 16 + type: dynamic + scale_bits: e4m3 + num_bits: e2m1 + - quantizer_name: '*[kv]_bmm_quantizer' + enable: true + cfg: + num_bits: e4m3 + axis: + - quantizer_name: '*lm_head*' + enable: false diff --git a/modelopt/torch/kernels/quantization/gemm/fp4_kernel.py b/modelopt/torch/kernels/quantization/gemm/fp4_kernel.py index 2b655f4bbcb..6e4754741d0 100644 --- a/modelopt/torch/kernels/quantization/gemm/fp4_kernel.py +++ b/modelopt/torch/kernels/quantization/gemm/fp4_kernel.py @@ -28,7 +28,12 @@ from ..common.nvfp4_quant import nvfp4_scalar_quant -__all__ = ["compute_fp4_scales", "fp4_dequantize", "static_blockwise_fp4_fake_quant"] +__all__ = [ + "compute_fp4_scales", + "fp4_dequantize", + "static_blockwise_fp4_cast", + "static_blockwise_fp4_fake_quant", +] _TORCH_TO_TL_DTYPE = { @@ -309,3 +314,89 @@ def static_blockwise_fp4_fake_quant( ) return y_flat.view(original_shape) + + +@triton.jit +def static_blockwise_fp4_cast_kernel( + x_ptr, # [NUM_ELEMENTS] flattened pre-scaled input + y_ptr, # [NUM_ELEMENTS] flattened output + NUM_ELEMENTS, + TILE_SIZE: tl.constexpr, + OUT_DTYPE: tl.constexpr, +): + """Round pre-scaled values to nearest FP4 representable value (no scale).""" + pid = tl.program_id(axis=0) + offset = pid * TILE_SIZE + tl.arange(0, TILE_SIZE) + mask = offset < NUM_ELEMENTS + + x = tl.load(x_ptr + offset, mask=mask).to(tl.float32) + x_abs = tl.abs(x) + + # FP4 E2M1 representable values: 0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0 + q_val = tl.where( + x_abs <= 0.25, + 0.0, + tl.where( + x_abs < 0.75, + 0.5, + tl.where( + x_abs <= 1.25, + 1.0, + tl.where( + x_abs < 1.75, + 1.5, + tl.where( + x_abs <= 2.5, + 2.0, + tl.where( + x_abs < 3.5, + 3.0, + tl.where(x_abs <= 5.0, 4.0, 6.0), + ), + ), + ), + ), + ), + ) + + y = tl.where(x >= 0, q_val, -q_val) + tl.store(y_ptr + offset, y.to(OUT_DTYPE), mask=mask) + + +def static_blockwise_fp4_cast( + x: torch.Tensor, + out_dtype: torch.dtype | None = None, + rounding: str = "rne", +) -> torch.Tensor: + """Round pre-scaled values to nearest FP4 E2M1 representable value. + + Unlike ``static_blockwise_fp4_fake_quant``, this does **not** apply any + scale -- the caller is responsible for pre-dividing by scale_pre and + post-multiplying by scale_post (as in LAQ). + + Args: + x: Input tensor (any shape) on CUDA. + out_dtype: Output dtype. Defaults to x.dtype. + rounding: Rounding mode (only ``"rne"`` supported currently). + """ + if out_dtype is None: + out_dtype = x.dtype + + x_flat = x.contiguous().view(-1) + y_flat = torch.empty_like(x_flat, dtype=out_dtype) + NUM_ELEMENTS = x_flat.numel() + TILE_SIZE = 1024 + + tl_out_dtype = _torch_dtype_to_tl(out_dtype) + grid = ((NUM_ELEMENTS + TILE_SIZE - 1) // TILE_SIZE,) + + with torch.cuda.device(x.device): + static_blockwise_fp4_cast_kernel[grid]( + x_flat, + y_flat, + NUM_ELEMENTS, + TILE_SIZE=TILE_SIZE, + OUT_DTYPE=tl_out_dtype, + ) + + return y_flat.view_as(x) diff --git a/modelopt/torch/quantization/config.py b/modelopt/torch/quantization/config.py index 0ca30d18448..8c10a9f9403 100644 --- a/modelopt/torch/quantization/config.py +++ b/modelopt/torch/quantization/config.py @@ -1204,6 +1204,82 @@ def _gptq_qdq_default(self): return self +class LAQConfig(QuantizeAlgorithmConfig): + """Config for LAQ (Learnt Amax Quantization) algorithm. + + LAQ uses separate learnable pre-quantization and post-dequantization amax + values. Forward: ``w_q = Q_STE(w / s_pre) * s_post`` where ``s = amax / Q_max``. + + ``learnable_amax`` controls which amax parameters are learnable vs frozen: + - ``["pre", "post"]``: both learnable + - ``"post"`` or ``["post"]``: only post learnable, pre frozen + - ``"pre"`` or ``["pre"]``: only pre learnable, post frozen + - ``[]``: both frozen (static scales) + + ``tied_amax`` makes pre and post share a single tensor (requires both to + have the same learnable state, i.e. ``learnable_amax`` must be + ``["pre", "post"]`` or ``[]``). + + ``quantize_pre_scale=False`` leaves the pre-quantization scale unquantized + while preserving the existing post-scale quantization behavior. + """ + + method: Literal["laq"] = ModeloptField("laq") + + learnable_amax: list[Literal["pre", "post"]] | Literal["pre", "post"] = ModeloptField( + default=["post"], + title="Which amax parameters are learnable.", + description=( + "Which amax params are learnable. " + "'pre', 'post', ['pre', 'post'], or []. " + "Defaults to ['post'] (post-only learnable)." + ), + ) + + tied_amax: bool = ModeloptField( + default=False, + title="Tie pre and post amax into a single tensor.", + description=( + "If True, pre and post share one underlying tensor. " + "Requires both to have the same learnable state." + ), + ) + + quantize_pre_scale: bool = ModeloptField( + default=True, + title="FP8-quantize the LAQ pre-quantization scale.", + description=( + "If False, LAQ uses the raw pre-quantization scale while keeping post-scale " + "quantization controlled by the quantizer's block-scale settings." + ), + ) + + scale_algorithm: dict | None = ModeloptField( + default=None, + title="Scale calibration algorithm to run first.", + description=( + "Dict with 'method' key: 'mse', 'local_hessian', or 'max'. " + "Optional keys include 'fp8_scale_sweep' for FP4 formats. " + "Defaults to {'method': 'mse'} if None." + ), + ) + + @model_validator(mode="after") + def _validate_tied_amax(self): + """Validate tied_amax is compatible with learnable_amax.""" + learn = self.learnable_amax + if isinstance(learn, str): + learn = [learn] + learn_set = set(learn) + if self.tied_amax: + if learn_set not in (set(), {"pre", "post"}): + raise ValueError( + f"tied_amax=True requires learnable_amax to be [] or ['pre', 'post'], " + f"got {self.learnable_amax}" + ) + return self + + QuantizeQuantCfgType = list[QuantizerCfgEntry] QuantizerCfgListConfig = QuantizeQuantCfgType diff --git a/modelopt/torch/quantization/conversion.py b/modelopt/torch/quantization/conversion.py index fa7a8a0a128..00187d291c0 100644 --- a/modelopt/torch/quantization/conversion.py +++ b/modelopt/torch/quantization/conversion.py @@ -37,10 +37,10 @@ normalize_quant_cfg_list, ) from .nn import ( - NVFP4StaticQuantizer, QuantModule, QuantModuleRegistry, SequentialQuantizer, + StaticBlockScaleQuantizer, SVDQuantLinear, TensorQuantizer, ) @@ -100,10 +100,11 @@ def restore_quantized_model( def maybe_promote_nvfp4_static_quantizer(module: nn.Module, quantizer_state: dict) -> None: - if quantizer_state.get("_is_nvfp4_static_quantizer") and not isinstance( - module, NVFP4StaticQuantizer - ): - NVFP4StaticQuantizer.from_tensor_quantizer(module) + if ( + quantizer_state.get("_is_static_block_scale_quantizer") + or quantizer_state.get("_is_nvfp4_static_quantizer") + ) and not isinstance(module, StaticBlockScaleQuantizer): + StaticBlockScaleQuantizer.from_tensor_quantizer(module) def _restore_shared_quant_state_aliases( @@ -153,6 +154,7 @@ def restore_quantizer_state(model: nn.Module, config: QuantizeConfig, metadata: if isinstance(module, TensorQuantizer): name = get_unwrapped_name(name, model) state = quantizer_state_dict[name] + # TODO: Add a registry for TensorQuantizers and avoid this manual conversion. maybe_promote_nvfp4_static_quantizer(module, state) module.set_from_modelopt_state(state) diff --git a/modelopt/torch/quantization/mode.py b/modelopt/torch/quantization/mode.py index 2db966ddbed..718492cc8cf 100644 --- a/modelopt/torch/quantization/mode.py +++ b/modelopt/torch/quantization/mode.py @@ -38,6 +38,7 @@ AWQLiteCalibConfig, CompressConfig, GPTQCalibConfig, + LAQConfig, LocalHessianCalibConfig, MaxCalibConfig, MseCalibConfig, @@ -60,6 +61,7 @@ from .model_calib import ( awq, gptq, + laq, layerwise_calibrate, local_hessian_calibrate, max_calibrate, @@ -531,3 +533,15 @@ def config_class(self) -> type[QuantizeAlgorithmConfig]: return GPTQCalibConfig _calib_func = gptq + + +@CalibrateModeRegistry.register_mode +class LAQModeDescriptor(BaseCalibrateModeDescriptor): + """Mode for LAQ (Learnt Amax Quantization) algorithm.""" + + @property + def config_class(self) -> type[QuantizeAlgorithmConfig]: + """Specifies the config class for the mode.""" + return LAQConfig + + _calib_func = laq diff --git a/modelopt/torch/quantization/model_calib.py b/modelopt/torch/quantization/model_calib.py index 7e5bb85c09b..8d65900db9a 100644 --- a/modelopt/torch/quantization/model_calib.py +++ b/modelopt/torch/quantization/model_calib.py @@ -16,6 +16,7 @@ """Calibration utilities.""" import fnmatch +import inspect import math import time import warnings @@ -34,7 +35,7 @@ LayerActivationCollector, _CheckpointState, ) -from modelopt.torch.utils import print_rank_0, warn_rank_0 +from modelopt.torch.utils import print_rank_0, same_device_as, warn_rank_0 from modelopt.torch.utils.distributed import DistributedProcessGroup, ParallelState from modelopt.torch.utils.distributed import is_initialized as dist_is_initialized from modelopt.torch.utils.distributed import size as dist_size @@ -42,7 +43,13 @@ from .calib import MseCalibrator, NVFP4MSECalibrator, _Calibrator from .conversion import create_and_replace_svdquant_linear_on_the_fly, set_quantizer_by_cfg_context -from .nn import NVFP4StaticQuantizer, QuantModule, SequentialQuantizer, TensorQuantizer +from .nn import ( + NVFP4StaticQuantizer, + QuantModule, + SequentialQuantizer, + StaticBlockScaleQuantizer, + TensorQuantizer, +) from .utils import ( SHARED_PATTERNS, SharedWeightGlobalAmaxState, @@ -55,12 +62,16 @@ is_quantized_row_parallel_linear, persistent_materialization, promote_nvfp4_static_quantizers, + quantizer_attr_names, + reduce_amax, + weight_attr_names, ) from .utils.calib_utils import _GPTQ_HELPER_REGISTRY, GPTQHelper __all__ = [ "CalibratorFactory", "awq", + "laq", "layerwise_calibrate", "local_hessian_calibrate", "max_calibrate", @@ -2045,3 +2056,169 @@ def _make_gptq_handle(name, m): if torch.cuda.is_available(): torch.cuda.empty_cache() print_rank_0(f"GPTQ time: {time.time() - total_start:.2f}s") + + +def _is_quantized_block_scale(quantizer: StaticBlockScaleQuantizer) -> bool: + if quantizer._block_sizes is None: + return False + scale_bits = quantizer._block_sizes.get("scale_bits", None) + if scale_bits is None: + return False + return scale_bits == (4, 3) + + +def _convert_to_static_block_quantizers(model: nn.Module): + """Convert eligible TensorQuantizers to StaticBlockScaleQuantizer.""" + for name, module in model.named_modules(): + if isinstance(module, TensorQuantizer) and not module._disabled: + if not hasattr(module, "_amax") or module._amax is None: + continue + is_static_block_scale = ( + module.is_static_block_quant + and module._block_sizes is not None + and ( + (module._num_bits == (2, 1) and module._block_sizes.get("scale_bits") == (4, 3)) + or isinstance(module._num_bits, int) + ) + ) + if is_static_block_scale: + if _is_quantized_block_scale(module): + global_amax = reduce_amax(module._amax.clone().detach(), axis=None) + else: + global_amax = None + StaticBlockScaleQuantizer.from_tensor_quantizer(module, global_amax=global_amax) + + +def _run_scale_calibration(model, forward_loop, scale_algorithm, caller_name): + """Run calibration and convert to StaticBlockScaleQuantizer if needed.""" + if scale_algorithm is None: + scale_algorithm = {"method": "mse"} + + method = scale_algorithm.get("method") + supported = ("mse", "local_hessian", "max") + assert method in supported, f"{caller_name}: method must be one of {supported}, got '{method}'" + + algo_kwargs = {k: v for k, v in scale_algorithm.items() if k != "method"} + calib_funcs = { + "mse": mse_calibrate, + "local_hessian": local_hessian_calibrate, + "max": max_calibrate, + } + calib_func = calib_funcs[method] + accepted = { + name + for name, p in inspect.signature(calib_func).parameters.items() + if p.kind not in (inspect.Parameter.VAR_KEYWORD, inspect.Parameter.VAR_POSITIONAL) + } + ignored = sorted(k for k in algo_kwargs if k not in accepted) + if ignored: + warnings.warn( + f"{caller_name}: scale_algorithm kwargs {ignored} are not supported by " + f"'{method}' calibration and will be ignored.", + stacklevel=2, + ) + algo_kwargs = {k: v for k, v in algo_kwargs.items() if k in accepted} + calib_func(model, forward_loop=forward_loop, **algo_kwargs) + + if method == "max": + _convert_to_static_block_quantizers(model) + + +def _compute_block_scales(quantizer): + """Compute per-block and per-tensor scales from a StaticBlockScaleQuantizer. + + Returns (per_block_scale, per_tensor_scale, quantize_scales). + """ + from .nn.modules.tensor_quantizer import _FP8_E4M3_MIN_POSITIVE, _amax_to_scale + from .tensor_quant import scaled_e4m3 + + amax = quantizer._amax.float() + max_representable = quantizer._quant_max_bound + quantize_scales = _is_quantized_block_scale(quantizer) + per_tensor_scale = None + + with same_device_as(amax): + if quantize_scales: + global_amax = quantizer._global_amax.float() + per_tensor_scale = _amax_to_scale(global_amax, max_representable) + per_block_scale = scaled_e4m3( + _amax_to_scale( + amax, + max_representable, + min_value=_FP8_E4M3_MIN_POSITIVE * per_tensor_scale.view(-1), + ), + per_tensor_scale, + None, + 4, + 3, + ) + else: + per_block_scale = _amax_to_scale(amax, max_representable) + + return per_block_scale, per_tensor_scale, quantize_scales + + +def _iter_weight_quantizers(model): + """Yield (module, weight_name, quantizer) for each StaticBlockScaleQuantizer with amax.""" + seen_modules = set() + for name, module in model.named_modules(): + if module in seen_modules: + continue + for weight_name in weight_attr_names(module): + wq_name = quantizer_attr_names(weight_name).weight_quantizer + quantizer = getattr(module, wq_name, None) + if isinstance(quantizer, StaticBlockScaleQuantizer) and hasattr(quantizer, "_amax"): + seen_modules.add(module) + yield module, weight_name, quantizer + break + + +def _compute_laq_params(quantizer): + """Compute amax and scale-quantization params for LAQ.""" + per_block_scale, per_tensor_scale, quantize_scales = _compute_block_scales(quantizer) + amax = per_block_scale * quantizer._quant_max_bound + return amax, per_tensor_scale, quantize_scales + + +@torch.no_grad() +def laq( + model: nn.Module, + forward_loop: ForwardLoop | None = None, + scale_algorithm: dict | None = None, + learnable_amax: list | str = ("post",), + tied_amax: bool = False, + quantize_pre_scale: bool = True, + **kwargs, +): + """Run scale calibration then convert to LAQ mode. + + Uses separate pre (quant) and post (dequant) amax values. + Forward: ``w_q = Q_STE(w / s_pre) * s_post`` where ``s = amax / Q_max``. + + Args: + model: Quantized model. + forward_loop: Calibration data forward loop. + scale_algorithm: Calibration algorithm config to run first. + Dict with 'method' key: 'mse', 'local_hessian', or 'max'. + Defaults to {'method': 'mse'} if None. + learnable_amax: Which amax params are learnable: 'pre', 'post', + ['pre', 'post'], or []. + tied_amax: If True, pre and post share a single tensor. + quantize_pre_scale: If False, skip FP8 quantization for the LAQ pre scale. + """ + _run_scale_calibration(model, forward_loop, scale_algorithm, "laq") + + for module, weight_name, quantizer in _iter_weight_quantizers(model): + amax, per_tensor_scale, quantize_scales = _compute_laq_params(quantizer) + weight_dtype = getattr(module, weight_name).dtype + amax = amax.to(weight_dtype) + if per_tensor_scale is not None: + per_tensor_scale = per_tensor_scale.to(weight_dtype) + quantizer.enable_laq( + amax, + per_tensor_scale, + quantize_scales, + learnable_amax=learnable_amax, + tied_amax=tied_amax, + quantize_pre_scale=quantize_pre_scale, + ) diff --git a/modelopt/torch/quantization/nn/modules/tensor_quantizer.py b/modelopt/torch/quantization/nn/modules/tensor_quantizer.py index 98d9e0dcb1e..5658df88172 100644 --- a/modelopt/torch/quantization/nn/modules/tensor_quantizer.py +++ b/modelopt/torch/quantization/nn/modules/tensor_quantizer.py @@ -57,6 +57,8 @@ from ...tensor_quant import ( dynamic_block_quant, fake_tensor_quant, + fp4_cast_ste, + int_cast_ste, scaled_e4m3, static_blockwise_fp4_fake_quant, ) @@ -64,10 +66,15 @@ from ...utils.numeric_utils import fp8_max_for_normalization from ..functional import normalized_hadamard_transform +# torch.finfo(...).tiny gives the smallest normal E4M3 value; scale clamping needs +# the smallest positive subnormal value representable by the 3-bit mantissa. +_FP8_E4M3_MIN_POSITIVE = torch.finfo(torch.float8_e4m3fn).smallest_normal / (2**3) + __all__ = [ "HardDisabledTensorQuantizer", "NVFP4StaticQuantizer", "SequentialQuantizer", + "StaticBlockScaleQuantizer", "TensorQuantizer", "TensorQuantizerCache", "is_registered_quant_backend", @@ -1436,19 +1443,56 @@ def set_from_attribute_config(self, attribute_cfg): self._disabled = True -class NVFP4StaticQuantizer(TensorQuantizer): - """TensorQuantizer for NVFP4 static block quantization with two-level scaling. +def _clamp_scale(scale: torch.Tensor, min_value: float | torch.Tensor = 1e-8) -> torch.Tensor: + """Clamp per-block scale to guard against small/zero values.""" + return torch.where(scale <= min_value, min_value, scale) + + +def _amax_to_scale( + amax: torch.Tensor, max_bound: float, min_value: float | torch.Tensor = 1e-8 +) -> torch.Tensor: + """Convert amax to per-block scale, guarding against small/zero values.""" + return _clamp_scale(amax.float() / max_bound, min_value) + + +def _to_local(t: torch.Tensor) -> torch.Tensor: + """Convert DTensor to local tensor (no-op for regular tensors). + + Under FSDP2, learnable parameters are DTensors but the quantizer forward + operates on local tensors (see TensorQuantizer.forward DTensor handling). + to_local() preserves autograd so gradients flow back to the DTensor parameter. + """ + if DTensor is not None and isinstance(t, DTensor): + return t.to_local() + return t + +class StaticBlockScaleQuantizer(TensorQuantizer): + """TensorQuantizer for static block quantization with two-level scaling. + + Supports both FP4 (E2M1) and INT block quantization formats with configurable + block_size and optional FP8 scale quantization. Uses _global_amax and inherited _amax for per-block amax values. - Preserves both amax states in fp32. + Preserves static amax states in fp32. """ + _laq: bool = False + _learnable_amax: list = [] + _tied_amax: bool = False + _quant_max_bound: float = 6.0 + _quantize_scales: bool = True + _quantize_pre_scale: bool = True + def _preserve_amax_in_fp32(self): amax = getattr(self, "_amax", None) - if amax is not None: + if amax is not None and not isinstance(amax, nn.Parameter): self._amax = amax.to(dtype=torch.float32) global_amax = getattr(self, "_global_amax", None) - if global_amax is not None and global_amax.dtype != torch.float32: + if ( + global_amax is not None + and not isinstance(global_amax, nn.Parameter) + and global_amax.dtype != torch.float32 + ): if "_global_amax" in self.__dict__.get("_shared_quant_tied_attrs", set()): global_amax.data = global_amax.to(dtype=torch.float32) else: @@ -1461,8 +1505,8 @@ def _amax_setter_helper(self, value): @classmethod def from_tensor_quantizer( cls, tq: TensorQuantizer, global_amax: torch.Tensor | None = None - ) -> "NVFP4StaticQuantizer": - """Convert a TensorQuantizer to NVFP4StaticQuantizer in-place. + ) -> "StaticBlockScaleQuantizer": + """Convert a TensorQuantizer to StaticBlockScaleQuantizer in-place. Args: tq: The TensorQuantizer to convert. @@ -1477,11 +1521,48 @@ def _preserve_and_set_global_amax(tq): if isinstance(tq, cls): _preserve_and_set_global_amax(tq) return tq + is_nvfp4_static = getattr(tq, "is_nvfp4_static", False) tq.__class__ = cls - tq._is_nvfp4_static_quantizer = True + tq._is_static_block_scale_quantizer = True + if is_nvfp4_static: + tq._is_nvfp4_static_quantizer = True + tq._quant_max_bound = float(tq.maxbound) _preserve_and_set_global_amax(tq) return tq + @property + def amax_pre(self): + """Pre (quantization) amax. Returns _amax_post when tied.""" + if self._tied_amax: + return self._amax_post + return self._amax_pre + + @property + def amax_post(self): + """Post (dequantization) amax.""" + return self._amax_post + + @property + def amax(self): + """Return amax, derived from learnable amax parameters if in LAQ mode.""" + if self._laq and not self._tied_amax: + raise RuntimeError( + "LAQ with untied amaxes has separate pre and post parameters. " + "Access them via amax_pre / amax_post." + ) + if self._laq: + return self._amax_post + if not hasattr(self, "_amax"): + return None + return self._amax + + @amax.setter + def amax(self, value): + assert value is not None, "amax cannot be set to None." + if not isinstance(value, torch.Tensor): + value = torch.tensor(value) + self._amax_setter_helper(value) + @property def global_amax(self): """Return global_amax for quantization.""" @@ -1519,21 +1600,132 @@ def _apply(self, fn, recurse=True): self.global_amax = global_amax return module + def _short_amax(self, fmt=".4f"): + """Short description of amax, accounting for LAQ mode.""" + if not self._laq: + return super()._short_amax(fmt) + learn = self._learnable_amax + learn_str = "frozen" if not learn else f"learn=[{','.join(learn)}]" + if self._tied_amax: + return f"LAQ(tied={self._short_tensor(self._amax_post.data, fmt)}, {learn_str})" + return ( + f"LAQ(pre={self._short_tensor(self._amax_pre.data, fmt)}, " + f"post={self._short_tensor(self._amax_post.data, fmt)}, {learn_str})" + ) + + def enable_laq( + self, + amax: torch.Tensor, + per_tensor_scale: torch.Tensor = None, + quantize_scales: bool = True, + learnable_amax: list | str = ("post",), + tied_amax: bool = False, + quantize_pre_scale: bool = True, + ): + """LAQ mode with configurable learnable/frozen amax tensors. + + Args: + amax: Initial amax values (per-block). + per_tensor_scale: Optional per-tensor scale (frozen buffer). + quantize_scales: Whether to FP8-quantize per-block scales. + learnable_amax: Which amax params are learnable: 'pre', 'post', + ['pre', 'post'], or []. + tied_amax: If True, pre and post share a single tensor. + quantize_pre_scale: Whether to FP8-quantize the LAQ pre scale. + """ + if hasattr(self, "_amax"): + delattr(self, "_amax") + amax = amax.detach() + if not amax.is_floating_point(): + amax = amax.float() + # TODO: Support fp32 learnable amax values once a stable PyTorch release + # includes FSDP2 mixed-precision parameter dtype support. + amax_param = amax.clone() + amax_buffer = amax.clone() + learn = {learnable_amax} if isinstance(learnable_amax, str) else set(learnable_amax) + + if "post" in learn: + self._amax_post = nn.Parameter(amax_param.clone(), requires_grad=True) + else: + self.register_buffer("_amax_post", amax_buffer.clone()) + + if not tied_amax: + if "pre" in learn: + self._amax_pre = nn.Parameter(amax_param.clone(), requires_grad=True) + else: + self.register_buffer("_amax_pre", amax_buffer.clone()) + + if per_tensor_scale is not None: + self.register_buffer("_per_tensor_scale", per_tensor_scale.clone().detach()) + self._quantize_scales = quantize_scales + self._quantize_pre_scale = quantize_pre_scale + self._laq = True + self._learnable_amax = sorted(learn) + self._tied_amax = tied_amax + + def _cast_ste(self, inputs): + """Cast inputs to quantized representable values (no scaling).""" + if isinstance(self._num_bits, tuple): + return fp4_cast_ste(inputs) + return int_cast_ste(inputs, self._num_bits, self._unsigned, self._narrow_range) + + def _maybe_quantize_scale(self, scale_raw): + """FP8-quantize a per-block scale if ``_quantize_scales`` is enabled, else pass through.""" + if self._quantize_scales: + return scaled_e4m3(scale_raw, self._per_tensor_scale, None, 4, 3) + return scale_raw + def _fake_quantize(self, inputs): """Fake quantization using two-level scaling with _amax and _global_amax.""" - if self.amax is not None: - return static_blockwise_fp4_fake_quant( - inputs, - self.amax, - self.global_amax, # Can be None, will be computed internally - True, # quantize_block_scales - fp8_max_for_normalization(self), - inputs.dtype, - self._pass_through_bwd, + if self._laq: + scale_min_post = ( + _FP8_E4M3_MIN_POSITIVE * self._per_tensor_scale.view(-1) + if self._quantize_scales + else 1e-8 + ) + scale_min_pre = ( + _FP8_E4M3_MIN_POSITIVE * self._per_tensor_scale.view(-1) + if self._quantize_scales and self._quantize_pre_scale + else 1e-8 + ) + + scale_post = self._maybe_quantize_scale( + _amax_to_scale( + _to_local(self.amax_post), + self._quant_max_bound, + min_value=scale_min_post, + ) ) + scale_pre = _amax_to_scale( + _to_local(self.amax_pre), + self._quant_max_bound, + min_value=scale_min_pre, + ) + if self._quantize_pre_scale: + scale_pre = self._maybe_quantize_scale(scale_pre) + quant_input = inputs.float() / scale_pre.float().view(-1, 1) + w_cast = self._cast_ste(quant_input) + return (w_cast * scale_post.view(-1, 1).to(w_cast.dtype)).to(inputs.dtype) + + if self.amax is not None: + if isinstance(self._num_bits, tuple): + return static_blockwise_fp4_fake_quant( + inputs, + self.amax, + self.global_amax, + True, + fp8_max_for_normalization(self), + inputs.dtype, + self._pass_through_bwd, + ) + else: + return super()._fake_quantize(inputs) return super()._fake_quantize(inputs) +NVFP4StaticQuantizer = StaticBlockScaleQuantizer + + class SequentialQuantizer(nn.Sequential): """A sequential container for :class:`TensorQuantizer` modules. diff --git a/modelopt/torch/quantization/plugins/transformers_trainer.py b/modelopt/torch/quantization/plugins/transformers_trainer.py index 981f3d990d4..162b464d15e 100644 --- a/modelopt/torch/quantization/plugins/transformers_trainer.py +++ b/modelopt/torch/quantization/plugins/transformers_trainer.py @@ -38,7 +38,9 @@ disable_lora_quantizers_in_config, get_quantizer_state_dict, is_quantized, + quantizer_attr_names, set_quantizer_state_dict, + weight_attr_names, ) # TODO: Enable documentation rendering for this class @@ -169,6 +171,27 @@ def _patched_post_backward(self): FSDPParamGroup.post_backward = _patched_post_backward +def _align_laq_amax_param_dtypes(model): + """Cast LAQ learnable amax params to their owning weight dtype for FSDP2.""" + # TODO: Remove this once a stable PyTorch release supports FSDP2 mixed + # precision parameter dtypes for this case. + for module in model.modules(): + for weight_name in weight_attr_names(module): + weight = getattr(module, weight_name, None) + if weight is None: + continue + + quantizer_name = quantizer_attr_names(weight_name).weight_quantizer + quantizer = getattr(module, quantizer_name, None) + if not isinstance(quantizer, TensorQuantizer) or not getattr(quantizer, "_laq", False): + continue + + for amax_name in ("_amax_pre", "_amax_post"): + amax = getattr(quantizer, amax_name, None) + if isinstance(amax, torch.nn.Parameter) and amax.dtype != weight.dtype: + amax.data = amax.data.to(dtype=weight.dtype) + + def check_awq_smoothquant(quant_cfg): # TODO: Remove this once deepspeed for AWQ and SmoothQuant is added """Get the quantization type from the configuration.""" @@ -372,6 +395,8 @@ def _modelopt_prepare(self, *args, **kwargs): if model is None: return self._original_prepare(*args, **kwargs) + _align_laq_amax_param_dtypes(model) + # Hide TQ buffers from accelerate's FSDP2 state_dict handling. tq_og_non_prsist_buffers = {} for tq in (m for m in model.modules() if isinstance(m, TensorQuantizer)): diff --git a/modelopt/torch/quantization/tensor_quant.py b/modelopt/torch/quantization/tensor_quant.py index cb48b2bf304..4c220ac4d8c 100644 --- a/modelopt/torch/quantization/tensor_quant.py +++ b/modelopt/torch/quantization/tensor_quant.py @@ -645,7 +645,65 @@ def _tensor_quant(inputs, amax, num_bits=8, unsigned=False, narrow_range=True): return outputs +class FP4CastSTEFunction(Function): + """FP4 cast with STE backward -- no scale/descale, just rounding.""" + + @staticmethod + def forward(ctx, x, out_dtype=None, rounding="rne"): + """Forward pass: cast to FP4 using triton kernel. + + Args: + x: Input tensor of shape [NUM_BLOCKS, BLOCK_SIZE]. + out_dtype: Output dtype. Defaults to x.dtype. + rounding: Rounding mode -- ``"rne"`` (round to nearest even, default) + or ``"down"`` (floor toward zero). + """ + if not triton_kernel.IS_AVAILABLE: + raise RuntimeError("FP4CastSTEFunction requires triton.") + ctx.save_for_backward(x) + return triton_kernel.static_blockwise_fp4_cast(x, out_dtype, rounding=rounding) + + @staticmethod + def backward(ctx, grad_outputs): + """Backward pass: STE with clip mask at |x| <= 6.0.""" + (x,) = ctx.saved_tensors + grad = torch.where(x.abs() <= 6.0, grad_outputs, torch.zeros_like(grad_outputs)) + return grad, None, None + + +class IntCastSTEFunction(Function): + """Integer quantization cast with STE backward, analogous to FP4CastSTEFunction.""" + + @staticmethod + def forward(ctx, x, num_bits, unsigned=False, narrow_range=True): + """Forward pass: clamp-round to integer range.""" + max_bound = (2.0 ** (num_bits - 1 + int(unsigned))) - 1.0 + if unsigned: + min_bound = 0 + elif narrow_range: + min_bound = -max_bound + else: + min_bound = -max_bound - 1 + ctx.save_for_backward(x) + ctx.min_bound = min_bound + ctx.max_bound = max_bound + return torch.clamp(x.round(), min_bound, max_bound) + + @staticmethod + def backward(ctx, grad_outputs): + """Backward pass: STE with clip mask.""" + (x,) = ctx.saved_tensors + grad = torch.where( + (x >= ctx.min_bound) & (x <= ctx.max_bound), + grad_outputs, + torch.zeros_like(grad_outputs), + ) + return grad, None, None, None + + fake_tensor_quant = FakeTensorQuantFunction.apply scaled_e4m3 = ScaledE4M3Function.apply dynamic_block_quant = DynamicBlockQuantizationFunction.apply static_blockwise_fp4_fake_quant = StaticBlockwiseFP4FakeQuantFunction.apply +fp4_cast_ste = FP4CastSTEFunction.apply +int_cast_ste = IntCastSTEFunction.apply diff --git a/tests/gpu/torch/quantization/test_fsdp2.py b/tests/gpu/torch/quantization/test_fsdp2.py index 55648ac26e2..21c6a87ec2d 100644 --- a/tests/gpu/torch/quantization/test_fsdp2.py +++ b/tests/gpu/torch/quantization/test_fsdp2.py @@ -27,6 +27,7 @@ import modelopt.torch.quantization as mtq from modelopt.torch.opt.dynamic import _pytorch_managed +from modelopt.torch.quantization.nn import StaticBlockScaleQuantizer, TensorQuantizer from modelopt.torch.quantization.utils import ( enable_weight_access_and_writeback, persistent_materialization, @@ -136,6 +137,50 @@ def test_nested_fsdp2_backward(quant_cfg, dist_workers): dist_workers.run(partial(_test_nested_fsdp2_backward, quant_cfg=quant_cfg)) +class _LAQBf16Linear(nn.Module): + """Minimal bf16 module with LAQ learnable amax parameters.""" + + def __init__(self, dim=16): + super().__init__() + self.weight = nn.Parameter(torch.randn(dim, dim, dtype=torch.bfloat16)) + + tq = TensorQuantizer() + tq._num_bits = 4 + tq._unsigned = False + tq._narrow_range = True + tq._disabled = False + tq._block_sizes = {-1: dim} + tq._pass_through_bwd = True + tq.register_buffer("_amax", torch.ones(dim, dtype=torch.bfloat16)) + self.weight_quantizer = StaticBlockScaleQuantizer.from_tensor_quantizer(tq) + self.weight_quantizer.enable_laq( + torch.ones(dim, dtype=torch.bfloat16), + quantize_scales=False, + learnable_amax=["pre", "post"], + ) + + def forward(self, inputs): + weight = self.weight_quantizer._fake_quantize(self.weight) + return torch.nn.functional.linear(inputs, weight) + + +def _test_laq_bf16_learnable_amax_fsdp2(rank, size): + torch.manual_seed(1) + model = _LAQBf16Linear().cuda(rank) + inputs = torch.randn(2, 16, device=rank, dtype=torch.bfloat16) + synchronize_state_dict(model) + + assert {p.dtype for p in model.parameters()} == {torch.bfloat16} + + model = fully_shard(model) + output = model(inputs) + output.float().sum().backward() + + +def test_laq_bf16_learnable_amax_fsdp2(dist_workers): + dist_workers.run(_test_laq_bf16_learnable_amax_fsdp2) + + class _DecoderBlock(nn.Module): """Minimal decoder block for FSDP2 sequential tests.""" diff --git a/tests/gpu/torch/quantization/test_laq_cuda.py b/tests/gpu/torch/quantization/test_laq_cuda.py new file mode 100644 index 00000000000..23a04b56a14 --- /dev/null +++ b/tests/gpu/torch/quantization/test_laq_cuda.py @@ -0,0 +1,202 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 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. + +"""GPU unit tests for the LAQ algorithm using FP4 (NVFP4) quantization.""" + +import pytest +import torch +from torch import nn + +import modelopt.torch.quantization as mtq + +NVFP4_LAQ_POST_MSE_CFG = { + "quant_cfg": { + "*weight_quantizer": { + "num_bits": (2, 1), + "block_sizes": {-1: 16, "type": "static", "scale_bits": (4, 3)}, + "axis": None, + "enable": True, + }, + "*input_quantizer": { + "enable": False, + }, + }, + "algorithm": { + "method": "laq", + "learnable_amax": ["post"], + "scale_algorithm": {"method": "mse", "fp8_scale_sweep": True}, + }, +} + +NVFP4_LAQ_PRE_POST_MSE_CFG = { + "quant_cfg": { + "*weight_quantizer": { + "num_bits": (2, 1), + "block_sizes": {-1: 16, "type": "static", "scale_bits": (4, 3)}, + "axis": None, + "enable": True, + }, + "*input_quantizer": { + "enable": False, + }, + }, + "algorithm": { + "method": "laq", + "learnable_amax": ["pre", "post"], + "scale_algorithm": {"method": "mse", "fp8_scale_sweep": True}, + }, +} + +NVFP4_LAQ_TIED_MSE_CFG = { + "quant_cfg": { + "*weight_quantizer": { + "num_bits": (2, 1), + "block_sizes": {-1: 16, "type": "static", "scale_bits": (4, 3)}, + "axis": None, + "enable": True, + }, + "*input_quantizer": { + "enable": False, + }, + }, + "algorithm": { + "method": "laq", + "learnable_amax": ["pre", "post"], + "tied_amax": True, + "scale_algorithm": {"method": "mse", "fp8_scale_sweep": True}, + }, +} + +NVFP4_LAQ_SKIP_PRE_SCALE_MSE_CFG = { + "quant_cfg": { + "*weight_quantizer": { + "num_bits": (2, 1), + "block_sizes": {-1: 16, "type": "static", "scale_bits": (4, 3)}, + "axis": None, + "enable": True, + }, + "*input_quantizer": { + "enable": False, + }, + }, + "algorithm": { + "method": "laq", + "learnable_amax": ["post"], + "quantize_pre_scale": False, + "scale_algorithm": {"method": "mse", "fp8_scale_sweep": True}, + }, +} + + +class SimpleModel(nn.Module): + """Minimal model for LAQ testing.""" + + def __init__(self): + super().__init__() + self.linear = nn.Linear(64, 64, bias=False) + + def forward(self, x): + return self.linear(x) + + +def _make_forward_loop(model, device): + x = torch.randn(2, 64, device=device) + + def forward_loop(m): + m(x) + + return forward_loop + + +@pytest.mark.parametrize( + "config", + [ + NVFP4_LAQ_POST_MSE_CFG, + NVFP4_LAQ_PRE_POST_MSE_CFG, + NVFP4_LAQ_TIED_MSE_CFG, + NVFP4_LAQ_SKIP_PRE_SCALE_MSE_CFG, + ], + ids=["post_only", "pre_and_post", "tied", "skip_pre_scale"], +) +def test_laq_quantize_e2e(config): + """End-to-end: quantize a small model with LAQ + NVFP4 on GPU.""" + device = torch.device("cuda") + model = SimpleModel().to(device) + forward_loop = _make_forward_loop(model, device) + + model = mtq.quantize(model, config, forward_loop=forward_loop) + assert model.linear.weight_quantizer._quantize_pre_scale is config["algorithm"].get( + "quantize_pre_scale", True + ) + + # Verify the model still produces output of the correct shape + x = torch.randn(2, 64, device=device) + out = model(x) + assert out.shape == (2, 64) + + +def test_laq_fp4_fake_quantize_differentiable(): + """Test that _fake_quantize in FP4 LAQ mode is differentiable.""" + from modelopt.torch.quantization.nn.modules.tensor_quantizer import ( + StaticBlockScaleQuantizer, + TensorQuantizer, + ) + + device = torch.device("cuda") + tq = TensorQuantizer() + tq._num_bits = (2, 1) + tq._unsigned = False + tq._narrow_range = True + tq._disabled = False + tq._block_sizes = {-1: 16, "type": "static", "scale_bits": (4, 3)} + tq._pass_through_bwd = True + tq.register_buffer("_amax", torch.ones(4, device=device)) + tq.to(device) + sbsq = StaticBlockScaleQuantizer.from_tensor_quantizer( + tq, global_amax=torch.tensor(1.0, device=device) + ) + + amax = torch.ones(4, device=device) * 3.0 + per_tensor_scale = torch.tensor(1.0 / 6.0, device=device) + sbsq.enable_laq( + amax, + per_tensor_scale=per_tensor_scale, + quantize_scales=True, + learnable_amax=["post"], + ) + + x = torch.randn(4, 16, device=device) + out = sbsq._fake_quantize(x) + assert out.shape == x.shape + out.sum().backward() + assert sbsq._amax_post.grad is not None + + +def test_laq_fp4_cast_ste(): + """Test fp4_cast_ste on GPU.""" + from modelopt.torch.quantization.tensor_quant import fp4_cast_ste + + device = torch.device("cuda") + x = torch.tensor([[-3.0, 1.5, 0.0, 6.0, -6.0, 0.5, -0.5, 2.0]], device=device) + x.requires_grad_(True) + # fp4_cast_ste expects [NUM_BLOCKS, BLOCK_SIZE] -- pad to block size 16 + x_padded = torch.zeros(1, 16, device=device, requires_grad=True) + with torch.no_grad(): + x_padded[:, : x.shape[1]] = x.detach() + x_padded = x_padded.clone().detach().requires_grad_(True) + y = fp4_cast_ste(x_padded) + assert y.shape == x_padded.shape + y.sum().backward() + assert x_padded.grad is not None diff --git a/tests/unit/recipe/test_laq_recipes.py b/tests/unit/recipe/test_laq_recipes.py new file mode 100644 index 00000000000..e6d4be4b1f5 --- /dev/null +++ b/tests/unit/recipe/test_laq_recipes.py @@ -0,0 +1,125 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 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. + +"""Unit tests for LAQ PTQ recipe YAML files in configs/quantize/.""" + +from pathlib import Path + +import pytest +import yaml + +CONFIGS_DIR = Path(__file__).resolve().parents[3] / "examples" / "llm_qat" / "configs" / "quantize" + +# (filename, expected learnable_amax, expected tied_amax) +_LAQ_RECIPES = [ + ("nvfp4_laq_post-mse_init-fp8_kv.yml", ["post"], False), + ("nvfp4_laq_pre-mse_init-fp8_kv.yml", ["pre"], False), + ("nvfp4_laq_pre_post-mse_init-fp8_kv.yml", ["pre", "post"], False), + ("nvfp4_laq_pre_post_tied-mse_init-fp8_kv.yml", ["pre", "post"], True), + ("nvfp4_laq_frozen-mse_init-fp8_kv.yml", [], False), +] + + +def _load_yaml(filename): + path = CONFIGS_DIR / filename + with open(path) as f: + return yaml.safe_load(f) + + +def _find_entry(quant_cfg, quantizer_name): + """Find entry by quantizer_name in the quant_cfg list.""" + for entry in quant_cfg: + if entry.get("quantizer_name") == quantizer_name: + return entry + raise KeyError(f"No entry with quantizer_name={quantizer_name!r}") + + +# --------------------------------------------------------------------------- +# Parametrized load & parse test +# --------------------------------------------------------------------------- + + +@pytest.mark.parametrize(("filename", "_", "__"), _LAQ_RECIPES, ids=[r[0] for r in _LAQ_RECIPES]) +def test_recipe_loads_and_has_required_sections(filename, _, __): + """Each LAQ recipe YAML is parseable and has metadata + quantize.""" + data = _load_yaml(filename) + assert "metadata" in data + assert data["metadata"]["recipe_type"] == "ptq" + assert "quantize" in data + assert "algorithm" in data["quantize"] + assert "quant_cfg" in data["quantize"] + + +# --------------------------------------------------------------------------- +# Algorithm structure test +# --------------------------------------------------------------------------- + + +@pytest.mark.parametrize( + ("filename", "expected_learnable", "expected_tied"), + _LAQ_RECIPES, + ids=[r[0] for r in _LAQ_RECIPES], +) +def test_algorithm_has_correct_laq_params(filename, expected_learnable, expected_tied): + """Algorithm section has correct method, learnable_amax, tied_amax, and scale_algorithm.""" + algo = _load_yaml(filename)["quantize"]["algorithm"] + assert algo["method"] == "laq" + assert algo["learnable_amax"] == expected_learnable + assert algo["tied_amax"] is expected_tied + assert algo["scale_algorithm"] == {"method": "mse", "fp8_scale_sweep": True} + + +# --------------------------------------------------------------------------- +# Weight quantizer uses static type +# --------------------------------------------------------------------------- + + +@pytest.mark.parametrize(("filename", "_", "__"), _LAQ_RECIPES, ids=[r[0] for r in _LAQ_RECIPES]) +def test_weight_quantizer_is_static(filename, _, __): + """Weight quantizer must use static block type for LAQ learnable scales.""" + qcfg = _load_yaml(filename)["quantize"]["quant_cfg"] + w = _find_entry(qcfg, "*weight_quantizer") + assert w["enable"] is True + assert w["cfg"]["block_sizes"]["type"] == "static" + assert w["cfg"]["num_bits"] == "e2m1" + + +# --------------------------------------------------------------------------- +# Input quantizer uses dynamic type +# --------------------------------------------------------------------------- + + +@pytest.mark.parametrize(("filename", "_", "__"), _LAQ_RECIPES, ids=[r[0] for r in _LAQ_RECIPES]) +def test_input_quantizer_is_dynamic(filename, _, __): + """Input/activation quantizer uses dynamic block type.""" + qcfg = _load_yaml(filename)["quantize"]["quant_cfg"] + inp = _find_entry(qcfg, "*input_quantizer") + assert inp["enable"] is True + assert inp["cfg"]["block_sizes"]["type"] == "dynamic" + assert inp["cfg"]["num_bits"] == "e2m1" + + +# --------------------------------------------------------------------------- +# KV cache quantizer enabled +# --------------------------------------------------------------------------- + + +@pytest.mark.parametrize(("filename", "_", "__"), _LAQ_RECIPES, ids=[r[0] for r in _LAQ_RECIPES]) +def test_kv_cache_quantizer_enabled(filename, _, __): + """FP8 KV cache quantizer is present and enabled.""" + qcfg = _load_yaml(filename)["quantize"]["quant_cfg"] + kv = _find_entry(qcfg, "*[kv]_bmm_quantizer") + assert kv["enable"] is True + assert kv["cfg"]["num_bits"] == "e4m3" diff --git a/tests/unit/torch/quantization/test_laq.py b/tests/unit/torch/quantization/test_laq.py new file mode 100644 index 00000000000..0a4819a596c --- /dev/null +++ b/tests/unit/torch/quantization/test_laq.py @@ -0,0 +1,301 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 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. + +"""CPU unit tests for the LAQ algorithm using INT4 quantization.""" + +import pytest +import torch +from torch import nn + +from modelopt.torch.quantization.config import LAQConfig +from modelopt.torch.quantization.nn.modules.tensor_quantizer import ( + _FP8_E4M3_MIN_POSITIVE, + StaticBlockScaleQuantizer, + TensorQuantizer, +) +from modelopt.torch.quantization.plugins.transformers_trainer import _align_laq_amax_param_dtypes +from modelopt.torch.quantization.tensor_quant import int_cast_ste + + +class TestLAQConfig: + """Tests for LAQConfig validation.""" + + def test_default_config(self): + cfg = LAQConfig() + assert cfg.method == "laq" + assert cfg.learnable_amax == ["post"] + assert cfg.tied_amax is False + assert cfg.quantize_pre_scale is True + assert cfg.scale_algorithm is None + + @pytest.mark.parametrize( + ("learnable_amax", "tied_amax"), + [ + (["post"], False), + (["pre"], False), + (["pre", "post"], False), + (["pre", "post"], True), + ([], False), + ([], True), + ("post", False), + ("pre", False), + ], + ) + def test_valid_combinations(self, learnable_amax, tied_amax): + cfg = LAQConfig(learnable_amax=learnable_amax, tied_amax=tied_amax) + assert cfg.tied_amax is tied_amax + + @pytest.mark.parametrize( + "learnable_amax", + [["post"], ["pre"], "post", "pre"], + ) + def test_invalid_tied_with_single_learnable(self, learnable_amax): + with pytest.raises(ValueError, match="tied_amax=True requires"): + LAQConfig(learnable_amax=learnable_amax, tied_amax=True) + + +class TestEnableLAQ: + """Tests for StaticBlockScaleQuantizer.enable_laq() with INT4 format.""" + + def _make_quantizer(self): + """Create a StaticBlockScaleQuantizer configured for INT4.""" + tq = TensorQuantizer() + tq._num_bits = 4 + tq._unsigned = False + tq._narrow_range = True + tq._disabled = False + tq._block_sizes = {-1: 16} + tq._pass_through_bwd = True + tq.register_buffer("_amax", torch.ones(8)) + sbsq = StaticBlockScaleQuantizer.from_tensor_quantizer(tq) + assert sbsq._quant_max_bound == 7.0 + return sbsq + + def test_post_only_learnable(self): + q = self._make_quantizer() + amax = torch.ones(8) * 3.0 + q.enable_laq(amax, quantize_scales=False, learnable_amax=["post"], tied_amax=False) + assert q._laq is True + assert isinstance(q._amax_post, nn.Parameter) + assert q._amax_post.requires_grad is True + assert not isinstance(q._amax_pre, nn.Parameter) + assert not q._amax_pre.requires_grad + + def test_pre_only_learnable(self): + q = self._make_quantizer() + amax = torch.ones(8) * 3.0 + q.enable_laq(amax, quantize_scales=False, learnable_amax=["pre"], tied_amax=False) + assert isinstance(q._amax_pre, nn.Parameter) + assert q._amax_pre.requires_grad is True + assert not isinstance(q._amax_post, nn.Parameter) + + def test_both_learnable(self): + q = self._make_quantizer() + amax = torch.ones(8) * 3.0 + q.enable_laq(amax, quantize_scales=False, learnable_amax=["pre", "post"], tied_amax=False) + assert isinstance(q._amax_pre, nn.Parameter) + assert isinstance(q._amax_post, nn.Parameter) + + def test_tied_both_learnable(self): + q = self._make_quantizer() + amax = torch.ones(8) * 3.0 + q.enable_laq(amax, quantize_scales=False, learnable_amax=["pre", "post"], tied_amax=True) + assert q._tied_amax is True + assert isinstance(q._amax_post, nn.Parameter) + assert not hasattr(q, "_amax_pre") + assert q.amax_pre is q._amax_post + + def test_frozen(self): + q = self._make_quantizer() + amax = torch.ones(8) * 3.0 + q.enable_laq(amax, quantize_scales=False, learnable_amax=[], tied_amax=False) + assert not isinstance(q._amax_post, nn.Parameter) + assert not isinstance(q._amax_pre, nn.Parameter) + + def test_old_amax_deleted(self): + q = self._make_quantizer() + assert hasattr(q, "_amax") + q.enable_laq(torch.ones(8), quantize_scales=False) + assert not hasattr(q, "_amax") + + def test_can_skip_pre_scale_quantization(self): + q = self._make_quantizer() + q.enable_laq( + torch.ones(8), + quantize_scales=False, + quantize_pre_scale=False, + ) + assert q._quantize_pre_scale is False + + @pytest.mark.parametrize("dtype", [torch.float16, torch.bfloat16]) + def test_learnable_amax_uses_input_dtype(self, dtype): + q = self._make_quantizer() + q.enable_laq( + torch.ones(8, dtype=dtype), + quantize_scales=False, + learnable_amax=["pre", "post"], + ) + + assert q._amax_pre.dtype == dtype + assert q._amax_post.dtype == dtype + + def test_dtype_cast_updates_learnable_amax_dtype(self): + q = self._make_quantizer() + q.enable_laq( + torch.ones(8), + quantize_scales=False, + learnable_amax=["pre", "post"], + ) + + q.to(dtype=torch.bfloat16) + + assert q._amax_pre.dtype == torch.bfloat16 + assert q._amax_post.dtype == torch.bfloat16 + + def test_align_laq_amax_param_dtypes_uses_weight_dtype(self): + module = nn.Module() + module.weight = nn.Parameter(torch.ones(8, 16, dtype=torch.bfloat16)) + module.weight_quantizer = self._make_quantizer() + module.weight_quantizer.enable_laq( + torch.ones(8), + quantize_scales=False, + learnable_amax=["pre", "post"], + ) + + assert module.weight_quantizer._amax_pre.dtype == torch.float32 + assert module.weight_quantizer._amax_post.dtype == torch.float32 + + _align_laq_amax_param_dtypes(module) + + assert module.weight_quantizer._amax_pre.dtype == torch.bfloat16 + assert module.weight_quantizer._amax_post.dtype == torch.bfloat16 + + +class TestIntCastSTE: + """Tests for int_cast_ste (INT4 STE function).""" + + def test_round_trip(self): + x = torch.tensor([[-3.2, 1.8, 0.0, 6.5, -7.1]], requires_grad=True) + y = int_cast_ste(x, 4) + assert y.shape == x.shape + max_bound = 7.0 + assert y.min() >= -max_bound + assert y.max() <= max_bound + y.sum().backward() + assert x.grad is not None + + def test_ste_gradient(self): + x = torch.tensor([[2.3, -2.3]], requires_grad=True) + y = int_cast_ste(x, 4) + y.sum().backward() + assert torch.all(x.grad == 1.0) + + +class TestFakeQuantizeLAQ: + """Tests for _fake_quantize() LAQ path with INT4.""" + + def _make_laq_quantizer(self, learnable_amax=("post",), tied_amax=False): + tq = TensorQuantizer() + tq._num_bits = 4 + tq._unsigned = False + tq._narrow_range = True + tq._disabled = False + tq._block_sizes = {-1: 16} + tq._pass_through_bwd = True + tq.register_buffer("_amax", torch.ones(4)) + sbsq = StaticBlockScaleQuantizer.from_tensor_quantizer(tq) + amax = torch.ones(4) * 3.5 + sbsq.enable_laq( + amax, quantize_scales=False, learnable_amax=learnable_amax, tied_amax=tied_amax + ) + return sbsq + + def test_output_shape(self): + q = self._make_laq_quantizer() + x = torch.randn(4, 16) + out = q._fake_quantize(x) + assert out.shape == x.shape + + def test_differentiable_post(self): + q = self._make_laq_quantizer(learnable_amax=["post"]) + x = torch.randn(4, 16) + out = q._fake_quantize(x) + out.sum().backward() + assert q._amax_post.grad is not None + assert q._amax_pre.grad is None + + def test_differentiable_pre(self): + q = self._make_laq_quantizer(learnable_amax=["pre"]) + x = torch.randn(4, 16) + out = q._fake_quantize(x) + out.sum().backward() + assert q._amax_pre.grad is not None + assert q._amax_post.grad is None + + def test_differentiable_both(self): + q = self._make_laq_quantizer(learnable_amax=["pre", "post"]) + x = torch.randn(4, 16) + out = q._fake_quantize(x) + out.sum().backward() + assert q._amax_pre.grad is not None + assert q._amax_post.grad is not None + + def test_tied_shares_tensor(self): + q = self._make_laq_quantizer(learnable_amax=["pre", "post"], tied_amax=True) + x = torch.randn(4, 16) + out = q._fake_quantize(x) + out.sum().backward() + assert q._amax_post.grad is not None + + def test_skip_pre_scale_quantization_still_quantizes_post(self, monkeypatch): + q = self._make_laq_quantizer() + q._quantize_scales = True + q._quantize_pre_scale = False + q.register_buffer("_per_tensor_scale", torch.tensor(1.0)) + calls = [] + + def spy_maybe_quantize_scale(scale_raw): + calls.append(scale_raw) + return scale_raw + + monkeypatch.setattr(q, "_maybe_quantize_scale", spy_maybe_quantize_scale) + + out = q._fake_quantize(torch.randn(4, 16)) + + assert out.shape == (4, 16) + assert len(calls) == 1 + + def test_skip_pre_scale_quantization_uses_raw_scale_floor(self, monkeypatch): + q = self._make_laq_quantizer() + q._quantize_scales = True + q._quantize_pre_scale = False + q.register_buffer("_per_tensor_scale", torch.tensor(1.0)) + min_values = [] + + def fake_amax_to_scale(amax, maxbound, min_value=None): + min_values.append(min_value) + return torch.ones_like(amax) + + monkeypatch.setattr( + "modelopt.torch.quantization.nn.modules.tensor_quantizer._amax_to_scale", + fake_amax_to_scale, + ) + monkeypatch.setattr(q, "_maybe_quantize_scale", lambda scale_raw: scale_raw) + + out = q._fake_quantize(torch.randn(4, 16)) + + assert out.shape == (4, 16) + assert torch.equal(min_values[0], torch.tensor([_FP8_E4M3_MIN_POSITIVE])) + assert min_values[1] == 1e-8 From 058492f6e51284a1fc7eff1e02fd81ce0f895a0d Mon Sep 17 00:00:00 2001 From: realAsma Date: Tue, 7 Jul 2026 17:45:35 +0000 Subject: [PATCH 02/19] Add LSQ and Dual-LSQ QAD support and recipes Signed-off-by: realAsma --- CHANGELOG.rst | 1 + docs/source/guides/10_recipes.rst | 5 +- docs/source/guides/11_config_system.rst | 2 +- examples/hf_ptq/hf_ptq.py | 6 +- examples/llm_qat/ARGUMENTS.md | 2 +- .../nvfp4_laq_frozen-mse_init-fp8_kv.yml | 52 -------- .../nvfp4_laq_post-mse_init-fp8_kv.yml | 53 -------- .../nvfp4_laq_pre-mse_init-fp8_kv.yml | 53 -------- .../configs/train/lr/lr_config_amax.yaml | 5 + .../train/{ => lr}/lr_config_example.yaml | 2 +- .../llm_qat/configs/train/qad_scale_only.yaml | 51 +++++++ .../configs/train/qad_with_learnt_amax.yaml | 45 +++++++ examples/llm_qat/simple_qat_train.py | 4 +- examples/megatron_bridge/quantize.py | 4 +- examples/torch_trt/torch_tensorrt_ptq.py | 4 +- examples/vllm_serve/vllm_ptq_utils.py | 4 +- modelopt/recipe/config.py | 26 +++- modelopt/recipe/loader.py | 12 +- .../kernels/quantization/gemm/fp4_kernel.py | 4 +- modelopt/torch/opt/plugins/transformers.py | 2 +- modelopt/torch/quantization/config.py | 24 +++- modelopt/torch/quantization/mode.py | 12 +- modelopt/torch/quantization/model_calib.py | 18 +-- .../nn/modules/tensor_quantizer.py | 33 ++--- .../plugins/transformers_trainer.py | 18 +-- modelopt/torch/quantization/tensor_quant.py | 10 +- .../general/ptq/nvfp4_default-kv_fp8.yaml | 6 +- .../general/qad/nvfp4_default-kv_fp8.yaml | 1 + .../qad/nvfp4_dual_lsq-mse_init-fp8_kv.yaml | 43 +++--- .../qad/nvfp4_lsq-mse_init-fp8_kv.yaml | 43 +++--- tests/gpu/torch/quantization/test_fsdp2.py | 14 +- .../{test_laq_cuda.py => test_lsq_cuda.py} | 40 +++--- tests/unit/recipe/test_laq_recipes.py | 125 ------------------ tests/unit/recipe/test_loader.py | 22 ++- tests/unit/recipe/test_lsq_recipes.py | 78 +++++++++++ .../quantization/{test_laq.py => test_lsq.py} | 74 ++++++----- 36 files changed, 416 insertions(+), 482 deletions(-) delete mode 100644 examples/llm_qat/configs/quantize/nvfp4_laq_frozen-mse_init-fp8_kv.yml delete mode 100644 examples/llm_qat/configs/quantize/nvfp4_laq_post-mse_init-fp8_kv.yml delete mode 100644 examples/llm_qat/configs/quantize/nvfp4_laq_pre-mse_init-fp8_kv.yml create mode 100644 examples/llm_qat/configs/train/lr/lr_config_amax.yaml rename examples/llm_qat/configs/train/{ => lr}/lr_config_example.yaml (95%) create mode 100644 examples/llm_qat/configs/train/qad_scale_only.yaml create mode 100644 examples/llm_qat/configs/train/qad_with_learnt_amax.yaml create mode 120000 modelopt_recipes/general/qad/nvfp4_default-kv_fp8.yaml rename examples/llm_qat/configs/quantize/nvfp4_laq_pre_post-mse_init-fp8_kv.yml => modelopt_recipes/general/qad/nvfp4_dual_lsq-mse_init-fp8_kv.yaml (54%) rename examples/llm_qat/configs/quantize/nvfp4_laq_pre_post_tied-mse_init-fp8_kv.yml => modelopt_recipes/general/qad/nvfp4_lsq-mse_init-fp8_kv.yaml (54%) rename tests/gpu/torch/quantization/{test_laq_cuda.py => test_lsq_cuda.py} (87%) delete mode 100644 tests/unit/recipe/test_laq_recipes.py create mode 100644 tests/unit/recipe/test_lsq_recipes.py rename tests/unit/torch/quantization/{test_laq.py => test_lsq.py} (83%) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 03bdb027296..d7173f7e373 100755 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -11,6 +11,7 @@ Changelog **Deprecations** +- Renamed ``modelopt.recipe.ModelOptPTQRecipe`` to ``ModelOptQuantizeRecipe`` because it now backs the ``ptq``, ``qat/qad``, and ``ptq/qat/qad`` recipe types (not just PTQ). The old ``ModelOptPTQRecipe`` name remains as a **deprecated alias** of ``ModelOptQuantizeRecipe`` and will be removed in a future release. Please update imports and ``isinstance`` checks to the new name. - ``examples/hf_ptq`` AutoQuantize is now driven by an **AutoQuantize recipe** (``--recipe``). The ``--auto_quantize_bits``, ``--auto_quantize_method``, ``--auto_quantize_score_size``, ``--auto_quantize_cost_model``, and ``--auto_quantize_active_moe_expert_ratio`` flags are **deprecated** but still work: they are converted into an ``AutoQuantizeConfig`` on the fly (emitting a ``DeprecationWarning``) and will be removed in a future release. Prefer a recipe under ``modelopt_recipes/general/auto_quantize/``. See ``examples/hf_ptq/README.md``. - Renamed ``examples/llm_ptq`` to ``examples/hf_ptq`` to reflect that it covers Hugging Face LLM **and** VLM PTQ. A relative symlink ``examples/llm_ptq`` -> ``hf_ptq`` keeps existing paths and commands working; it will be removed in a future release. Please update references to the new ``examples/hf_ptq`` path. diff --git a/docs/source/guides/10_recipes.rst b/docs/source/guides/10_recipes.rst index ba96b823fe8..fa114c10289 100644 --- a/docs/source/guides/10_recipes.rst +++ b/docs/source/guides/10_recipes.rst @@ -720,8 +720,9 @@ Recipes are validated at load time using Pydantic models: :class:`~modelopt.torch.opt.config.ModeloptBaseConfig` subclass exposing ``recipe_type`` and ``description`` as Pydantic fields. -:class:`~modelopt.recipe.config.ModelOptPTQRecipe` - PTQ-specific recipe. Adds a required ``quantize`` field typed as +:class:`~modelopt.recipe.config.ModelOptQuantizeRecipe` + Quantization recipe (PTQ, QAT/QAD, or both). Adds a required ``quantize`` + field typed as :class:`~modelopt.torch.quantization.config.QuantizeConfig` (also a ``ModeloptBaseConfig`` subclass, containing ``quant_cfg`` and ``algorithm``). diff --git a/docs/source/guides/11_config_system.rst b/docs/source/guides/11_config_system.rst index cb659c2482a..0ee6ecd4933 100644 --- a/docs/source/guides/11_config_system.rst +++ b/docs/source/guides/11_config_system.rst @@ -529,7 +529,7 @@ the speculative-decoding variants); ``metadata`` is required for all types. ``metadata.recipe_type``, picks the matching recipe schema, and calls ``load_config(file, schema_type=schema)`` so list-typed ``$import`` resolution knows the element types. The returned object is a validated recipe instance - (for example a ``ModelOptPTQRecipe``). + (for example a ``ModelOptQuantizeRecipe``). * A **directory recipe** is a directory containing ``metadata.yml`` / ``metadata.yaml`` and ``quantize.yml`` / ``quantize.yaml``. Each file is loaded with its own schema (``RecipeMetadataConfig`` and ``QuantizeConfig``, diff --git a/examples/hf_ptq/hf_ptq.py b/examples/hf_ptq/hf_ptq.py index 8dcc78afa27..2e8e087a64e 100755 --- a/examples/hf_ptq/hf_ptq.py +++ b/examples/hf_ptq/hf_ptq.py @@ -56,7 +56,7 @@ import modelopt.torch.opt as mto import modelopt.torch.quantization as mtq import modelopt.torch.sparsity as mts -from modelopt.recipe import ModelOptAutoQuantizeRecipe, ModelOptPTQRecipe, load_recipe +from modelopt.recipe import ModelOptAutoQuantizeRecipe, ModelOptQuantizeRecipe, load_recipe from modelopt.recipe.presets import KV_CACHE_NONE, KV_QUANT_CFG_CHOICES, QUANT_CFG_CHOICES from modelopt.torch.export import ( export_hf_checkpoint, @@ -1072,7 +1072,7 @@ def quantize_main( if args.recipe is not None: print(f"Use recipe {args.recipe} for quantization") recipe = load_recipe(args.recipe) - if not isinstance(recipe, (ModelOptPTQRecipe, ModelOptAutoQuantizeRecipe)): + if not isinstance(recipe, (ModelOptQuantizeRecipe, ModelOptAutoQuantizeRecipe)): raise TypeError( f"Expected PTQ or AutoQuantize recipe, but got {type(recipe).__name__} " f"from {args.recipe}" @@ -1093,7 +1093,7 @@ def quantize_main( aq_config = None def _is_layerwise(obj): - if isinstance(obj, ModelOptPTQRecipe): + if isinstance(obj, ModelOptQuantizeRecipe): return _is_layerwise(obj.quantize.algorithm) if isinstance(obj, list): return any(_is_layerwise(a) for a in obj) diff --git a/examples/llm_qat/ARGUMENTS.md b/examples/llm_qat/ARGUMENTS.md index 0a3e2b7a12d..35f788318c9 100644 --- a/examples/llm_qat/ARGUMENTS.md +++ b/examples/llm_qat/ARGUMENTS.md @@ -64,7 +64,7 @@ Extends [HuggingFace TrainingArguments](https://huggingface.co/docs/transformers |----------|------|---------|-------------| | `--trainable_params` | `list[str]` | `None` | Glob patterns (fnmatch) for parameters that should be trainable. All other parameters will be frozen. Mutually exclusive with frozen_params. | | `--frozen_params` | `list[str]` | `None` | Glob patterns (fnmatch) for parameters that should be frozen. Mutually exclusive with trainable_params. | -| `--lr_config` | `str` | `None` | Path to a YAML file mapping fnmatch patterns to optimizer kwargs (e.g. lr, weight_decay). First matching pattern wins per parameter. See examples/llm_qat/configs/train/lr_config_example.yaml. | +| `--lr_config` | `str` | `None` | Path to a YAML file mapping fnmatch patterns to optimizer kwargs (e.g. lr, weight_decay). First matching pattern wins per parameter. See examples/llm_qat/configs/train/lr/lr_config_example.yaml. | | `--manual_gc` | `bool` | `False` | Run `gc.collect()` before each training/prediction step to work around GPU memory leaks during QAT/distillation. | | `--liger_ce_label_smoothing` | `float` | `0.0` | Label smoothing for Liger fused CE loss. Only used when --use_liger_kernel is enabled. | | `--lora` | `bool` | `False` | Whether to add LoRA (Low-Rank Adaptation) adapter before training. When using real quantization, the LoRA adapter must be set, as quantized weights will be frozen during training. | diff --git a/examples/llm_qat/configs/quantize/nvfp4_laq_frozen-mse_init-fp8_kv.yml b/examples/llm_qat/configs/quantize/nvfp4_laq_frozen-mse_init-fp8_kv.yml deleted file mode 100644 index 9a4406961f4..00000000000 --- a/examples/llm_qat/configs/quantize/nvfp4_laq_frozen-mse_init-fp8_kv.yml +++ /dev/null @@ -1,52 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024 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. - -metadata: - recipe_type: ptq - description: NVFP4 LAQ frozen amax (static, both pre+post non-learnable), MSE init with FP8 scale sweep, FP8 KV cache. -quantize: - algorithm: - method: laq - learnable_amax: [] - tied_amax: false - scale_algorithm: - method: mse - fp8_scale_sweep: true - quant_cfg: - - quantizer_name: '*' - enable: false - - quantizer_name: '*weight_quantizer' - enable: true - cfg: - block_sizes: - -1: 16 - type: static - scale_bits: e4m3 - num_bits: e2m1 - - quantizer_name: '*input_quantizer' - enable: true - cfg: - block_sizes: - -1: 16 - type: dynamic - scale_bits: e4m3 - num_bits: e2m1 - - quantizer_name: '*[kv]_bmm_quantizer' - enable: true - cfg: - num_bits: e4m3 - axis: - - quantizer_name: '*lm_head*' - enable: false diff --git a/examples/llm_qat/configs/quantize/nvfp4_laq_post-mse_init-fp8_kv.yml b/examples/llm_qat/configs/quantize/nvfp4_laq_post-mse_init-fp8_kv.yml deleted file mode 100644 index 34169be85e6..00000000000 --- a/examples/llm_qat/configs/quantize/nvfp4_laq_post-mse_init-fp8_kv.yml +++ /dev/null @@ -1,53 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024 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. - -metadata: - recipe_type: ptq - description: NVFP4 LAQ post-only learnable amax (W4A16), MSE init with FP8 scale sweep, FP8 KV cache. -quantize: - algorithm: - method: laq - learnable_amax: - - post - tied_amax: false - scale_algorithm: - method: mse - fp8_scale_sweep: true - quant_cfg: - - quantizer_name: '*' - enable: false - - quantizer_name: '*weight_quantizer' - enable: true - cfg: - block_sizes: - -1: 16 - type: static - scale_bits: e4m3 - num_bits: e2m1 - - quantizer_name: '*input_quantizer' - enable: true - cfg: - block_sizes: - -1: 16 - type: dynamic - scale_bits: e4m3 - num_bits: e2m1 - - quantizer_name: '*[kv]_bmm_quantizer' - enable: true - cfg: - num_bits: e4m3 - axis: - - quantizer_name: '*lm_head*' - enable: false diff --git a/examples/llm_qat/configs/quantize/nvfp4_laq_pre-mse_init-fp8_kv.yml b/examples/llm_qat/configs/quantize/nvfp4_laq_pre-mse_init-fp8_kv.yml deleted file mode 100644 index 6a8056f9795..00000000000 --- a/examples/llm_qat/configs/quantize/nvfp4_laq_pre-mse_init-fp8_kv.yml +++ /dev/null @@ -1,53 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024 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. - -metadata: - recipe_type: ptq - description: NVFP4 LAQ pre-only learnable amax (W4A16), MSE init with FP8 scale sweep, FP8 KV cache. -quantize: - algorithm: - method: laq - learnable_amax: - - pre - tied_amax: false - scale_algorithm: - method: mse - fp8_scale_sweep: true - quant_cfg: - - quantizer_name: '*' - enable: false - - quantizer_name: '*weight_quantizer' - enable: true - cfg: - block_sizes: - -1: 16 - type: static - scale_bits: e4m3 - num_bits: e2m1 - - quantizer_name: '*input_quantizer' - enable: true - cfg: - block_sizes: - -1: 16 - type: dynamic - scale_bits: e4m3 - num_bits: e2m1 - - quantizer_name: '*[kv]_bmm_quantizer' - enable: true - cfg: - num_bits: e4m3 - axis: - - quantizer_name: '*lm_head*' - enable: false diff --git a/examples/llm_qat/configs/train/lr/lr_config_amax.yaml b/examples/llm_qat/configs/train/lr/lr_config_amax.yaml new file mode 100644 index 00000000000..6b2b5f303f9 --- /dev/null +++ b/examples/llm_qat/configs/train/lr/lr_config_amax.yaml @@ -0,0 +1,5 @@ +# Override the learning rate for LSQ's learnable amax parameters to 1e-4. +"*weight_quantizer._amax_pre": + lr: 1e-4 +"*weight_quantizer._amax_post": + lr: 1e-4 diff --git a/examples/llm_qat/configs/train/lr_config_example.yaml b/examples/llm_qat/configs/train/lr/lr_config_example.yaml similarity index 95% rename from examples/llm_qat/configs/train/lr_config_example.yaml rename to examples/llm_qat/configs/train/lr/lr_config_example.yaml index 844e5199e8b..ce3c6a5a5a2 100644 --- a/examples/llm_qat/configs/train/lr_config_example.yaml +++ b/examples/llm_qat/configs/train/lr/lr_config_example.yaml @@ -12,7 +12,7 @@ # eps - term added to denominator for numerical stability # # Usage: -# --lr_config configs/train/lr_config_example.yaml +# --lr_config configs/train/lr/lr_config_example.yaml # # Tip: use `model.named_parameters()` to find the exact parameter names # for your model. diff --git a/examples/llm_qat/configs/train/qad_scale_only.yaml b/examples/llm_qat/configs/train/qad_scale_only.yaml new file mode 100644 index 00000000000..39c999d02e1 --- /dev/null +++ b/examples/llm_qat/configs/train/qad_scale_only.yaml @@ -0,0 +1,51 @@ +# Scale-only QAD for LSQ-quantized checkpoints + +# Model +model_name_or_path: # e.g., qwen3-8b-lsq-quantized +output_dir: # e.g., qwen3-8b-lsq-scale-qad +attn_implementation: flash_attention_2 + +# Distillation +distill: true +teacher_model: # e.g., Qwen/Qwen3-8B + +# Dataset +dataset_config: configs/dataset/blend.yaml +train_samples: 20000 +eval_samples: 2000 + +# Train only LSQ amax scale parameters. Tied LSQ exposes only _amax_post. +trainable_params: + - "*weight_quantizer._amax_pre" + - "*weight_quantizer._amax_post" + +# Hyperparameters +num_train_epochs: 1.0 +# LSQ amax parameter requires higher learning rate than quantized weights +learning_rate: 1e-4 +weight_decay: 0.0 +per_device_train_batch_size: 2 +per_device_eval_batch_size: 2 +gradient_accumulation_steps: 2 +model_max_length: 8192 +warmup_ratio: 0.05 +lr_scheduler_type: cosine +use_liger_kernel: true +manual_gc: true +seed: 42 +do_train: true +do_eval: true + +# Checkpointing +load_best_model_at_end: true +save_total_limit: 2 + +# Evaluation +eval_on_start: true +eval_strategy: steps +eval_steps: 50 + +# Logging +logging_steps: 1 +report_to: + - tensorboard diff --git a/examples/llm_qat/configs/train/qad_with_learnt_amax.yaml b/examples/llm_qat/configs/train/qad_with_learnt_amax.yaml new file mode 100644 index 00000000000..76352defa43 --- /dev/null +++ b/examples/llm_qat/configs/train/qad_with_learnt_amax.yaml @@ -0,0 +1,45 @@ +# Full-parameter QAD for LSQ-quantized checkpoints + +# Model +model_name_or_path: # e.g., qwen3-8b-lsq-quantized +output_dir: # e.g., qwen3-8b-lsq-full-qad +attn_implementation: flash_attention_2 + +# Distillation +distill: true +teacher_model: # e.g., Qwen/Qwen3-8B + +# Dataset +dataset_config: configs/dataset/blend.yaml +train_samples: 20000 +eval_samples: 2000 + +# Hyperparameters +num_train_epochs: 1.0 +learning_rate: 1e-5 +lr_config: configs/train/lr/lr_config_amax.yaml +per_device_train_batch_size: 2 +per_device_eval_batch_size: 2 +gradient_accumulation_steps: 2 +model_max_length: 8192 +warmup_ratio: 0.05 +lr_scheduler_type: cosine +use_liger_kernel: true +manual_gc: true +seed: 42 +do_train: true +do_eval: true + +# Checkpointing +load_best_model_at_end: true +save_total_limit: 2 + +# Evaluation +eval_on_start: true +eval_strategy: steps +eval_steps: 50 + +# Logging +logging_steps: 1 +report_to: + - tensorboard diff --git a/examples/llm_qat/simple_qat_train.py b/examples/llm_qat/simple_qat_train.py index e3c3231494c..7c33853c710 100644 --- a/examples/llm_qat/simple_qat_train.py +++ b/examples/llm_qat/simple_qat_train.py @@ -26,7 +26,7 @@ import modelopt.torch.opt as mto import modelopt.torch.quantization as mtq -from modelopt.recipe import ModelOptPTQRecipe, load_recipe +from modelopt.recipe import ModelOptQuantizeRecipe, load_recipe def get_dataloader(args, tokenizer): @@ -131,7 +131,7 @@ def calibrate(m: nn.Module): # Load recipe and quantize the model recipe = load_recipe(args.recipe) - if not isinstance(recipe, ModelOptPTQRecipe): + if not isinstance(recipe, ModelOptQuantizeRecipe): raise ValueError(f"Expected PTQ recipe, but got {type(recipe).__name__} from {args.recipe}") model = mtq.quantize(model, recipe.quantize, calibrate) diff --git a/examples/megatron_bridge/quantize.py b/examples/megatron_bridge/quantize.py index d57e74277c6..5045e994137 100644 --- a/examples/megatron_bridge/quantize.py +++ b/examples/megatron_bridge/quantize.py @@ -65,7 +65,7 @@ import modelopt.torch.quantization as mtq import modelopt.torch.utils.distributed as dist -from modelopt.recipe import ModelOptPTQRecipe, load_recipe +from modelopt.recipe import ModelOptQuantizeRecipe, load_recipe from modelopt.recipe.presets import KV_CACHE_NONE, KV_QUANT_CFG_CHOICES, QUANT_CFG_CHOICES from modelopt.torch.utils import print_args, print_rank_0, warn_rank_0 from modelopt.torch.utils.dataset_utils import get_supported_datasets @@ -227,7 +227,7 @@ def get_quant_config(args: argparse.Namespace) -> dict: "--recipe is set; the recipe is authoritative." ) recipe = load_recipe(args.recipe) - if not isinstance(recipe, ModelOptPTQRecipe): + if not isinstance(recipe, ModelOptQuantizeRecipe): raise TypeError( f"Expected a PTQ recipe but got {type(recipe).__name__} from {args.recipe}" ) diff --git a/examples/torch_trt/torch_tensorrt_ptq.py b/examples/torch_trt/torch_tensorrt_ptq.py index dcd60534de7..fa4b5becbfd 100644 --- a/examples/torch_trt/torch_tensorrt_ptq.py +++ b/examples/torch_trt/torch_tensorrt_ptq.py @@ -41,7 +41,7 @@ import modelopt.torch.opt as mto import modelopt.torch.quantization as mtq -from modelopt.recipe import ModelOptPTQRecipe, load_recipe +from modelopt.recipe import ModelOptQuantizeRecipe, load_recipe from modelopt.torch.quantization.utils import export_torch_mode # Default ViT PTQ recipe under `modelopt_recipes/huggingface/vit/ptq/`. The @@ -97,7 +97,7 @@ def quantize_with_recipe(model, recipe_path: str, calib_batches): """Resolve the YAML recipe and run `mtq.quantize`.""" print(f"Loading recipe: {recipe_path}") recipe = load_recipe(recipe_path) - if not isinstance(recipe, ModelOptPTQRecipe): + if not isinstance(recipe, ModelOptQuantizeRecipe): raise TypeError(f"Expected PTQ recipe, got {type(recipe).__name__}") quant_cfg = recipe.quantize.model_dump() diff --git a/examples/vllm_serve/vllm_ptq_utils.py b/examples/vllm_serve/vllm_ptq_utils.py index 88b31d54a70..4f1cb4c0f88 100644 --- a/examples/vllm_serve/vllm_ptq_utils.py +++ b/examples/vllm_serve/vllm_ptq_utils.py @@ -24,7 +24,7 @@ from vllm.v1.core.sched.output import CachedRequestData, NewRequestData, SchedulerOutput import modelopt.torch.quantization as mtq -from modelopt.recipe import ModelOptPTQRecipe, load_recipe +from modelopt.recipe import ModelOptQuantizeRecipe, load_recipe def _create_new_data_cls(data_cls, **kwargs): @@ -144,7 +144,7 @@ def get_quant_config(quant_config: dict[str, Any], model: Any) -> dict[str, Any] if quant_config["recipe_path"]: recipe = load_recipe(quant_config["recipe_path"]) - assert isinstance(recipe, ModelOptPTQRecipe), ( + assert isinstance(recipe, ModelOptQuantizeRecipe), ( f"Expected PTQ recipe, but got {type(recipe).__name__} from {quant_config['recipe_path']}" ) quant_cfg = recipe.quantize diff --git a/modelopt/recipe/config.py b/modelopt/recipe/config.py index 2cf5a2f0cfb..f2d268ded22 100644 --- a/modelopt/recipe/config.py +++ b/modelopt/recipe/config.py @@ -43,6 +43,7 @@ "ModelOptEagleRecipe", "ModelOptMedusaRecipe", "ModelOptPTQRecipe", + "ModelOptQuantizeRecipe", "ModelOptRecipeBase", "ModelOptSpeculativeRecipeBase", "RecipeMetadataConfig", @@ -54,6 +55,8 @@ class RecipeType(str, Enum): """List of recipe types. See ``RECIPE_TYPE_TO_CLASS`` at the bottom for the schema mapping.""" PTQ = "ptq" + QAT_QAD = "qat/qad" + PTQ_QAT_QAD = "ptq/qat/qad" AUTO_QUANTIZE = "auto_quantize" SPECULATIVE_EAGLE = "speculative_eagle" SPECULATIVE_DFLASH = "speculative_dflash" @@ -112,17 +115,24 @@ def description(self) -> str: return self.metadata.description -class ModelOptPTQRecipe(ModelOptRecipeBase): - """Our config class for PTQ recipes.""" +class ModelOptQuantizeRecipe(ModelOptRecipeBase): + """Config class for quantization recipes — PTQ, QAT/QAD, or both. + + ``metadata.recipe_type`` declares which workflow(s) the recipe is intended for. + """ quantize: QuantizeConfig = Field( - title="PTQ config", - description="PTQ config containing quant_cfg and algorithm. Required: a PTQ " - "recipe without a ``quantize`` section is rejected so that a missing section " - "can't silently fall back to the default INT8 config.", + title="Quantization config", + description="Quantization config containing quant_cfg and algorithm. Required: a " + "quantization recipe without a ``quantize`` section is rejected so that a missing " + "section can't silently fall back to the default INT8 config.", ) +# Deprecated alias (shipped in 0.43 as ModelOptPTQRecipe); remove in a future release. +ModelOptPTQRecipe = ModelOptQuantizeRecipe + + # Named alias so a shared layer-pattern unit (e.g. configs/auto_quantize/units/base_disabled_layers) # can declare ``modelopt-schema: modelopt.recipe.config.LayerPatternList`` and be spliced into a # ``list[str]`` field — mirrors how base_disable_all is imported into a PTQ quant_cfg list. @@ -358,7 +368,9 @@ class ModelOptMedusaRecipe(ModelOptSpeculativeRecipeBase): # Single source of truth mapping YAML ``metadata.recipe_type`` to its schema class. The loader # uses this for typed-list ``$import`` resolution; add a new entry when introducing a recipe. RECIPE_TYPE_TO_CLASS: dict[RecipeType, type[ModelOptRecipeBase]] = { - RecipeType.PTQ: ModelOptPTQRecipe, + RecipeType.PTQ: ModelOptQuantizeRecipe, + RecipeType.QAT_QAD: ModelOptQuantizeRecipe, + RecipeType.PTQ_QAT_QAD: ModelOptQuantizeRecipe, RecipeType.AUTO_QUANTIZE: ModelOptAutoQuantizeRecipe, RecipeType.SPECULATIVE_EAGLE: ModelOptEagleRecipe, RecipeType.SPECULATIVE_DFLASH: ModelOptDFlashRecipe, diff --git a/modelopt/recipe/loader.py b/modelopt/recipe/loader.py index 6af6d0a8a7a..0a3c3b42a86 100644 --- a/modelopt/recipe/loader.py +++ b/modelopt/recipe/loader.py @@ -29,7 +29,7 @@ from .config import ( RECIPE_TYPE_TO_CLASS, - ModelOptPTQRecipe, + ModelOptQuantizeRecipe, ModelOptRecipeBase, RecipeMetadataConfig, RecipeType, @@ -42,6 +42,8 @@ # must contain 'quantize'" instead of pydantic's generic missing-field error. _REQUIRED_SECTION_PER_RECIPE_TYPE: dict[RecipeType, str] = { RecipeType.PTQ: "quantize", + RecipeType.QAT_QAD: "quantize", + RecipeType.PTQ_QAT_QAD: "quantize", RecipeType.AUTO_QUANTIZE: "auto_quantize", RecipeType.SPECULATIVE_EAGLE: "eagle", RecipeType.SPECULATIVE_DFLASH: "dflash", @@ -224,8 +226,12 @@ def _load_recipe_from_dir(recipe_dir: Path | Traversable) -> ModelOptRecipeBase: metadata_file = _find_recipe_section_file(recipe_dir, "metadata") metadata = load_config(metadata_file, schema_type=RecipeMetadataConfig) - if metadata.recipe_type == RecipeType.PTQ: + if metadata.recipe_type in { + RecipeType.PTQ, + RecipeType.QAT_QAD, + RecipeType.PTQ_QAT_QAD, + }: quantize_file = _find_recipe_section_file(recipe_dir, "quantize") quantize_cfg = load_config(quantize_file, schema_type=QuantizeConfig) - return ModelOptPTQRecipe(metadata=metadata, quantize=quantize_cfg) + return ModelOptQuantizeRecipe(metadata=metadata, quantize=quantize_cfg) raise ValueError(f"Unsupported recipe type: {metadata.recipe_type!r}") diff --git a/modelopt/torch/kernels/quantization/gemm/fp4_kernel.py b/modelopt/torch/kernels/quantization/gemm/fp4_kernel.py index 6e4754741d0..c9499b612f6 100644 --- a/modelopt/torch/kernels/quantization/gemm/fp4_kernel.py +++ b/modelopt/torch/kernels/quantization/gemm/fp4_kernel.py @@ -366,18 +366,16 @@ def static_blockwise_fp4_cast_kernel( def static_blockwise_fp4_cast( x: torch.Tensor, out_dtype: torch.dtype | None = None, - rounding: str = "rne", ) -> torch.Tensor: """Round pre-scaled values to nearest FP4 E2M1 representable value. Unlike ``static_blockwise_fp4_fake_quant``, this does **not** apply any scale -- the caller is responsible for pre-dividing by scale_pre and - post-multiplying by scale_post (as in LAQ). + post-multiplying by scale_post (as in LSQ). Args: x: Input tensor (any shape) on CUDA. out_dtype: Output dtype. Defaults to x.dtype. - rounding: Rounding mode (only ``"rne"`` supported currently). """ if out_dtype is None: out_dtype = x.dtype diff --git a/modelopt/torch/opt/plugins/transformers.py b/modelopt/torch/opt/plugins/transformers.py index 6853abcf85c..f72715d410c 100644 --- a/modelopt/torch/opt/plugins/transformers.py +++ b/modelopt/torch/opt/plugins/transformers.py @@ -231,7 +231,7 @@ class ModelOptTrainerArguments(ModelOptHFArguments): "help": ( "Path to a YAML file mapping fnmatch patterns to optimizer kwargs " "(e.g. lr, weight_decay). First matching pattern wins per parameter. " - "See examples/llm_qat/configs/train/lr_config_example.yaml." + "See examples/llm_qat/configs/train/lr/lr_config_example.yaml." ), }, ) diff --git a/modelopt/torch/quantization/config.py b/modelopt/torch/quantization/config.py index 8c10a9f9403..94c22b2a44f 100644 --- a/modelopt/torch/quantization/config.py +++ b/modelopt/torch/quantization/config.py @@ -1204,11 +1204,21 @@ def _gptq_qdq_default(self): return self -class LAQConfig(QuantizeAlgorithmConfig): - """Config for LAQ (Learnt Amax Quantization) algorithm. +class LSQConfig(QuantizeAlgorithmConfig): + """Config for LSQ (Learnt Scale Quantization) and Dual-LSQ algorithms. - LAQ uses separate learnable pre-quantization and post-dequantization amax - values. Forward: ``w_q = Q_STE(w / s_pre) * s_post`` where ``s = amax / Q_max``. + In LSQ, the scale used for quantization is learnt. ModelOpt's LSQ is similar to the + original `Learned Step Size Quantization paper `_. + Its forward pass is ``w_q = Q_STE(w / s) * s``, where ``s`` is learnt. + + Dual-LSQ learns separate pre-quantization and post-quantization scales. Its forward + pass is ``w_q = Q_STE(w / s_pre) * s_post``, where ``s_pre`` and ``s_post`` are + learnt. Dual-LSQ generally performs better than LSQ for learning NVFP4 per-block + weight scales. + + Currently, only NVFP4 per-block weight-scale learning is supported. Both LSQ and + Dual-LSQ use a reparameterization that learns ``amax`` instead of scale directly, + where ``scale = amax / max_bound``. ``learnable_amax`` controls which amax parameters are learnable vs frozen: - ``["pre", "post"]``: both learnable @@ -1224,7 +1234,7 @@ class LAQConfig(QuantizeAlgorithmConfig): while preserving the existing post-scale quantization behavior. """ - method: Literal["laq"] = ModeloptField("laq") + method: Literal["lsq"] = ModeloptField("lsq") learnable_amax: list[Literal["pre", "post"]] | Literal["pre", "post"] = ModeloptField( default=["post"], @@ -1247,9 +1257,9 @@ class LAQConfig(QuantizeAlgorithmConfig): quantize_pre_scale: bool = ModeloptField( default=True, - title="FP8-quantize the LAQ pre-quantization scale.", + title="FP8-quantize the LSQ pre-quantization scale.", description=( - "If False, LAQ uses the raw pre-quantization scale while keeping post-scale " + "If False, LSQ uses the raw pre-quantization scale while keeping post-scale " "quantization controlled by the quantizer's block-scale settings." ), ) diff --git a/modelopt/torch/quantization/mode.py b/modelopt/torch/quantization/mode.py index 718492cc8cf..80be73daa2a 100644 --- a/modelopt/torch/quantization/mode.py +++ b/modelopt/torch/quantization/mode.py @@ -38,8 +38,8 @@ AWQLiteCalibConfig, CompressConfig, GPTQCalibConfig, - LAQConfig, LocalHessianCalibConfig, + LSQConfig, MaxCalibConfig, MseCalibConfig, QuantizeAlgoCfgType, @@ -61,9 +61,9 @@ from .model_calib import ( awq, gptq, - laq, layerwise_calibrate, local_hessian_calibrate, + lsq, max_calibrate, mse_calibrate, smoothquant, @@ -536,12 +536,12 @@ def config_class(self) -> type[QuantizeAlgorithmConfig]: @CalibrateModeRegistry.register_mode -class LAQModeDescriptor(BaseCalibrateModeDescriptor): - """Mode for LAQ (Learnt Amax Quantization) algorithm.""" +class LSQModeDescriptor(BaseCalibrateModeDescriptor): + """Mode for LSQ (Learned Scale Quantization) algorithm.""" @property def config_class(self) -> type[QuantizeAlgorithmConfig]: """Specifies the config class for the mode.""" - return LAQConfig + return LSQConfig - _calib_func = laq + _calib_func = lsq diff --git a/modelopt/torch/quantization/model_calib.py b/modelopt/torch/quantization/model_calib.py index 8d65900db9a..26e9b7d3280 100644 --- a/modelopt/torch/quantization/model_calib.py +++ b/modelopt/torch/quantization/model_calib.py @@ -71,9 +71,9 @@ __all__ = [ "CalibratorFactory", "awq", - "laq", "layerwise_calibrate", "local_hessian_calibrate", + "lsq", "max_calibrate", "smoothquant", "svdquant", @@ -2173,15 +2173,15 @@ def _iter_weight_quantizers(model): break -def _compute_laq_params(quantizer): - """Compute amax and scale-quantization params for LAQ.""" +def _compute_lsq_params(quantizer): + """Compute amax and scale-quantization params for LSQ.""" per_block_scale, per_tensor_scale, quantize_scales = _compute_block_scales(quantizer) amax = per_block_scale * quantizer._quant_max_bound return amax, per_tensor_scale, quantize_scales @torch.no_grad() -def laq( +def lsq( model: nn.Module, forward_loop: ForwardLoop | None = None, scale_algorithm: dict | None = None, @@ -2190,7 +2190,7 @@ def laq( quantize_pre_scale: bool = True, **kwargs, ): - """Run scale calibration then convert to LAQ mode. + """Run scale calibration then convert to LSQ mode. Uses separate pre (quant) and post (dequant) amax values. Forward: ``w_q = Q_STE(w / s_pre) * s_post`` where ``s = amax / Q_max``. @@ -2204,17 +2204,17 @@ def laq( learnable_amax: Which amax params are learnable: 'pre', 'post', ['pre', 'post'], or []. tied_amax: If True, pre and post share a single tensor. - quantize_pre_scale: If False, skip FP8 quantization for the LAQ pre scale. + quantize_pre_scale: If False, skip FP8 quantization for the LSQ pre scale. """ - _run_scale_calibration(model, forward_loop, scale_algorithm, "laq") + _run_scale_calibration(model, forward_loop, scale_algorithm, "lsq") for module, weight_name, quantizer in _iter_weight_quantizers(model): - amax, per_tensor_scale, quantize_scales = _compute_laq_params(quantizer) + amax, per_tensor_scale, quantize_scales = _compute_lsq_params(quantizer) weight_dtype = getattr(module, weight_name).dtype amax = amax.to(weight_dtype) if per_tensor_scale is not None: per_tensor_scale = per_tensor_scale.to(weight_dtype) - quantizer.enable_laq( + quantizer.enable_lsq( amax, per_tensor_scale, quantize_scales, diff --git a/modelopt/torch/quantization/nn/modules/tensor_quantizer.py b/modelopt/torch/quantization/nn/modules/tensor_quantizer.py index 5658df88172..2a8a798283c 100644 --- a/modelopt/torch/quantization/nn/modules/tensor_quantizer.py +++ b/modelopt/torch/quantization/nn/modules/tensor_quantizer.py @@ -1476,9 +1476,10 @@ class StaticBlockScaleQuantizer(TensorQuantizer): Preserves static amax states in fp32. """ - _laq: bool = False + _lsq: bool = False _learnable_amax: list = [] _tied_amax: bool = False + # FP4 default; overwritten on promotion with the format-specific bound, including INT. _quant_max_bound: float = 6.0 _quantize_scales: bool = True _quantize_pre_scale: bool = True @@ -1544,13 +1545,13 @@ def amax_post(self): @property def amax(self): - """Return amax, derived from learnable amax parameters if in LAQ mode.""" - if self._laq and not self._tied_amax: + """Return amax, derived from learnable amax parameters if in LSQ mode.""" + if self._lsq and not self._tied_amax: raise RuntimeError( - "LAQ with untied amaxes has separate pre and post parameters. " + "LSQ with untied amaxes has separate pre and post parameters. " "Access them via amax_pre / amax_post." ) - if self._laq: + if self._lsq: return self._amax_post if not hasattr(self, "_amax"): return None @@ -1601,19 +1602,19 @@ def _apply(self, fn, recurse=True): return module def _short_amax(self, fmt=".4f"): - """Short description of amax, accounting for LAQ mode.""" - if not self._laq: + """Short description of amax, accounting for LSQ mode.""" + if not self._lsq: return super()._short_amax(fmt) learn = self._learnable_amax learn_str = "frozen" if not learn else f"learn=[{','.join(learn)}]" if self._tied_amax: - return f"LAQ(tied={self._short_tensor(self._amax_post.data, fmt)}, {learn_str})" + return f"LSQ(tied={self._short_tensor(self._amax_post.data, fmt)}, {learn_str})" return ( - f"LAQ(pre={self._short_tensor(self._amax_pre.data, fmt)}, " + f"LSQ(pre={self._short_tensor(self._amax_pre.data, fmt)}, " f"post={self._short_tensor(self._amax_post.data, fmt)}, {learn_str})" ) - def enable_laq( + def enable_lsq( self, amax: torch.Tensor, per_tensor_scale: torch.Tensor = None, @@ -1622,16 +1623,16 @@ def enable_laq( tied_amax: bool = False, quantize_pre_scale: bool = True, ): - """LAQ mode with configurable learnable/frozen amax tensors. + """LSQ mode with configurable learnable/frozen amax tensors. Args: amax: Initial amax values (per-block). per_tensor_scale: Optional per-tensor scale (frozen buffer). - quantize_scales: Whether to FP8-quantize per-block scales. + quantize_scales: Whether to FP8-quantize per-block scales. Used for NVFP4 quantization. learnable_amax: Which amax params are learnable: 'pre', 'post', ['pre', 'post'], or []. tied_amax: If True, pre and post share a single tensor. - quantize_pre_scale: Whether to FP8-quantize the LAQ pre scale. + quantize_pre_scale: Whether to FP8-quantize the LSQ pre scale. """ if hasattr(self, "_amax"): delattr(self, "_amax") @@ -1659,7 +1660,7 @@ def enable_laq( self.register_buffer("_per_tensor_scale", per_tensor_scale.clone().detach()) self._quantize_scales = quantize_scales self._quantize_pre_scale = quantize_pre_scale - self._laq = True + self._lsq = True self._learnable_amax = sorted(learn) self._tied_amax = tied_amax @@ -1677,7 +1678,7 @@ def _maybe_quantize_scale(self, scale_raw): def _fake_quantize(self, inputs): """Fake quantization using two-level scaling with _amax and _global_amax.""" - if self._laq: + if self._lsq: scale_min_post = ( _FP8_E4M3_MIN_POSITIVE * self._per_tensor_scale.view(-1) if self._quantize_scales @@ -1701,7 +1702,7 @@ def _fake_quantize(self, inputs): self._quant_max_bound, min_value=scale_min_pre, ) - if self._quantize_pre_scale: + if self._quantize_scales and self._quantize_pre_scale: scale_pre = self._maybe_quantize_scale(scale_pre) quant_input = inputs.float() / scale_pre.float().view(-1, 1) w_cast = self._cast_ste(quant_input) diff --git a/modelopt/torch/quantization/plugins/transformers_trainer.py b/modelopt/torch/quantization/plugins/transformers_trainer.py index 162b464d15e..00ea9626c3c 100644 --- a/modelopt/torch/quantization/plugins/transformers_trainer.py +++ b/modelopt/torch/quantization/plugins/transformers_trainer.py @@ -103,10 +103,10 @@ def resolve_quant_cfg_from_args( recipe_path = getattr(quant_args, "recipe", None) if recipe_path: - from modelopt.recipe import ModelOptPTQRecipe, load_recipe + from modelopt.recipe import ModelOptQuantizeRecipe, load_recipe recipe = load_recipe(recipe_path) - if not isinstance(recipe, ModelOptPTQRecipe): + if not isinstance(recipe, ModelOptQuantizeRecipe): raise ValueError( f"Expected PTQ recipe, but got {type(recipe).__name__} from {recipe_path}" ) @@ -171,10 +171,12 @@ def _patched_post_backward(self): FSDPParamGroup.post_backward = _patched_post_backward -def _align_laq_amax_param_dtypes(model): - """Cast LAQ learnable amax params to their owning weight dtype for FSDP2.""" - # TODO: Remove this once a stable PyTorch release supports FSDP2 mixed - # precision parameter dtypes for this case. +def _align_lsq_amax_param_dtypes(model): + """Cast LSQ learnable amax params to their owning weight dtype for FSDP2.""" + # FSDP2 currently requires all parameters in a module to use the same dtype, + # so align the LSQ amax parameters with their owning weights. + # TODO: Remove this once a stable PyTorch release supports mixed-dtype + # parameters within an FSDP2 module. for module in model.modules(): for weight_name in weight_attr_names(module): weight = getattr(module, weight_name, None) @@ -183,7 +185,7 @@ def _align_laq_amax_param_dtypes(model): quantizer_name = quantizer_attr_names(weight_name).weight_quantizer quantizer = getattr(module, quantizer_name, None) - if not isinstance(quantizer, TensorQuantizer) or not getattr(quantizer, "_laq", False): + if not isinstance(quantizer, TensorQuantizer) or not getattr(quantizer, "_lsq", False): continue for amax_name in ("_amax_pre", "_amax_post"): @@ -395,7 +397,7 @@ def _modelopt_prepare(self, *args, **kwargs): if model is None: return self._original_prepare(*args, **kwargs) - _align_laq_amax_param_dtypes(model) + _align_lsq_amax_param_dtypes(model) # Hide TQ buffers from accelerate's FSDP2 state_dict handling. tq_og_non_prsist_buffers = {} diff --git a/modelopt/torch/quantization/tensor_quant.py b/modelopt/torch/quantization/tensor_quant.py index 4c220ac4d8c..20e083491aa 100644 --- a/modelopt/torch/quantization/tensor_quant.py +++ b/modelopt/torch/quantization/tensor_quant.py @@ -649,26 +649,24 @@ class FP4CastSTEFunction(Function): """FP4 cast with STE backward -- no scale/descale, just rounding.""" @staticmethod - def forward(ctx, x, out_dtype=None, rounding="rne"): + def forward(ctx, x, out_dtype=None): """Forward pass: cast to FP4 using triton kernel. Args: x: Input tensor of shape [NUM_BLOCKS, BLOCK_SIZE]. out_dtype: Output dtype. Defaults to x.dtype. - rounding: Rounding mode -- ``"rne"`` (round to nearest even, default) - or ``"down"`` (floor toward zero). """ if not triton_kernel.IS_AVAILABLE: raise RuntimeError("FP4CastSTEFunction requires triton.") ctx.save_for_backward(x) - return triton_kernel.static_blockwise_fp4_cast(x, out_dtype, rounding=rounding) + return triton_kernel.static_blockwise_fp4_cast(x, out_dtype) @staticmethod def backward(ctx, grad_outputs): - """Backward pass: STE with clip mask at |x| <= 6.0.""" + """Backward pass: STE with clip mask at ``|x| <= 6.0``.""" (x,) = ctx.saved_tensors grad = torch.where(x.abs() <= 6.0, grad_outputs, torch.zeros_like(grad_outputs)) - return grad, None, None + return grad, None class IntCastSTEFunction(Function): diff --git a/modelopt_recipes/general/ptq/nvfp4_default-kv_fp8.yaml b/modelopt_recipes/general/ptq/nvfp4_default-kv_fp8.yaml index 6a65efef57a..5a83d2bdc86 100644 --- a/modelopt_recipes/general/ptq/nvfp4_default-kv_fp8.yaml +++ b/modelopt_recipes/general/ptq/nvfp4_default-kv_fp8.yaml @@ -22,10 +22,10 @@ imports: kv_fp8: configs/ptq/units/kv_fp8 metadata: - recipe_type: ptq + recipe_type: ptq/qat/qad description: >- - Composes dynamic NVFP4 W4A4 model quantization with FP8 KV-cache quantization; uses max - calibration. + Composes dynamic NVFP4 W4A4 model quantization with FP8 KV-cache quantization for PTQ, + QAT, and QAD; uses max calibration. quantize: algorithm: max quant_cfg: diff --git a/modelopt_recipes/general/qad/nvfp4_default-kv_fp8.yaml b/modelopt_recipes/general/qad/nvfp4_default-kv_fp8.yaml new file mode 120000 index 00000000000..97cca50092a --- /dev/null +++ b/modelopt_recipes/general/qad/nvfp4_default-kv_fp8.yaml @@ -0,0 +1 @@ +../ptq/nvfp4_default-kv_fp8.yaml \ No newline at end of file diff --git a/examples/llm_qat/configs/quantize/nvfp4_laq_pre_post-mse_init-fp8_kv.yml b/modelopt_recipes/general/qad/nvfp4_dual_lsq-mse_init-fp8_kv.yaml similarity index 54% rename from examples/llm_qat/configs/quantize/nvfp4_laq_pre_post-mse_init-fp8_kv.yml rename to modelopt_recipes/general/qad/nvfp4_dual_lsq-mse_init-fp8_kv.yaml index 7f2bee8d335..772f24f0fc7 100644 --- a/examples/llm_qat/configs/quantize/nvfp4_laq_pre_post-mse_init-fp8_kv.yml +++ b/modelopt_recipes/general/qad/nvfp4_dual_lsq-mse_init-fp8_kv.yaml @@ -14,41 +14,36 @@ # limitations under the License. metadata: - recipe_type: ptq - description: NVFP4 LAQ pre+post learnable amax (W4A16), MSE init with FP8 scale sweep, FP8 KV cache. + recipe_type: qat/qad + description: >- + Learns separate pre-quantization and post-quantization NVFP4 weight scales with MSE + initialization and FP8 scale sweep; uses dynamic NVFP4 activations and FP8 KV cache. + QAT/QAD-only: the LSQ scales are learned during training, so this recipe is not + suitable for calibration-only PTQ. +imports: + base_disable_all: configs/ptq/units/base_disable_all + default_disabled_quantizers: configs/ptq/units/default_disabled_quantizers + kv_fp8: configs/ptq/units/kv_fp8 + nvfp4: configs/numerics/nvfp4 + nvfp4_static: configs/numerics/nvfp4_static quantize: algorithm: - method: laq + method: lsq learnable_amax: - pre - post tied_amax: false + quantize_pre_scale: false scale_algorithm: method: mse fp8_scale_sweep: true quant_cfg: - - quantizer_name: '*' - enable: false + - $import: base_disable_all - quantizer_name: '*weight_quantizer' - enable: true cfg: - block_sizes: - -1: 16 - type: static - scale_bits: e4m3 - num_bits: e2m1 + $import: nvfp4_static - quantizer_name: '*input_quantizer' - enable: true cfg: - block_sizes: - -1: 16 - type: dynamic - scale_bits: e4m3 - num_bits: e2m1 - - quantizer_name: '*[kv]_bmm_quantizer' - enable: true - cfg: - num_bits: e4m3 - axis: - - quantizer_name: '*lm_head*' - enable: false + $import: nvfp4 + - $import: kv_fp8 + - $import: default_disabled_quantizers diff --git a/examples/llm_qat/configs/quantize/nvfp4_laq_pre_post_tied-mse_init-fp8_kv.yml b/modelopt_recipes/general/qad/nvfp4_lsq-mse_init-fp8_kv.yaml similarity index 54% rename from examples/llm_qat/configs/quantize/nvfp4_laq_pre_post_tied-mse_init-fp8_kv.yml rename to modelopt_recipes/general/qad/nvfp4_lsq-mse_init-fp8_kv.yaml index 01a2c1dac80..9f422a229fa 100644 --- a/examples/llm_qat/configs/quantize/nvfp4_laq_pre_post_tied-mse_init-fp8_kv.yml +++ b/modelopt_recipes/general/qad/nvfp4_lsq-mse_init-fp8_kv.yaml @@ -14,41 +14,36 @@ # limitations under the License. metadata: - recipe_type: ptq - description: NVFP4 LAQ pre+post tied learnable amax (W4A16), MSE init with FP8 scale sweep, FP8 KV cache. + recipe_type: qat/qad + description: >- + Learns one shared pre-quantization and post-quantization NVFP4 weight scale with MSE + initialization and FP8 scale sweep; uses dynamic NVFP4 activations and FP8 KV cache. + QAT/QAD-only: the LSQ scales are learned during training, so this recipe is not + suitable for calibration-only PTQ. +imports: + base_disable_all: configs/ptq/units/base_disable_all + default_disabled_quantizers: configs/ptq/units/default_disabled_quantizers + kv_fp8: configs/ptq/units/kv_fp8 + nvfp4: configs/numerics/nvfp4 + nvfp4_static: configs/numerics/nvfp4_static quantize: algorithm: - method: laq + method: lsq learnable_amax: - pre - post tied_amax: true + quantize_pre_scale: true scale_algorithm: method: mse fp8_scale_sweep: true quant_cfg: - - quantizer_name: '*' - enable: false + - $import: base_disable_all - quantizer_name: '*weight_quantizer' - enable: true cfg: - block_sizes: - -1: 16 - type: static - scale_bits: e4m3 - num_bits: e2m1 + $import: nvfp4_static - quantizer_name: '*input_quantizer' - enable: true cfg: - block_sizes: - -1: 16 - type: dynamic - scale_bits: e4m3 - num_bits: e2m1 - - quantizer_name: '*[kv]_bmm_quantizer' - enable: true - cfg: - num_bits: e4m3 - axis: - - quantizer_name: '*lm_head*' - enable: false + $import: nvfp4 + - $import: kv_fp8 + - $import: default_disabled_quantizers diff --git a/tests/gpu/torch/quantization/test_fsdp2.py b/tests/gpu/torch/quantization/test_fsdp2.py index 21c6a87ec2d..6f8ab6e292b 100644 --- a/tests/gpu/torch/quantization/test_fsdp2.py +++ b/tests/gpu/torch/quantization/test_fsdp2.py @@ -137,8 +137,8 @@ def test_nested_fsdp2_backward(quant_cfg, dist_workers): dist_workers.run(partial(_test_nested_fsdp2_backward, quant_cfg=quant_cfg)) -class _LAQBf16Linear(nn.Module): - """Minimal bf16 module with LAQ learnable amax parameters.""" +class _LSQBf16Linear(nn.Module): + """Minimal bf16 module with LSQ learnable amax parameters.""" def __init__(self, dim=16): super().__init__() @@ -153,7 +153,7 @@ def __init__(self, dim=16): tq._pass_through_bwd = True tq.register_buffer("_amax", torch.ones(dim, dtype=torch.bfloat16)) self.weight_quantizer = StaticBlockScaleQuantizer.from_tensor_quantizer(tq) - self.weight_quantizer.enable_laq( + self.weight_quantizer.enable_lsq( torch.ones(dim, dtype=torch.bfloat16), quantize_scales=False, learnable_amax=["pre", "post"], @@ -164,9 +164,9 @@ def forward(self, inputs): return torch.nn.functional.linear(inputs, weight) -def _test_laq_bf16_learnable_amax_fsdp2(rank, size): +def _test_lsq_bf16_learnable_amax_fsdp2(rank, size): torch.manual_seed(1) - model = _LAQBf16Linear().cuda(rank) + model = _LSQBf16Linear().cuda(rank) inputs = torch.randn(2, 16, device=rank, dtype=torch.bfloat16) synchronize_state_dict(model) @@ -177,8 +177,8 @@ def _test_laq_bf16_learnable_amax_fsdp2(rank, size): output.float().sum().backward() -def test_laq_bf16_learnable_amax_fsdp2(dist_workers): - dist_workers.run(_test_laq_bf16_learnable_amax_fsdp2) +def test_lsq_bf16_learnable_amax_fsdp2(dist_workers): + dist_workers.run(_test_lsq_bf16_learnable_amax_fsdp2) class _DecoderBlock(nn.Module): diff --git a/tests/gpu/torch/quantization/test_laq_cuda.py b/tests/gpu/torch/quantization/test_lsq_cuda.py similarity index 87% rename from tests/gpu/torch/quantization/test_laq_cuda.py rename to tests/gpu/torch/quantization/test_lsq_cuda.py index 23a04b56a14..7d2a686be93 100644 --- a/tests/gpu/torch/quantization/test_laq_cuda.py +++ b/tests/gpu/torch/quantization/test_lsq_cuda.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""GPU unit tests for the LAQ algorithm using FP4 (NVFP4) quantization.""" +"""GPU unit tests for the LSQ algorithm using FP4 (NVFP4) quantization.""" import pytest import torch @@ -21,7 +21,7 @@ import modelopt.torch.quantization as mtq -NVFP4_LAQ_POST_MSE_CFG = { +NVFP4_LSQ_POST_MSE_CFG = { "quant_cfg": { "*weight_quantizer": { "num_bits": (2, 1), @@ -34,13 +34,13 @@ }, }, "algorithm": { - "method": "laq", + "method": "lsq", "learnable_amax": ["post"], "scale_algorithm": {"method": "mse", "fp8_scale_sweep": True}, }, } -NVFP4_LAQ_PRE_POST_MSE_CFG = { +NVFP4_LSQ_PRE_POST_MSE_CFG = { "quant_cfg": { "*weight_quantizer": { "num_bits": (2, 1), @@ -53,13 +53,13 @@ }, }, "algorithm": { - "method": "laq", + "method": "lsq", "learnable_amax": ["pre", "post"], "scale_algorithm": {"method": "mse", "fp8_scale_sweep": True}, }, } -NVFP4_LAQ_TIED_MSE_CFG = { +NVFP4_LSQ_TIED_MSE_CFG = { "quant_cfg": { "*weight_quantizer": { "num_bits": (2, 1), @@ -72,14 +72,14 @@ }, }, "algorithm": { - "method": "laq", + "method": "lsq", "learnable_amax": ["pre", "post"], "tied_amax": True, "scale_algorithm": {"method": "mse", "fp8_scale_sweep": True}, }, } -NVFP4_LAQ_SKIP_PRE_SCALE_MSE_CFG = { +NVFP4_LSQ_SKIP_PRE_SCALE_MSE_CFG = { "quant_cfg": { "*weight_quantizer": { "num_bits": (2, 1), @@ -92,7 +92,7 @@ }, }, "algorithm": { - "method": "laq", + "method": "lsq", "learnable_amax": ["post"], "quantize_pre_scale": False, "scale_algorithm": {"method": "mse", "fp8_scale_sweep": True}, @@ -101,7 +101,7 @@ class SimpleModel(nn.Module): - """Minimal model for LAQ testing.""" + """Minimal model for LSQ testing.""" def __init__(self): super().__init__() @@ -123,15 +123,15 @@ def forward_loop(m): @pytest.mark.parametrize( "config", [ - NVFP4_LAQ_POST_MSE_CFG, - NVFP4_LAQ_PRE_POST_MSE_CFG, - NVFP4_LAQ_TIED_MSE_CFG, - NVFP4_LAQ_SKIP_PRE_SCALE_MSE_CFG, + NVFP4_LSQ_POST_MSE_CFG, + NVFP4_LSQ_PRE_POST_MSE_CFG, + NVFP4_LSQ_TIED_MSE_CFG, + NVFP4_LSQ_SKIP_PRE_SCALE_MSE_CFG, ], ids=["post_only", "pre_and_post", "tied", "skip_pre_scale"], ) -def test_laq_quantize_e2e(config): - """End-to-end: quantize a small model with LAQ + NVFP4 on GPU.""" +def test_lsq_quantize_e2e(config): + """End-to-end: quantize a small model with LSQ + NVFP4 on GPU.""" device = torch.device("cuda") model = SimpleModel().to(device) forward_loop = _make_forward_loop(model, device) @@ -147,8 +147,8 @@ def test_laq_quantize_e2e(config): assert out.shape == (2, 64) -def test_laq_fp4_fake_quantize_differentiable(): - """Test that _fake_quantize in FP4 LAQ mode is differentiable.""" +def test_lsq_fp4_fake_quantize_differentiable(): + """Test that _fake_quantize in FP4 LSQ mode is differentiable.""" from modelopt.torch.quantization.nn.modules.tensor_quantizer import ( StaticBlockScaleQuantizer, TensorQuantizer, @@ -170,7 +170,7 @@ def test_laq_fp4_fake_quantize_differentiable(): amax = torch.ones(4, device=device) * 3.0 per_tensor_scale = torch.tensor(1.0 / 6.0, device=device) - sbsq.enable_laq( + sbsq.enable_lsq( amax, per_tensor_scale=per_tensor_scale, quantize_scales=True, @@ -184,7 +184,7 @@ def test_laq_fp4_fake_quantize_differentiable(): assert sbsq._amax_post.grad is not None -def test_laq_fp4_cast_ste(): +def test_lsq_fp4_cast_ste(): """Test fp4_cast_ste on GPU.""" from modelopt.torch.quantization.tensor_quant import fp4_cast_ste diff --git a/tests/unit/recipe/test_laq_recipes.py b/tests/unit/recipe/test_laq_recipes.py deleted file mode 100644 index e6d4be4b1f5..00000000000 --- a/tests/unit/recipe/test_laq_recipes.py +++ /dev/null @@ -1,125 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024 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. - -"""Unit tests for LAQ PTQ recipe YAML files in configs/quantize/.""" - -from pathlib import Path - -import pytest -import yaml - -CONFIGS_DIR = Path(__file__).resolve().parents[3] / "examples" / "llm_qat" / "configs" / "quantize" - -# (filename, expected learnable_amax, expected tied_amax) -_LAQ_RECIPES = [ - ("nvfp4_laq_post-mse_init-fp8_kv.yml", ["post"], False), - ("nvfp4_laq_pre-mse_init-fp8_kv.yml", ["pre"], False), - ("nvfp4_laq_pre_post-mse_init-fp8_kv.yml", ["pre", "post"], False), - ("nvfp4_laq_pre_post_tied-mse_init-fp8_kv.yml", ["pre", "post"], True), - ("nvfp4_laq_frozen-mse_init-fp8_kv.yml", [], False), -] - - -def _load_yaml(filename): - path = CONFIGS_DIR / filename - with open(path) as f: - return yaml.safe_load(f) - - -def _find_entry(quant_cfg, quantizer_name): - """Find entry by quantizer_name in the quant_cfg list.""" - for entry in quant_cfg: - if entry.get("quantizer_name") == quantizer_name: - return entry - raise KeyError(f"No entry with quantizer_name={quantizer_name!r}") - - -# --------------------------------------------------------------------------- -# Parametrized load & parse test -# --------------------------------------------------------------------------- - - -@pytest.mark.parametrize(("filename", "_", "__"), _LAQ_RECIPES, ids=[r[0] for r in _LAQ_RECIPES]) -def test_recipe_loads_and_has_required_sections(filename, _, __): - """Each LAQ recipe YAML is parseable and has metadata + quantize.""" - data = _load_yaml(filename) - assert "metadata" in data - assert data["metadata"]["recipe_type"] == "ptq" - assert "quantize" in data - assert "algorithm" in data["quantize"] - assert "quant_cfg" in data["quantize"] - - -# --------------------------------------------------------------------------- -# Algorithm structure test -# --------------------------------------------------------------------------- - - -@pytest.mark.parametrize( - ("filename", "expected_learnable", "expected_tied"), - _LAQ_RECIPES, - ids=[r[0] for r in _LAQ_RECIPES], -) -def test_algorithm_has_correct_laq_params(filename, expected_learnable, expected_tied): - """Algorithm section has correct method, learnable_amax, tied_amax, and scale_algorithm.""" - algo = _load_yaml(filename)["quantize"]["algorithm"] - assert algo["method"] == "laq" - assert algo["learnable_amax"] == expected_learnable - assert algo["tied_amax"] is expected_tied - assert algo["scale_algorithm"] == {"method": "mse", "fp8_scale_sweep": True} - - -# --------------------------------------------------------------------------- -# Weight quantizer uses static type -# --------------------------------------------------------------------------- - - -@pytest.mark.parametrize(("filename", "_", "__"), _LAQ_RECIPES, ids=[r[0] for r in _LAQ_RECIPES]) -def test_weight_quantizer_is_static(filename, _, __): - """Weight quantizer must use static block type for LAQ learnable scales.""" - qcfg = _load_yaml(filename)["quantize"]["quant_cfg"] - w = _find_entry(qcfg, "*weight_quantizer") - assert w["enable"] is True - assert w["cfg"]["block_sizes"]["type"] == "static" - assert w["cfg"]["num_bits"] == "e2m1" - - -# --------------------------------------------------------------------------- -# Input quantizer uses dynamic type -# --------------------------------------------------------------------------- - - -@pytest.mark.parametrize(("filename", "_", "__"), _LAQ_RECIPES, ids=[r[0] for r in _LAQ_RECIPES]) -def test_input_quantizer_is_dynamic(filename, _, __): - """Input/activation quantizer uses dynamic block type.""" - qcfg = _load_yaml(filename)["quantize"]["quant_cfg"] - inp = _find_entry(qcfg, "*input_quantizer") - assert inp["enable"] is True - assert inp["cfg"]["block_sizes"]["type"] == "dynamic" - assert inp["cfg"]["num_bits"] == "e2m1" - - -# --------------------------------------------------------------------------- -# KV cache quantizer enabled -# --------------------------------------------------------------------------- - - -@pytest.mark.parametrize(("filename", "_", "__"), _LAQ_RECIPES, ids=[r[0] for r in _LAQ_RECIPES]) -def test_kv_cache_quantizer_enabled(filename, _, __): - """FP8 KV cache quantizer is present and enabled.""" - qcfg = _load_yaml(filename)["quantize"]["quant_cfg"] - kv = _find_entry(qcfg, "*[kv]_bmm_quantizer") - assert kv["enable"] is True - assert kv["cfg"]["num_bits"] == "e4m3" diff --git a/tests/unit/recipe/test_loader.py b/tests/unit/recipe/test_loader.py index 3aaacaa3e0e..90ceb1623a6 100644 --- a/tests/unit/recipe/test_loader.py +++ b/tests/unit/recipe/test_loader.py @@ -30,7 +30,7 @@ ModelOptAutoQuantizeRecipe, ModelOptDFlashRecipe, ModelOptEagleRecipe, - ModelOptPTQRecipe, + ModelOptQuantizeRecipe, RecipeType, ) from modelopt.recipe.loader import _apply_dotlist, load_config, load_recipe @@ -138,7 +138,7 @@ def test_load_recipe_builtin_with_suffix(): """load_recipe loads a built-in PTQ recipe given the full YAML path.""" recipe = load_recipe("general/ptq/fp8_default-kv_fp8.yaml") assert recipe.recipe_type == RecipeType.PTQ - assert isinstance(recipe, ModelOptPTQRecipe) + assert isinstance(recipe, ModelOptQuantizeRecipe) assert recipe.quantize @@ -159,7 +159,6 @@ def test_load_recipe_builtin_description(): "general/ptq/fp8_default-kv_fp8", "general/ptq/fp8_default-kv_fp8_cast", "general/ptq/int4_blockwise_weight_only", - "general/ptq/nvfp4_default-kv_fp8", "general/ptq/nvfp4_default-kv_fp8_cast", "general/ptq/nvfp4_default-kv_nvfp4_cast", "general/ptq/nvfp4_default-kv_none-gptq", @@ -181,10 +180,25 @@ def test_load_recipe_all_builtins(recipe_path): """Smoke-test: every built-in PTQ recipe loads without error and has quantize.""" recipe = load_recipe(recipe_path) assert recipe.recipe_type == RecipeType.PTQ - assert isinstance(recipe, ModelOptPTQRecipe) + assert isinstance(recipe, ModelOptQuantizeRecipe) assert recipe.quantize +def test_load_recipe_builtin_shared_across_ptq_qat_qad(): + ptq_recipe = load_recipe("general/ptq/nvfp4_default-kv_fp8") + qad_recipe = load_recipe("general/qad/nvfp4_default-kv_fp8") + + assert ptq_recipe.recipe_type == RecipeType.PTQ_QAT_QAD + assert qad_recipe == ptq_recipe + + +def test_ptq_recipe_deprecated_alias(): + """ModelOptPTQRecipe is a back-compat alias of ModelOptQuantizeRecipe.""" + from modelopt.recipe import ModelOptPTQRecipe, ModelOptQuantizeRecipe + + assert ModelOptPTQRecipe is ModelOptQuantizeRecipe + + def test_nvfp4_weight_only_recipe_disables_vllm_marlin_incompatible_projections(): recipe = load_recipe("general/ptq/nvfp4_weight_only-kv_fp16") disabled_quantizers = { diff --git a/tests/unit/recipe/test_lsq_recipes.py b/tests/unit/recipe/test_lsq_recipes.py new file mode 100644 index 00000000000..52451040004 --- /dev/null +++ b/tests/unit/recipe/test_lsq_recipes.py @@ -0,0 +1,78 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 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. + +"""Unit tests for LSQ QAD recipes.""" + +from pathlib import Path + +import pytest + +from modelopt.recipe.loader import load_recipe + +CONFIGS_DIR = Path(__file__).resolve().parents[3] / "modelopt_recipes" / "general" / "qad" + +# filename: (tied_amax, quantize_pre_scale) +_LSQ_RECIPES = { + "nvfp4_dual_lsq-mse_init-fp8_kv.yaml": (False, False), + "nvfp4_lsq-mse_init-fp8_kv.yaml": (True, True), +} + + +def _load_lsq_recipe(filename): + return load_recipe(CONFIGS_DIR / filename).quantize + + +def test_expected_lsq_recipe_files(): + assert {path.name for path in CONFIGS_DIR.glob("*lsq*")} == set(_LSQ_RECIPES) + + +def test_qad_default_nvfp4_recipe_reuses_ptq_recipe(): + recipe = CONFIGS_DIR / "nvfp4_default-kv_fp8.yaml" + + assert recipe.is_symlink() + assert recipe.resolve() == CONFIGS_DIR.parent / "ptq" / recipe.name + assert load_recipe(recipe).recipe_type.value == "ptq/qat/qad" + + +@pytest.mark.parametrize( + ("filename", "expected_tied", "expected_quantize_pre_scale"), + [(filename, *settings) for filename, settings in _LSQ_RECIPES.items()], +) +def test_lsq_recipe_loads_with_expected_algorithm( + filename, expected_tied, expected_quantize_pre_scale +): + algorithm = _load_lsq_recipe(filename).algorithm + + assert algorithm["method"] == "lsq" + assert algorithm["learnable_amax"] == ["pre", "post"] + assert algorithm["tied_amax"] is expected_tied + assert algorithm["quantize_pre_scale"] is expected_quantize_pre_scale + assert algorithm["scale_algorithm"] == {"method": "mse", "fp8_scale_sweep": True} + + +@pytest.mark.parametrize("filename", _LSQ_RECIPES) +def test_lsq_recipe_resolves_modular_quant_cfg(filename): + quantize = _load_lsq_recipe(filename) + entries = {entry.quantizer_name: entry for entry in quantize.quant_cfg} + + weight_cfg = entries["*weight_quantizer"].cfg.model_dump(exclude_unset=True) + input_cfg = entries["*input_quantizer"].cfg.model_dump(exclude_unset=True) + kv_cfg = entries["*[kv]_bmm_quantizer"].cfg.model_dump(exclude_unset=True) + + assert weight_cfg["block_sizes"]["type"] == "static" + assert weight_cfg["num_bits"] == (2, 1) + assert input_cfg["block_sizes"]["type"] == "dynamic" + assert input_cfg["num_bits"] == (2, 1) + assert kv_cfg["num_bits"] == (4, 3) diff --git a/tests/unit/torch/quantization/test_laq.py b/tests/unit/torch/quantization/test_lsq.py similarity index 83% rename from tests/unit/torch/quantization/test_laq.py rename to tests/unit/torch/quantization/test_lsq.py index 0a4819a596c..8e75bbf26e7 100644 --- a/tests/unit/torch/quantization/test_laq.py +++ b/tests/unit/torch/quantization/test_lsq.py @@ -13,28 +13,27 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""CPU unit tests for the LAQ algorithm using INT4 quantization.""" +"""CPU unit tests for the LSQ algorithm using INT4 quantization.""" import pytest import torch from torch import nn -from modelopt.torch.quantization.config import LAQConfig +from modelopt.torch.quantization.config import LSQConfig from modelopt.torch.quantization.nn.modules.tensor_quantizer import ( _FP8_E4M3_MIN_POSITIVE, StaticBlockScaleQuantizer, TensorQuantizer, ) -from modelopt.torch.quantization.plugins.transformers_trainer import _align_laq_amax_param_dtypes from modelopt.torch.quantization.tensor_quant import int_cast_ste -class TestLAQConfig: - """Tests for LAQConfig validation.""" +class TestLSQConfig: + """Tests for LSQConfig validation.""" def test_default_config(self): - cfg = LAQConfig() - assert cfg.method == "laq" + cfg = LSQConfig() + assert cfg.method == "lsq" assert cfg.learnable_amax == ["post"] assert cfg.tied_amax is False assert cfg.quantize_pre_scale is True @@ -54,7 +53,7 @@ def test_default_config(self): ], ) def test_valid_combinations(self, learnable_amax, tied_amax): - cfg = LAQConfig(learnable_amax=learnable_amax, tied_amax=tied_amax) + cfg = LSQConfig(learnable_amax=learnable_amax, tied_amax=tied_amax) assert cfg.tied_amax is tied_amax @pytest.mark.parametrize( @@ -63,11 +62,11 @@ def test_valid_combinations(self, learnable_amax, tied_amax): ) def test_invalid_tied_with_single_learnable(self, learnable_amax): with pytest.raises(ValueError, match="tied_amax=True requires"): - LAQConfig(learnable_amax=learnable_amax, tied_amax=True) + LSQConfig(learnable_amax=learnable_amax, tied_amax=True) -class TestEnableLAQ: - """Tests for StaticBlockScaleQuantizer.enable_laq() with INT4 format.""" +class TestEnableLSQ: + """Tests for StaticBlockScaleQuantizer.enable_lsq() with INT4 format.""" def _make_quantizer(self): """Create a StaticBlockScaleQuantizer configured for INT4.""" @@ -86,8 +85,8 @@ def _make_quantizer(self): def test_post_only_learnable(self): q = self._make_quantizer() amax = torch.ones(8) * 3.0 - q.enable_laq(amax, quantize_scales=False, learnable_amax=["post"], tied_amax=False) - assert q._laq is True + q.enable_lsq(amax, quantize_scales=False, learnable_amax=["post"], tied_amax=False) + assert q._lsq is True assert isinstance(q._amax_post, nn.Parameter) assert q._amax_post.requires_grad is True assert not isinstance(q._amax_pre, nn.Parameter) @@ -96,7 +95,7 @@ def test_post_only_learnable(self): def test_pre_only_learnable(self): q = self._make_quantizer() amax = torch.ones(8) * 3.0 - q.enable_laq(amax, quantize_scales=False, learnable_amax=["pre"], tied_amax=False) + q.enable_lsq(amax, quantize_scales=False, learnable_amax=["pre"], tied_amax=False) assert isinstance(q._amax_pre, nn.Parameter) assert q._amax_pre.requires_grad is True assert not isinstance(q._amax_post, nn.Parameter) @@ -104,14 +103,14 @@ def test_pre_only_learnable(self): def test_both_learnable(self): q = self._make_quantizer() amax = torch.ones(8) * 3.0 - q.enable_laq(amax, quantize_scales=False, learnable_amax=["pre", "post"], tied_amax=False) + q.enable_lsq(amax, quantize_scales=False, learnable_amax=["pre", "post"], tied_amax=False) assert isinstance(q._amax_pre, nn.Parameter) assert isinstance(q._amax_post, nn.Parameter) def test_tied_both_learnable(self): q = self._make_quantizer() amax = torch.ones(8) * 3.0 - q.enable_laq(amax, quantize_scales=False, learnable_amax=["pre", "post"], tied_amax=True) + q.enable_lsq(amax, quantize_scales=False, learnable_amax=["pre", "post"], tied_amax=True) assert q._tied_amax is True assert isinstance(q._amax_post, nn.Parameter) assert not hasattr(q, "_amax_pre") @@ -120,19 +119,19 @@ def test_tied_both_learnable(self): def test_frozen(self): q = self._make_quantizer() amax = torch.ones(8) * 3.0 - q.enable_laq(amax, quantize_scales=False, learnable_amax=[], tied_amax=False) + q.enable_lsq(amax, quantize_scales=False, learnable_amax=[], tied_amax=False) assert not isinstance(q._amax_post, nn.Parameter) assert not isinstance(q._amax_pre, nn.Parameter) def test_old_amax_deleted(self): q = self._make_quantizer() assert hasattr(q, "_amax") - q.enable_laq(torch.ones(8), quantize_scales=False) + q.enable_lsq(torch.ones(8), quantize_scales=False) assert not hasattr(q, "_amax") def test_can_skip_pre_scale_quantization(self): q = self._make_quantizer() - q.enable_laq( + q.enable_lsq( torch.ones(8), quantize_scales=False, quantize_pre_scale=False, @@ -142,7 +141,7 @@ def test_can_skip_pre_scale_quantization(self): @pytest.mark.parametrize("dtype", [torch.float16, torch.bfloat16]) def test_learnable_amax_uses_input_dtype(self, dtype): q = self._make_quantizer() - q.enable_laq( + q.enable_lsq( torch.ones(8, dtype=dtype), quantize_scales=False, learnable_amax=["pre", "post"], @@ -153,7 +152,7 @@ def test_learnable_amax_uses_input_dtype(self, dtype): def test_dtype_cast_updates_learnable_amax_dtype(self): q = self._make_quantizer() - q.enable_laq( + q.enable_lsq( torch.ones(8), quantize_scales=False, learnable_amax=["pre", "post"], @@ -164,11 +163,16 @@ def test_dtype_cast_updates_learnable_amax_dtype(self): assert q._amax_pre.dtype == torch.bfloat16 assert q._amax_post.dtype == torch.bfloat16 - def test_align_laq_amax_param_dtypes_uses_weight_dtype(self): + def test_align_lsq_amax_param_dtypes_uses_weight_dtype(self): + pytest.importorskip("transformers") + from modelopt.torch.quantization.plugins.transformers_trainer import ( + _align_lsq_amax_param_dtypes, + ) + module = nn.Module() module.weight = nn.Parameter(torch.ones(8, 16, dtype=torch.bfloat16)) module.weight_quantizer = self._make_quantizer() - module.weight_quantizer.enable_laq( + module.weight_quantizer.enable_lsq( torch.ones(8), quantize_scales=False, learnable_amax=["pre", "post"], @@ -177,7 +181,7 @@ def test_align_laq_amax_param_dtypes_uses_weight_dtype(self): assert module.weight_quantizer._amax_pre.dtype == torch.float32 assert module.weight_quantizer._amax_post.dtype == torch.float32 - _align_laq_amax_param_dtypes(module) + _align_lsq_amax_param_dtypes(module) assert module.weight_quantizer._amax_pre.dtype == torch.bfloat16 assert module.weight_quantizer._amax_post.dtype == torch.bfloat16 @@ -203,10 +207,10 @@ def test_ste_gradient(self): assert torch.all(x.grad == 1.0) -class TestFakeQuantizeLAQ: - """Tests for _fake_quantize() LAQ path with INT4.""" +class TestFakeQuantizeLSQ: + """Tests for _fake_quantize() LSQ path with INT4.""" - def _make_laq_quantizer(self, learnable_amax=("post",), tied_amax=False): + def _make_lsq_quantizer(self, learnable_amax=("post",), tied_amax=False): tq = TensorQuantizer() tq._num_bits = 4 tq._unsigned = False @@ -217,19 +221,19 @@ def _make_laq_quantizer(self, learnable_amax=("post",), tied_amax=False): tq.register_buffer("_amax", torch.ones(4)) sbsq = StaticBlockScaleQuantizer.from_tensor_quantizer(tq) amax = torch.ones(4) * 3.5 - sbsq.enable_laq( + sbsq.enable_lsq( amax, quantize_scales=False, learnable_amax=learnable_amax, tied_amax=tied_amax ) return sbsq def test_output_shape(self): - q = self._make_laq_quantizer() + q = self._make_lsq_quantizer() x = torch.randn(4, 16) out = q._fake_quantize(x) assert out.shape == x.shape def test_differentiable_post(self): - q = self._make_laq_quantizer(learnable_amax=["post"]) + q = self._make_lsq_quantizer(learnable_amax=["post"]) x = torch.randn(4, 16) out = q._fake_quantize(x) out.sum().backward() @@ -237,7 +241,7 @@ def test_differentiable_post(self): assert q._amax_pre.grad is None def test_differentiable_pre(self): - q = self._make_laq_quantizer(learnable_amax=["pre"]) + q = self._make_lsq_quantizer(learnable_amax=["pre"]) x = torch.randn(4, 16) out = q._fake_quantize(x) out.sum().backward() @@ -245,7 +249,7 @@ def test_differentiable_pre(self): assert q._amax_post.grad is None def test_differentiable_both(self): - q = self._make_laq_quantizer(learnable_amax=["pre", "post"]) + q = self._make_lsq_quantizer(learnable_amax=["pre", "post"]) x = torch.randn(4, 16) out = q._fake_quantize(x) out.sum().backward() @@ -253,14 +257,14 @@ def test_differentiable_both(self): assert q._amax_post.grad is not None def test_tied_shares_tensor(self): - q = self._make_laq_quantizer(learnable_amax=["pre", "post"], tied_amax=True) + q = self._make_lsq_quantizer(learnable_amax=["pre", "post"], tied_amax=True) x = torch.randn(4, 16) out = q._fake_quantize(x) out.sum().backward() assert q._amax_post.grad is not None def test_skip_pre_scale_quantization_still_quantizes_post(self, monkeypatch): - q = self._make_laq_quantizer() + q = self._make_lsq_quantizer() q._quantize_scales = True q._quantize_pre_scale = False q.register_buffer("_per_tensor_scale", torch.tensor(1.0)) @@ -278,7 +282,7 @@ def spy_maybe_quantize_scale(scale_raw): assert len(calls) == 1 def test_skip_pre_scale_quantization_uses_raw_scale_floor(self, monkeypatch): - q = self._make_laq_quantizer() + q = self._make_lsq_quantizer() q._quantize_scales = True q._quantize_pre_scale = False q.register_buffer("_per_tensor_scale", torch.tensor(1.0)) From 62508375707486c47ad11d67beccfa44cdedeb3c Mon Sep 17 00:00:00 2001 From: realAsma Date: Tue, 7 Jul 2026 19:46:44 +0000 Subject: [PATCH 03/19] Document LSQ amax learning rate Signed-off-by: realAsma --- examples/llm_qat/configs/train/qad_with_learnt_amax.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/llm_qat/configs/train/qad_with_learnt_amax.yaml b/examples/llm_qat/configs/train/qad_with_learnt_amax.yaml index 76352defa43..1923849f588 100644 --- a/examples/llm_qat/configs/train/qad_with_learnt_amax.yaml +++ b/examples/llm_qat/configs/train/qad_with_learnt_amax.yaml @@ -17,6 +17,7 @@ eval_samples: 2000 # Hyperparameters num_train_epochs: 1.0 learning_rate: 1e-5 +# Learnable LSQ amax may need a higher learning rate than quantized weights. lr_config: configs/train/lr/lr_config_amax.yaml per_device_train_batch_size: 2 per_device_eval_batch_size: 2 From 9b3f8b9d858bafcdca89d8904f7533414a0a3132 Mon Sep 17 00:00:00 2001 From: realAsma Date: Tue, 7 Jul 2026 20:05:25 +0000 Subject: [PATCH 04/19] Fix LSQ calibration for multi-weight quantizers Signed-off-by: realAsma --- modelopt/torch/quantization/model_calib.py | 59 +++++++-------- tests/unit/torch/quantization/test_lsq.py | 88 +++++++++++++++++++--- 2 files changed, 107 insertions(+), 40 deletions(-) diff --git a/modelopt/torch/quantization/model_calib.py b/modelopt/torch/quantization/model_calib.py index 26e9b7d3280..7987ba138a4 100644 --- a/modelopt/torch/quantization/model_calib.py +++ b/modelopt/torch/quantization/model_calib.py @@ -62,9 +62,7 @@ is_quantized_row_parallel_linear, persistent_materialization, promote_nvfp4_static_quantizers, - quantizer_attr_names, reduce_amax, - weight_attr_names, ) from .utils.calib_utils import _GPTQ_HELPER_REGISTRY, GPTQHelper @@ -2158,21 +2156,6 @@ def _compute_block_scales(quantizer): return per_block_scale, per_tensor_scale, quantize_scales -def _iter_weight_quantizers(model): - """Yield (module, weight_name, quantizer) for each StaticBlockScaleQuantizer with amax.""" - seen_modules = set() - for name, module in model.named_modules(): - if module in seen_modules: - continue - for weight_name in weight_attr_names(module): - wq_name = quantizer_attr_names(weight_name).weight_quantizer - quantizer = getattr(module, wq_name, None) - if isinstance(quantizer, StaticBlockScaleQuantizer) and hasattr(quantizer, "_amax"): - seen_modules.add(module) - yield module, weight_name, quantizer - break - - def _compute_lsq_params(quantizer): """Compute amax and scale-quantization params for LSQ.""" per_block_scale, per_tensor_scale, quantize_scales = _compute_block_scales(quantizer) @@ -2208,17 +2191,31 @@ def lsq( """ _run_scale_calibration(model, forward_loop, scale_algorithm, "lsq") - for module, weight_name, quantizer in _iter_weight_quantizers(model): - amax, per_tensor_scale, quantize_scales = _compute_lsq_params(quantizer) - weight_dtype = getattr(module, weight_name).dtype - amax = amax.to(weight_dtype) - if per_tensor_scale is not None: - per_tensor_scale = per_tensor_scale.to(weight_dtype) - quantizer.enable_lsq( - amax, - per_tensor_scale, - quantize_scales, - learnable_amax=learnable_amax, - tied_amax=tied_amax, - quantize_pre_scale=quantize_pre_scale, - ) + name_to_module = dict(model.named_modules()) + seen_modules: set[int] = set() + seen_quantizers: set[int] = set() + for module in name_to_module.values(): + if id(module) in seen_modules or not isinstance(module, QuantModule): + continue + seen_modules.add(id(module)) + with enable_weight_access_and_writeback(module, model, name_to_module): + for weight, quantizer in module.iter_weights_for_calibration(): + if id(quantizer) in seen_quantizers: + continue + seen_quantizers.add(id(quantizer)) + if not isinstance(quantizer, StaticBlockScaleQuantizer) or not hasattr( + quantizer, "_amax" + ): + continue + amax, per_tensor_scale, quantize_scales = _compute_lsq_params(quantizer) + amax = amax.to(weight.dtype) + if per_tensor_scale is not None: + per_tensor_scale = per_tensor_scale.to(weight.dtype) + quantizer.enable_lsq( + amax, + per_tensor_scale, + quantize_scales, + learnable_amax=learnable_amax, + tied_amax=tied_amax, + quantize_pre_scale=quantize_pre_scale, + ) diff --git a/tests/unit/torch/quantization/test_lsq.py b/tests/unit/torch/quantization/test_lsq.py index 8e75bbf26e7..472efca3c7c 100644 --- a/tests/unit/torch/quantization/test_lsq.py +++ b/tests/unit/torch/quantization/test_lsq.py @@ -15,11 +15,16 @@ """CPU unit tests for the LSQ algorithm using INT4 quantization.""" +import types +from unittest.mock import Mock + import pytest import torch from torch import nn from modelopt.torch.quantization.config import LSQConfig +from modelopt.torch.quantization.model_calib import lsq +from modelopt.torch.quantization.nn import QuantLinear from modelopt.torch.quantization.nn.modules.tensor_quantizer import ( _FP8_E4M3_MIN_POSITIVE, StaticBlockScaleQuantizer, @@ -28,6 +33,25 @@ from modelopt.torch.quantization.tensor_quant import int_cast_ste +def _make_int4_static_quantizer(): + tq = TensorQuantizer() + tq._num_bits = 4 + tq._unsigned = False + tq._narrow_range = True + tq._disabled = False + tq._block_sizes = {-1: 16} + tq._pass_through_bwd = True + tq.register_buffer("_amax", torch.ones(8)) + return StaticBlockScaleQuantizer.from_tensor_quantizer(tq) + + +def _skip_scale_calibration(monkeypatch): + monkeypatch.setattr( + "modelopt.torch.quantization.model_calib._run_scale_calibration", + lambda *args, **kwargs: None, + ) + + class TestLSQConfig: """Tests for LSQConfig validation.""" @@ -70,15 +94,7 @@ class TestEnableLSQ: def _make_quantizer(self): """Create a StaticBlockScaleQuantizer configured for INT4.""" - tq = TensorQuantizer() - tq._num_bits = 4 - tq._unsigned = False - tq._narrow_range = True - tq._disabled = False - tq._block_sizes = {-1: 16} - tq._pass_through_bwd = True - tq.register_buffer("_amax", torch.ones(8)) - sbsq = StaticBlockScaleQuantizer.from_tensor_quantizer(tq) + sbsq = _make_int4_static_quantizer() assert sbsq._quant_max_bound == 7.0 return sbsq @@ -187,6 +203,60 @@ def test_align_lsq_amax_param_dtypes_uses_weight_dtype(self): assert module.weight_quantizer._amax_post.dtype == torch.bfloat16 +class TestLSQWeightIteration: + """Tests LSQ conversion for each weight exposed by QuantModule's iterator contract.""" + + def test_multiple_singular_weight_quantizers_use_their_weight_dtypes(self, monkeypatch): + _skip_scale_calibration(monkeypatch) + module = QuantLinear(16, 8, bias=False, dtype=torch.bfloat16) + module.weight_quantizer = _make_int4_static_quantizer() + module.proj = nn.Parameter(torch.ones(8, 16, dtype=torch.float16)) + module.proj_weight_quantizer = _make_int4_static_quantizer() + + lsq(module) + + assert module.weight_quantizer._lsq + assert module.proj_weight_quantizer._lsq + assert module.weight_quantizer._amax_post.dtype == torch.bfloat16 + assert module.proj_weight_quantizer._amax_post.dtype == torch.float16 + + def test_plural_expert_weight_quantizers_enter_lsq(self, monkeypatch): + _skip_scale_calibration(monkeypatch) + module = QuantLinear(16, 8, bias=False) + module.expert_weight = nn.Parameter(torch.ones(2, 8, 16)) + module.expert_weight_quantizers = nn.ModuleList( + [_make_int4_static_quantizer(), _make_int4_static_quantizer()] + ) + + def iter_expert_weights(self): + yield from zip(self.expert_weight, self.expert_weight_quantizers) + + module.iter_weights_for_calibration = types.MethodType(iter_expert_weights, module) + + lsq(module) + + assert all(quantizer._lsq for quantizer in module.expert_weight_quantizers) + + def test_shared_weight_quantizer_enters_lsq_once(self, monkeypatch): + _skip_scale_calibration(monkeypatch) + module = QuantLinear(16, 8, bias=False) + shared_quantizer = _make_int4_static_quantizer() + + def mark_lsq_enabled(*_args, **_kwargs): + shared_quantizer._lsq = True + + shared_quantizer.enable_lsq = Mock(side_effect=mark_lsq_enabled) + module.weight_quantizer = shared_quantizer + module.proj = nn.Parameter(torch.ones(8, 16)) + module.proj_weight_quantizer = shared_quantizer + + lsq(module) + + assert shared_quantizer._lsq + assert shared_quantizer.enable_lsq.call_count == 1 + assert module.weight_quantizer is module.proj_weight_quantizer + + class TestIntCastSTE: """Tests for int_cast_ste (INT4 STE function).""" From 2a06b57eff4131a182058db09b0794d217a2e15a Mon Sep 17 00:00:00 2001 From: realAsma Date: Tue, 7 Jul 2026 21:15:30 +0000 Subject: [PATCH 05/19] Fix static quantizer NVFP4 dispatch Signed-off-by: realAsma --- .../nn/modules/tensor_quantizer.py | 2 +- tests/unit/torch/quantization/test_lsq.py | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/modelopt/torch/quantization/nn/modules/tensor_quantizer.py b/modelopt/torch/quantization/nn/modules/tensor_quantizer.py index 2a8a798283c..b41a517fbeb 100644 --- a/modelopt/torch/quantization/nn/modules/tensor_quantizer.py +++ b/modelopt/torch/quantization/nn/modules/tensor_quantizer.py @@ -1709,7 +1709,7 @@ def _fake_quantize(self, inputs): return (w_cast * scale_post.view(-1, 1).to(w_cast.dtype)).to(inputs.dtype) if self.amax is not None: - if isinstance(self._num_bits, tuple): + if self.is_nvfp4_static: return static_blockwise_fp4_fake_quant( inputs, self.amax, diff --git a/tests/unit/torch/quantization/test_lsq.py b/tests/unit/torch/quantization/test_lsq.py index 472efca3c7c..e92ea779438 100644 --- a/tests/unit/torch/quantization/test_lsq.py +++ b/tests/unit/torch/quantization/test_lsq.py @@ -22,6 +22,7 @@ import torch from torch import nn +import modelopt.torch.quantization.nn.modules.tensor_quantizer as tensor_quantizer_module from modelopt.torch.quantization.config import LSQConfig from modelopt.torch.quantization.model_calib import lsq from modelopt.torch.quantization.nn import QuantLinear @@ -52,6 +53,36 @@ def _skip_scale_calibration(monkeypatch): ) +@pytest.mark.parametrize( + ("num_bits", "expected_dispatch"), + [pytest.param((2, 1), "nvfp4", id="nvfp4"), pytest.param((4, 3), "generic", id="fp8")], +) +def test_non_lsq_static_float_dispatches_only_nvfp4_to_fp4_kernel( + monkeypatch, num_bits, expected_dispatch +): + tq = TensorQuantizer() + tq._num_bits = num_bits + tq._block_sizes = {-1: 16, "type": "static", "scale_bits": (4, 3)} + tq.register_buffer("_amax", torch.ones(4)) + quantizer = StaticBlockScaleQuantizer.from_tensor_quantizer(tq, global_amax=torch.tensor(1.0)) + dispatches = [] + + def fake_nvfp4(inputs, *_args): + dispatches.append("nvfp4") + return inputs + + def fake_generic(_self, inputs): + dispatches.append("generic") + return inputs + + monkeypatch.setattr(tensor_quantizer_module, "static_blockwise_fp4_fake_quant", fake_nvfp4) + monkeypatch.setattr(TensorQuantizer, "_fake_quantize", fake_generic) + + quantizer._fake_quantize(torch.ones(4, 16)) + + assert dispatches == [expected_dispatch] + + class TestLSQConfig: """Tests for LSQConfig validation.""" From 66526ba00778420e26776795564d83222b1df3dd Mon Sep 17 00:00:00 2001 From: realAsma Date: Tue, 7 Jul 2026 21:15:43 +0000 Subject: [PATCH 06/19] Refactor LSQ block amax computation Signed-off-by: realAsma --- modelopt/torch/quantization/model_calib.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/modelopt/torch/quantization/model_calib.py b/modelopt/torch/quantization/model_calib.py index 7987ba138a4..a54cc589180 100644 --- a/modelopt/torch/quantization/model_calib.py +++ b/modelopt/torch/quantization/model_calib.py @@ -2122,10 +2122,10 @@ def _run_scale_calibration(model, forward_loop, scale_algorithm, caller_name): _convert_to_static_block_quantizers(model) -def _compute_block_scales(quantizer): - """Compute per-block and per-tensor scales from a StaticBlockScaleQuantizer. +def _compute_block_amax(quantizer): + """Compute per-block amax and per-tensor scale from a StaticBlockScaleQuantizer. - Returns (per_block_scale, per_tensor_scale, quantize_scales). + Returns (per_block_amax, per_tensor_scale, quantize_scales). """ from .nn.modules.tensor_quantizer import _FP8_E4M3_MIN_POSITIVE, _amax_to_scale from .tensor_quant import scaled_e4m3 @@ -2153,14 +2153,13 @@ def _compute_block_scales(quantizer): else: per_block_scale = _amax_to_scale(amax, max_representable) - return per_block_scale, per_tensor_scale, quantize_scales + per_block_amax = per_block_scale * max_representable + return per_block_amax, per_tensor_scale, quantize_scales def _compute_lsq_params(quantizer): """Compute amax and scale-quantization params for LSQ.""" - per_block_scale, per_tensor_scale, quantize_scales = _compute_block_scales(quantizer) - amax = per_block_scale * quantizer._quant_max_bound - return amax, per_tensor_scale, quantize_scales + return _compute_block_amax(quantizer) @torch.no_grad() From 61d85a1df19f9e086ad9c9db49e55abf9d02ad49 Mon Sep 17 00:00:00 2001 From: realAsma Date: Tue, 7 Jul 2026 23:02:53 +0000 Subject: [PATCH 07/19] docs: add LSQ changelog entry Signed-off-by: realAsma --- CHANGELOG.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d7173f7e373..6319ea412a5 100755 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -20,6 +20,7 @@ Changelog **New Features** +- Add Learned Scale Quantization (LSQ) and Dual-LSQ support for quantization-aware distillation, including learnable ``amax`` parameters, tied-scale and pre-scale options, focused NVFP4 recipes, and scale-only training. - Add the **D-PACE** loss objective for DFlash speculative-decoding training (`arXiv:2605.18810 `_) and make it the default (``dflash_loss_objective: dpace``). It replaces the static exponential position decay with dynamic, confidence-derived per-position weights that adapt to whichever block positions currently limit acceptance. Smoothing is controlled by ``dflash_dpace_alpha`` (default 0.5); set ``dflash_loss_objective: decay`` to restore the previous static schedule. Training-only and detached from the gradient (no architecture or inference change). - Add the ``day0-release`` agent skill (``.agents/skills/day0-release/``), a deterministic end-to-end driver that chains the PTQ → evaluation → comparison skills (the evaluation stage deploys the checkpoint itself) with an enforced gate after each stage and returns a publish decision (ACCEPT / REGRESSION / ANOMALOUS / INFEASIBLE). Ships three GPU-free, unit-tested gate scripts (``gate_ptq.py``, ``gate_run.py``, ``gate_compare.py``) that validate checkpoint coverage, evaluation-run completeness, and baseline-vs-candidate accuracy threshold. v1 reports and stops on regression; the recipe-search loop is deferred. - Add **streaming** speculative-decoding training (EAGLE3 / DFlash): the draft trains on base-model hidden states produced on the fly by a co-located ``vllm serve`` (no disk dump), moved trainer-side over NIXL RDMA, scaling to multi-node (dedicated serve replicas + DDP trainers). New launcher examples for NVFP4 Kimi-K2.5 / K2.6 on GB200/aarch64 under ``tools/launcher/examples/moonshotai/``. From 4bac049c4e5932b3279809a982eb093a181c4bc2 Mon Sep 17 00:00:00 2001 From: realAsma <86726418+realAsma@users.noreply.github.com> Date: Wed, 8 Jul 2026 20:16:36 +0000 Subject: [PATCH 08/19] docs: add PR 1884 QAD loss curves Signed-off-by: realAsma <86726418+realAsma@users.noreply.github.com> --- .../pr1884-qwen3-1.7b-qad-loss-curves.png | Bin 0 -> 262652 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/source/assets/pr1884-qwen3-1.7b-qad-loss-curves.png diff --git a/docs/source/assets/pr1884-qwen3-1.7b-qad-loss-curves.png b/docs/source/assets/pr1884-qwen3-1.7b-qad-loss-curves.png new file mode 100644 index 0000000000000000000000000000000000000000..9baeee53e778facbce73c22e1e1a9b24ed5a9ec3 GIT binary patch literal 262652 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 QKJh&AF0-9!+mBxS55xwELI3~& literal 0 HcmV?d00001 From dc1efc0c6cef43d4285780a836abedb09fcd2de2 Mon Sep 17 00:00:00 2001 From: realAsma Date: Thu, 9 Jul 2026 00:45:54 +0000 Subject: [PATCH 09/19] Add scale calibration config type Signed-off-by: realAsma --- modelopt/torch/quantization/config.py | 21 +++++++++-- modelopt/torch/quantization/model_calib.py | 3 ++ tests/unit/torch/quantization/test_lsq.py | 41 ++++++++++++++++++++-- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/modelopt/torch/quantization/config.py b/modelopt/torch/quantization/config.py index 94c22b2a44f..cd62837725c 100644 --- a/modelopt/torch/quantization/config.py +++ b/modelopt/torch/quantization/config.py @@ -155,7 +155,14 @@ from collections.abc import Mapping, Sequence from typing import Any, Literal -from pydantic import AliasChoices, Field, ValidationInfo, field_validator, model_validator +from pydantic import ( + AliasChoices, + Field, + ValidationInfo, + field_serializer, + field_validator, + model_validator, +) from modelopt.torch.opt.config import ModeloptBaseConfig, ModeloptField from modelopt.torch.opt.config_loader import load_config @@ -1013,6 +1020,9 @@ class LocalHessianCalibConfig(_SharedStatesConfig, QuantizeAlgorithmConfig): ) +ScaleCalibConfig = MaxCalibConfig | MseCalibConfig | LocalHessianCalibConfig + + class SmoothQuantCalibConfig(QuantizeAlgorithmConfig): """The config for ``smoothquant`` algorithm (SmoothQuant). @@ -1264,7 +1274,7 @@ class LSQConfig(QuantizeAlgorithmConfig): ), ) - scale_algorithm: dict | None = ModeloptField( + scale_algorithm: ScaleCalibConfig | None = ModeloptField( default=None, title="Scale calibration algorithm to run first.", description=( @@ -1274,6 +1284,13 @@ class LSQConfig(QuantizeAlgorithmConfig): ), ) + @field_serializer("scale_algorithm") + def _serialize_scale_algorithm(self, value: ScaleCalibConfig | None): + """Preserve the sparse public dict shape accepted by this field.""" + if value is None: + return None + return {"method": value.method, **value.model_dump(exclude={"method"}, exclude_unset=True)} + @model_validator(mode="after") def _validate_tied_amax(self): """Validate tied_amax is compatible with learnable_amax.""" diff --git a/modelopt/torch/quantization/model_calib.py b/modelopt/torch/quantization/model_calib.py index a54cc589180..ce3f194c2b8 100644 --- a/modelopt/torch/quantization/model_calib.py +++ b/modelopt/torch/quantization/model_calib.py @@ -30,6 +30,7 @@ import torch.nn.functional as F from tqdm import tqdm +from modelopt.torch.opt.config import ModeloptBaseConfig from modelopt.torch.opt.searcher import ForwardLoop from modelopt.torch.quantization.utils.layerwise_calib import ( LayerActivationCollector, @@ -2096,6 +2097,8 @@ def _run_scale_calibration(model, forward_loop, scale_algorithm, caller_name): supported = ("mse", "local_hessian", "max") assert method in supported, f"{caller_name}: method must be one of {supported}, got '{method}'" + if isinstance(scale_algorithm, ModeloptBaseConfig): + scale_algorithm = scale_algorithm.model_dump(exclude_unset=True) algo_kwargs = {k: v for k, v in scale_algorithm.items() if k != "method"} calib_funcs = { "mse": mse_calibrate, diff --git a/tests/unit/torch/quantization/test_lsq.py b/tests/unit/torch/quantization/test_lsq.py index e92ea779438..9c838f8f098 100644 --- a/tests/unit/torch/quantization/test_lsq.py +++ b/tests/unit/torch/quantization/test_lsq.py @@ -16,14 +16,20 @@ """CPU unit tests for the LSQ algorithm using INT4 quantization.""" import types -from unittest.mock import Mock +from unittest.mock import Mock, create_autospec import pytest import torch from torch import nn +import modelopt.torch.quantization.model_calib as model_calib_module import modelopt.torch.quantization.nn.modules.tensor_quantizer as tensor_quantizer_module -from modelopt.torch.quantization.config import LSQConfig +from modelopt.torch.quantization.config import ( + LocalHessianCalibConfig, + LSQConfig, + MaxCalibConfig, + MseCalibConfig, +) from modelopt.torch.quantization.model_calib import lsq from modelopt.torch.quantization.nn import QuantLinear from modelopt.torch.quantization.nn.modules.tensor_quantizer import ( @@ -94,6 +100,37 @@ def test_default_config(self): assert cfg.quantize_pre_scale is True assert cfg.scale_algorithm is None + @pytest.mark.parametrize( + ("method", "config_type"), + [ + ("max", MaxCalibConfig), + ("mse", MseCalibConfig), + ("local_hessian", LocalHessianCalibConfig), + ], + ) + def test_scale_algorithm(self, method, config_type): + cfg = LSQConfig(scale_algorithm={"method": method}) + assert isinstance(cfg.scale_algorithm, config_type) + + def test_unsupported_scale_algorithm(self): + with pytest.raises(ValueError): + LSQConfig(scale_algorithm={"method": "smoothquant"}) + + def test_scale_algorithm_preserves_sparse_dict(self, monkeypatch): + cfg = LSQConfig(scale_algorithm={"method": "mse", "fp8_scale_sweep": True}) + assert cfg.model_dump()["scale_algorithm"] == { + "method": "mse", + "fp8_scale_sweep": True, + } + + calibrate = create_autospec(model_calib_module.mse_calibrate) + monkeypatch.setattr(model_calib_module, "mse_calibrate", calibrate) + model = Mock() + model_calib_module._run_scale_calibration( + model, None, cfg.scale_algorithm, caller_name="lsq" + ) + calibrate.assert_called_once_with(model, forward_loop=None, fp8_scale_sweep=True) + @pytest.mark.parametrize( ("learnable_amax", "tied_amax"), [ From 09bf4395556029cb66e3620761378301d74a7ce5 Mon Sep 17 00:00:00 2001 From: realAsma Date: Thu, 9 Jul 2026 01:02:54 +0000 Subject: [PATCH 10/19] Fix static integer weight calibration finalization Signed-off-by: realAsma --- .../pr1884-qwen3-1.7b-qad-loss-curves.png | Bin 262652 -> 0 bytes modelopt/torch/quantization/model_calib.py | 64 ++++++++++-------- tests/unit/torch/quantization/test_lsq.py | 21 +++++- 3 files changed, 55 insertions(+), 30 deletions(-) delete mode 100644 docs/source/assets/pr1884-qwen3-1.7b-qad-loss-curves.png diff --git a/docs/source/assets/pr1884-qwen3-1.7b-qad-loss-curves.png b/docs/source/assets/pr1884-qwen3-1.7b-qad-loss-curves.png deleted file mode 100644 index 9baeee53e778facbce73c22e1e1a9b24ed5a9ec3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 262652 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 QKJh&AF0-9!+mBxS55xwELI3~& diff --git a/modelopt/torch/quantization/model_calib.py b/modelopt/torch/quantization/model_calib.py index ce3f194c2b8..ec603e4b653 100644 --- a/modelopt/torch/quantization/model_calib.py +++ b/modelopt/torch/quantization/model_calib.py @@ -63,7 +63,6 @@ is_quantized_row_parallel_linear, persistent_materialization, promote_nvfp4_static_quantizers, - reduce_amax, ) from .utils.calib_utils import _GPTQ_HELPER_REGISTRY, GPTQHelper @@ -140,16 +139,48 @@ def _check_grouped_weight_global_amax_synced(model: nn.Module) -> None: ) +def _promote_integer_static_weight_quantizers(model: nn.Module) -> None: + """Promote calibrated integer static-block weight quantizers for LSQ.""" + candidate_ids = { + id(module) + for module in model.modules() + if isinstance(module, TensorQuantizer) + and module.is_enabled + and module.is_static_block_quant + and isinstance(module._num_bits, int) + and getattr(module, "_amax", None) is not None + } + if not candidate_ids: + return + + name_to_module = dict(model.named_modules()) + seen_modules: set[int] = set() + for module in name_to_module.values(): + if id(module) in seen_modules or not isinstance(module, QuantModule): + continue + seen_modules.add(id(module)) + with enable_weight_access_and_writeback(module, model, name_to_module): + for _, quantizer in module.iter_weights_for_calibration(): + if id(quantizer) not in candidate_ids: + continue + StaticBlockScaleQuantizer.from_tensor_quantizer(quantizer) + candidate_ids.remove(id(quantizer)) + if not candidate_ids: + return + + def _finalize_with_shared_state(model: nn.Module, weight_patterns: list[str]) -> None: - """Finalize quantization from the attached shared state: aggregate, promote, verify. + """Finalize calibrated static quantizers and attached shared state. Aggregates each fusible group's shared weight ``global_amax`` and promotes it onto the member NVFP4-static quantizers, so siblings read the unified value instead of their own - ``_amax``; under the default patterns, verifies the name groups were actually synced. + ``_amax``. Promotes integer static-block weight quantizers after their ``_amax`` is final. + Under the default patterns, verifies the name groups were actually synced. Call once ``_amax`` is final: single-process, or after the distributed amax sync. """ SharedWeightGlobalAmaxState.populate(model) promote_nvfp4_static_quantizers(model) + _promote_integer_static_weight_quantizers(model) # Under the default patterns, verify the fusible name groups were actually synced. if weight_patterns == list(SHARED_PATTERNS): _check_grouped_weight_global_amax_synced(model) @@ -2066,30 +2097,8 @@ def _is_quantized_block_scale(quantizer: StaticBlockScaleQuantizer) -> bool: return scale_bits == (4, 3) -def _convert_to_static_block_quantizers(model: nn.Module): - """Convert eligible TensorQuantizers to StaticBlockScaleQuantizer.""" - for name, module in model.named_modules(): - if isinstance(module, TensorQuantizer) and not module._disabled: - if not hasattr(module, "_amax") or module._amax is None: - continue - is_static_block_scale = ( - module.is_static_block_quant - and module._block_sizes is not None - and ( - (module._num_bits == (2, 1) and module._block_sizes.get("scale_bits") == (4, 3)) - or isinstance(module._num_bits, int) - ) - ) - if is_static_block_scale: - if _is_quantized_block_scale(module): - global_amax = reduce_amax(module._amax.clone().detach(), axis=None) - else: - global_amax = None - StaticBlockScaleQuantizer.from_tensor_quantizer(module, global_amax=global_amax) - - def _run_scale_calibration(model, forward_loop, scale_algorithm, caller_name): - """Run calibration and convert to StaticBlockScaleQuantizer if needed.""" + """Run scale calibration.""" if scale_algorithm is None: scale_algorithm = {"method": "mse"} @@ -2121,9 +2130,6 @@ def _run_scale_calibration(model, forward_loop, scale_algorithm, caller_name): algo_kwargs = {k: v for k, v in algo_kwargs.items() if k in accepted} calib_func(model, forward_loop=forward_loop, **algo_kwargs) - if method == "max": - _convert_to_static_block_quantizers(model) - def _compute_block_amax(quantizer): """Compute per-block amax and per-tensor scale from a StaticBlockScaleQuantizer. diff --git a/tests/unit/torch/quantization/test_lsq.py b/tests/unit/torch/quantization/test_lsq.py index 9c838f8f098..cef4aae6832 100644 --- a/tests/unit/torch/quantization/test_lsq.py +++ b/tests/unit/torch/quantization/test_lsq.py @@ -29,8 +29,9 @@ LSQConfig, MaxCalibConfig, MseCalibConfig, + QuantizerAttributeConfig, ) -from modelopt.torch.quantization.model_calib import lsq +from modelopt.torch.quantization.model_calib import lsq, max_calibrate from modelopt.torch.quantization.nn import QuantLinear from modelopt.torch.quantization.nn.modules.tensor_quantizer import ( _FP8_E4M3_MIN_POSITIVE, @@ -324,6 +325,24 @@ def mark_lsq_enabled(*_args, **_kwargs): assert shared_quantizer.enable_lsq.call_count == 1 assert module.weight_quantizer is module.proj_weight_quantizer + @pytest.mark.parametrize("distributed_sync", [False, True]) + def test_max_calibrate_promotes_static_int_quantizer(self, distributed_sync): + module = QuantLinear(16, 8, bias=False) + config = QuantizerAttributeConfig(num_bits=4, block_sizes={-1: 16, "type": "static"}) + module.weight_quantizer.set_from_attribute_config(config) + module.input_quantizer.set_from_attribute_config(config) + + max_calibrate( + module, + forward_loop=lambda model: model(torch.randn(2, 16)), + distributed_sync=distributed_sync, + ) + + assert isinstance(module.weight_quantizer, StaticBlockScaleQuantizer) + assert module.weight_quantizer.export_amax() is not None + assert not isinstance(module.input_quantizer, StaticBlockScaleQuantizer) + assert module.input_quantizer.amax is not None + class TestIntCastSTE: """Tests for int_cast_ste (INT4 STE function).""" From 1501777db041ebb9c0aceb7ca8e68492b461216c Mon Sep 17 00:00:00 2001 From: realAsma Date: Thu, 9 Jul 2026 19:45:56 +0000 Subject: [PATCH 11/19] Derive LSQ per-tensor scale from global_amax at runtime The frozen per-quantizer _per_tensor_scale buffer snapshotted at enable_lsq time broke the shared weight global_amax invariant for fusible sibling groups (q/k/v, gate/up): the snapshot was untied and diverged when the shared buffer changed. Compute the per-tensor scale from the (possibly tied) global_amax on each forward instead, matching the non-LSQ static path. Also drop the redundant FP8-snapped initial per-block amax (the forward FP8-quantizes the per-block scale every pass and scaled_e4m3 is idempotent), make enable_lsq fully state-driven, and consolidate the per-block scale math in StaticBlockScaleQuantizer, deleting the duplicated model_calib helpers. Co-Authored-By: Claude Fable 5 Signed-off-by: realAsma --- modelopt/torch/quantization/model_calib.py | 59 +-------- .../nn/modules/tensor_quantizer.py | 99 ++++++++------- tests/gpu/torch/quantization/test_fsdp2.py | 2 +- tests/gpu/torch/quantization/test_lsq_cuda.py | 6 +- tests/unit/torch/quantization/test_lsq.py | 116 +++++++++++++----- 5 files changed, 142 insertions(+), 140 deletions(-) diff --git a/modelopt/torch/quantization/model_calib.py b/modelopt/torch/quantization/model_calib.py index ec603e4b653..759cb4dabda 100644 --- a/modelopt/torch/quantization/model_calib.py +++ b/modelopt/torch/quantization/model_calib.py @@ -36,7 +36,7 @@ LayerActivationCollector, _CheckpointState, ) -from modelopt.torch.utils import print_rank_0, same_device_as, warn_rank_0 +from modelopt.torch.utils import print_rank_0, warn_rank_0 from modelopt.torch.utils.distributed import DistributedProcessGroup, ParallelState from modelopt.torch.utils.distributed import is_initialized as dist_is_initialized from modelopt.torch.utils.distributed import size as dist_size @@ -2088,15 +2088,6 @@ def _make_gptq_handle(name, m): print_rank_0(f"GPTQ time: {time.time() - total_start:.2f}s") -def _is_quantized_block_scale(quantizer: StaticBlockScaleQuantizer) -> bool: - if quantizer._block_sizes is None: - return False - scale_bits = quantizer._block_sizes.get("scale_bits", None) - if scale_bits is None: - return False - return scale_bits == (4, 3) - - def _run_scale_calibration(model, forward_loop, scale_algorithm, caller_name): """Run scale calibration.""" if scale_algorithm is None: @@ -2131,46 +2122,6 @@ def _run_scale_calibration(model, forward_loop, scale_algorithm, caller_name): calib_func(model, forward_loop=forward_loop, **algo_kwargs) -def _compute_block_amax(quantizer): - """Compute per-block amax and per-tensor scale from a StaticBlockScaleQuantizer. - - Returns (per_block_amax, per_tensor_scale, quantize_scales). - """ - from .nn.modules.tensor_quantizer import _FP8_E4M3_MIN_POSITIVE, _amax_to_scale - from .tensor_quant import scaled_e4m3 - - amax = quantizer._amax.float() - max_representable = quantizer._quant_max_bound - quantize_scales = _is_quantized_block_scale(quantizer) - per_tensor_scale = None - - with same_device_as(amax): - if quantize_scales: - global_amax = quantizer._global_amax.float() - per_tensor_scale = _amax_to_scale(global_amax, max_representable) - per_block_scale = scaled_e4m3( - _amax_to_scale( - amax, - max_representable, - min_value=_FP8_E4M3_MIN_POSITIVE * per_tensor_scale.view(-1), - ), - per_tensor_scale, - None, - 4, - 3, - ) - else: - per_block_scale = _amax_to_scale(amax, max_representable) - - per_block_amax = per_block_scale * max_representable - return per_block_amax, per_tensor_scale, quantize_scales - - -def _compute_lsq_params(quantizer): - """Compute amax and scale-quantization params for LSQ.""" - return _compute_block_amax(quantizer) - - @torch.no_grad() def lsq( model: nn.Module, @@ -2215,15 +2166,9 @@ def lsq( quantizer, "_amax" ): continue - amax, per_tensor_scale, quantize_scales = _compute_lsq_params(quantizer) - amax = amax.to(weight.dtype) - if per_tensor_scale is not None: - per_tensor_scale = per_tensor_scale.to(weight.dtype) quantizer.enable_lsq( - amax, - per_tensor_scale, - quantize_scales, learnable_amax=learnable_amax, tied_amax=tied_amax, quantize_pre_scale=quantize_pre_scale, + dtype=weight.dtype, ) diff --git a/modelopt/torch/quantization/nn/modules/tensor_quantizer.py b/modelopt/torch/quantization/nn/modules/tensor_quantizer.py index b41a517fbeb..69cebc59a16 100644 --- a/modelopt/torch/quantization/nn/modules/tensor_quantizer.py +++ b/modelopt/torch/quantization/nn/modules/tensor_quantizer.py @@ -1588,6 +1588,23 @@ def global_amax(self, value): global_amax.data.copy_(value.clone().detach().to(global_amax.device)) self._preserve_amax_in_fp32() + @property + def per_tensor_scale(self): + """Runtime per-tensor scale derived from ``global_amax``. + + Computed on the fly (fp32) rather than snapshotted so that updates to the + possibly tied/shared ``global_amax`` (e.g. export unification of a fusible + sibling group) are always reflected. Returns None when ``global_amax`` is None. + """ + if self.global_amax is None: + return None + return _amax_to_scale(self._global_amax, self._quant_max_bound) + + @property + def has_quantized_block_scale(self): + """True when per-block scales are FP8 (E4M3) quantized (format-only check).""" + return self._block_sizes is not None and self._block_sizes.get("scale_bits") == (4, 3) + def _apply(self, fn, recurse=True): """Apply module transforms without rounding static scale state.""" amax = getattr(self, "_amax", None) @@ -1616,48 +1633,55 @@ def _short_amax(self, fmt=".4f"): def enable_lsq( self, - amax: torch.Tensor, - per_tensor_scale: torch.Tensor = None, - quantize_scales: bool = True, + quantize_scales: bool | None = None, learnable_amax: list | str = ("post",), tied_amax: bool = False, quantize_pre_scale: bool = True, + dtype: torch.dtype | None = None, ): """LSQ mode with configurable learnable/frozen amax tensors. + The per-block amax params are initialized from the calibrated ``_amax``. The + per-tensor scale is never materialized; it is derived from ``global_amax`` at + runtime (see ``per_tensor_scale``) so shared-group updates are always reflected. + Args: - amax: Initial amax values (per-block). - per_tensor_scale: Optional per-tensor scale (frozen buffer). - quantize_scales: Whether to FP8-quantize per-block scales. Used for NVFP4 quantization. + quantize_scales: Whether to FP8-quantize per-block scales (NVFP4). When None, + defaults to ``has_quantized_block_scale``. learnable_amax: Which amax params are learnable: 'pre', 'post', ['pre', 'post'], or []. tied_amax: If True, pre and post share a single tensor. quantize_pre_scale: Whether to FP8-quantize the LSQ pre scale. + dtype: Optional dtype for the amax params. Kept at weight dtype for FSDP2 + mixed-precision support (see TODO below). """ - if hasattr(self, "_amax"): - delattr(self, "_amax") - amax = amax.detach() - if not amax.is_floating_point(): - amax = amax.float() + assert hasattr(self, "_amax"), "enable_lsq requires a calibrated _amax." + if quantize_scales is None: + quantize_scales = self.has_quantized_block_scale + if quantize_scales: + assert self.global_amax is not None, ( + "enable_lsq(quantize_scales=True) requires global_amax to be set." + ) + # TODO: Support fp32 learnable amax values once a stable PyTorch release # includes FSDP2 mixed-precision parameter dtype support. - amax_param = amax.clone() - amax_buffer = amax.clone() + amax = self._amax.float() + if dtype is not None: + amax = amax.to(dtype) + delattr(self, "_amax") learn = {learnable_amax} if isinstance(learnable_amax, str) else set(learnable_amax) if "post" in learn: - self._amax_post = nn.Parameter(amax_param.clone(), requires_grad=True) + self._amax_post = nn.Parameter(amax.clone(), requires_grad=True) else: - self.register_buffer("_amax_post", amax_buffer.clone()) + self.register_buffer("_amax_post", amax.clone()) if not tied_amax: if "pre" in learn: - self._amax_pre = nn.Parameter(amax_param.clone(), requires_grad=True) + self._amax_pre = nn.Parameter(amax.clone(), requires_grad=True) else: - self.register_buffer("_amax_pre", amax_buffer.clone()) + self.register_buffer("_amax_pre", amax.clone()) - if per_tensor_scale is not None: - self.register_buffer("_per_tensor_scale", per_tensor_scale.clone().detach()) self._quantize_scales = quantize_scales self._quantize_pre_scale = quantize_pre_scale self._lsq = True @@ -1670,40 +1694,21 @@ def _cast_ste(self, inputs): return fp4_cast_ste(inputs) return int_cast_ste(inputs, self._num_bits, self._unsigned, self._narrow_range) - def _maybe_quantize_scale(self, scale_raw): - """FP8-quantize a per-block scale if ``_quantize_scales`` is enabled, else pass through.""" - if self._quantize_scales: - return scaled_e4m3(scale_raw, self._per_tensor_scale, None, 4, 3) - return scale_raw + def _block_scale_from_amax(self, amax: torch.Tensor, quantize: bool) -> torch.Tensor: + """Compute the per-block scale from a per-block amax, optionally FP8-quantizing it.""" + min_value = _FP8_E4M3_MIN_POSITIVE * self.per_tensor_scale.view(-1) if quantize else 1e-8 + scale = _amax_to_scale(amax, self._quant_max_bound, min_value=min_value) + return scaled_e4m3(scale, self.per_tensor_scale, None, 4, 3) if quantize else scale def _fake_quantize(self, inputs): """Fake quantization using two-level scaling with _amax and _global_amax.""" if self._lsq: - scale_min_post = ( - _FP8_E4M3_MIN_POSITIVE * self._per_tensor_scale.view(-1) - if self._quantize_scales - else 1e-8 - ) - scale_min_pre = ( - _FP8_E4M3_MIN_POSITIVE * self._per_tensor_scale.view(-1) - if self._quantize_scales and self._quantize_pre_scale - else 1e-8 - ) - - scale_post = self._maybe_quantize_scale( - _amax_to_scale( - _to_local(self.amax_post), - self._quant_max_bound, - min_value=scale_min_post, - ) + scale_post = self._block_scale_from_amax( + _to_local(self.amax_post), self._quantize_scales ) - scale_pre = _amax_to_scale( - _to_local(self.amax_pre), - self._quant_max_bound, - min_value=scale_min_pre, + scale_pre = self._block_scale_from_amax( + _to_local(self.amax_pre), self._quantize_scales and self._quantize_pre_scale ) - if self._quantize_scales and self._quantize_pre_scale: - scale_pre = self._maybe_quantize_scale(scale_pre) quant_input = inputs.float() / scale_pre.float().view(-1, 1) w_cast = self._cast_ste(quant_input) return (w_cast * scale_post.view(-1, 1).to(w_cast.dtype)).to(inputs.dtype) diff --git a/tests/gpu/torch/quantization/test_fsdp2.py b/tests/gpu/torch/quantization/test_fsdp2.py index 6f8ab6e292b..6d47e1620ab 100644 --- a/tests/gpu/torch/quantization/test_fsdp2.py +++ b/tests/gpu/torch/quantization/test_fsdp2.py @@ -154,9 +154,9 @@ def __init__(self, dim=16): tq.register_buffer("_amax", torch.ones(dim, dtype=torch.bfloat16)) self.weight_quantizer = StaticBlockScaleQuantizer.from_tensor_quantizer(tq) self.weight_quantizer.enable_lsq( - torch.ones(dim, dtype=torch.bfloat16), quantize_scales=False, learnable_amax=["pre", "post"], + dtype=torch.bfloat16, ) def forward(self, inputs): diff --git a/tests/gpu/torch/quantization/test_lsq_cuda.py b/tests/gpu/torch/quantization/test_lsq_cuda.py index 7d2a686be93..e2d802bc6b7 100644 --- a/tests/gpu/torch/quantization/test_lsq_cuda.py +++ b/tests/gpu/torch/quantization/test_lsq_cuda.py @@ -168,11 +168,9 @@ def test_lsq_fp4_fake_quantize_differentiable(): tq, global_amax=torch.tensor(1.0, device=device) ) - amax = torch.ones(4, device=device) * 3.0 - per_tensor_scale = torch.tensor(1.0 / 6.0, device=device) + # global_amax=1.0 with NVFP4 _quant_max_bound=6.0 yields per_tensor_scale = 1/6. + sbsq.amax = torch.ones(4, device=device) * 3.0 sbsq.enable_lsq( - amax, - per_tensor_scale=per_tensor_scale, quantize_scales=True, learnable_amax=["post"], ) diff --git a/tests/unit/torch/quantization/test_lsq.py b/tests/unit/torch/quantization/test_lsq.py index cef4aae6832..a81fe7e22b5 100644 --- a/tests/unit/torch/quantization/test_lsq.py +++ b/tests/unit/torch/quantization/test_lsq.py @@ -37,8 +37,10 @@ _FP8_E4M3_MIN_POSITIVE, StaticBlockScaleQuantizer, TensorQuantizer, + _amax_to_scale, ) from modelopt.torch.quantization.tensor_quant import int_cast_ste +from modelopt.torch.quantization.utils.shared_input import SharedWeightGlobalAmaxState def _make_int4_static_quantizer(): @@ -169,8 +171,7 @@ def _make_quantizer(self): def test_post_only_learnable(self): q = self._make_quantizer() - amax = torch.ones(8) * 3.0 - q.enable_lsq(amax, quantize_scales=False, learnable_amax=["post"], tied_amax=False) + q.enable_lsq(quantize_scales=False, learnable_amax=["post"], tied_amax=False) assert q._lsq is True assert isinstance(q._amax_post, nn.Parameter) assert q._amax_post.requires_grad is True @@ -179,23 +180,20 @@ def test_post_only_learnable(self): def test_pre_only_learnable(self): q = self._make_quantizer() - amax = torch.ones(8) * 3.0 - q.enable_lsq(amax, quantize_scales=False, learnable_amax=["pre"], tied_amax=False) + q.enable_lsq(quantize_scales=False, learnable_amax=["pre"], tied_amax=False) assert isinstance(q._amax_pre, nn.Parameter) assert q._amax_pre.requires_grad is True assert not isinstance(q._amax_post, nn.Parameter) def test_both_learnable(self): q = self._make_quantizer() - amax = torch.ones(8) * 3.0 - q.enable_lsq(amax, quantize_scales=False, learnable_amax=["pre", "post"], tied_amax=False) + q.enable_lsq(quantize_scales=False, learnable_amax=["pre", "post"], tied_amax=False) assert isinstance(q._amax_pre, nn.Parameter) assert isinstance(q._amax_post, nn.Parameter) def test_tied_both_learnable(self): q = self._make_quantizer() - amax = torch.ones(8) * 3.0 - q.enable_lsq(amax, quantize_scales=False, learnable_amax=["pre", "post"], tied_amax=True) + q.enable_lsq(quantize_scales=False, learnable_amax=["pre", "post"], tied_amax=True) assert q._tied_amax is True assert isinstance(q._amax_post, nn.Parameter) assert not hasattr(q, "_amax_pre") @@ -203,33 +201,37 @@ def test_tied_both_learnable(self): def test_frozen(self): q = self._make_quantizer() - amax = torch.ones(8) * 3.0 - q.enable_lsq(amax, quantize_scales=False, learnable_amax=[], tied_amax=False) + q.enable_lsq(quantize_scales=False, learnable_amax=[], tied_amax=False) assert not isinstance(q._amax_post, nn.Parameter) assert not isinstance(q._amax_pre, nn.Parameter) def test_old_amax_deleted(self): q = self._make_quantizer() assert hasattr(q, "_amax") - q.enable_lsq(torch.ones(8), quantize_scales=False) + q.enable_lsq(quantize_scales=False) assert not hasattr(q, "_amax") def test_can_skip_pre_scale_quantization(self): q = self._make_quantizer() q.enable_lsq( - torch.ones(8), quantize_scales=False, quantize_pre_scale=False, ) assert q._quantize_pre_scale is False + def test_quantize_scales_without_global_amax_raises(self): + q = self._make_quantizer() + assert q.global_amax is None + with pytest.raises(AssertionError, match="global_amax"): + q.enable_lsq(quantize_scales=True) + @pytest.mark.parametrize("dtype", [torch.float16, torch.bfloat16]) def test_learnable_amax_uses_input_dtype(self, dtype): q = self._make_quantizer() q.enable_lsq( - torch.ones(8, dtype=dtype), quantize_scales=False, learnable_amax=["pre", "post"], + dtype=dtype, ) assert q._amax_pre.dtype == dtype @@ -238,7 +240,6 @@ def test_learnable_amax_uses_input_dtype(self, dtype): def test_dtype_cast_updates_learnable_amax_dtype(self): q = self._make_quantizer() q.enable_lsq( - torch.ones(8), quantize_scales=False, learnable_amax=["pre", "post"], ) @@ -258,7 +259,6 @@ def test_align_lsq_amax_param_dtypes_uses_weight_dtype(self): module.weight = nn.Parameter(torch.ones(8, 16, dtype=torch.bfloat16)) module.weight_quantizer = self._make_quantizer() module.weight_quantizer.enable_lsq( - torch.ones(8), quantize_scales=False, learnable_amax=["pre", "post"], ) @@ -375,12 +375,9 @@ def _make_lsq_quantizer(self, learnable_amax=("post",), tied_amax=False): tq._disabled = False tq._block_sizes = {-1: 16} tq._pass_through_bwd = True - tq.register_buffer("_amax", torch.ones(4)) + tq.register_buffer("_amax", torch.ones(4) * 3.5) sbsq = StaticBlockScaleQuantizer.from_tensor_quantizer(tq) - amax = torch.ones(4) * 3.5 - sbsq.enable_lsq( - amax, quantize_scales=False, learnable_amax=learnable_amax, tied_amax=tied_amax - ) + sbsq.enable_lsq(quantize_scales=False, learnable_amax=learnable_amax, tied_amax=tied_amax) return sbsq def test_output_shape(self): @@ -424,39 +421,96 @@ def test_skip_pre_scale_quantization_still_quantizes_post(self, monkeypatch): q = self._make_lsq_quantizer() q._quantize_scales = True q._quantize_pre_scale = False - q.register_buffer("_per_tensor_scale", torch.tensor(1.0)) - calls = [] + # per_tensor_scale of 1.0: INT4 _quant_max_bound is 7.0, so scale = global_amax / 7. + q.global_amax = torch.tensor(float(q._quant_max_bound)) + quantize_flags = [] + orig_block_scale = q._block_scale_from_amax - def spy_maybe_quantize_scale(scale_raw): - calls.append(scale_raw) - return scale_raw + def spy_block_scale(amax, quantize): + quantize_flags.append(quantize) + return orig_block_scale(amax, quantize) - monkeypatch.setattr(q, "_maybe_quantize_scale", spy_maybe_quantize_scale) + monkeypatch.setattr(q, "_block_scale_from_amax", spy_block_scale) out = q._fake_quantize(torch.randn(4, 16)) assert out.shape == (4, 16) - assert len(calls) == 1 + # post scale is FP8-quantized, pre scale is not (quantize_pre_scale=False). + assert quantize_flags == [True, False] def test_skip_pre_scale_quantization_uses_raw_scale_floor(self, monkeypatch): q = self._make_lsq_quantizer() q._quantize_scales = True q._quantize_pre_scale = False - q.register_buffer("_per_tensor_scale", torch.tensor(1.0)) + q.global_amax = torch.tensor(float(q._quant_max_bound)) min_values = [] - def fake_amax_to_scale(amax, maxbound, min_value=None): - min_values.append(min_value) + def fake_amax_to_scale(amax, maxbound, min_value=1e-8): + # Only record the per-block (shape-4) scale calls, not per_tensor_scale. + if amax.numel() == 4: + min_values.append(min_value) return torch.ones_like(amax) monkeypatch.setattr( "modelopt.torch.quantization.nn.modules.tensor_quantizer._amax_to_scale", fake_amax_to_scale, ) - monkeypatch.setattr(q, "_maybe_quantize_scale", lambda scale_raw: scale_raw) out = q._fake_quantize(torch.randn(4, 16)) assert out.shape == (4, 16) assert torch.equal(min_values[0], torch.tensor([_FP8_E4M3_MIN_POSITIVE])) assert min_values[1] == 1e-8 + + +class TestLSQSharedGlobalAmax: + """Regression: LSQ must honor the shared/tied weight global_amax invariant. + + A q/k/v-style fusible group ties ``_global_amax`` to a single shared buffer object. + Since LSQ derives ``per_tensor_scale`` from ``global_amax`` at runtime (no snapshot), + an in-place update of the shared buffer (e.g. export unification) must propagate to + every member. Uses INT4 (FP8-quantized scales) members so the forward runs on CPU; + the shared-buffer mechanism under test is format-agnostic. + """ + + def _make_member(self, amax_value=2.0): + tq = TensorQuantizer() + tq._num_bits = 4 + tq._unsigned = False + tq._narrow_range = True + tq._disabled = False + tq._block_sizes = {-1: 16, "type": "static", "scale_bits": (4, 3)} + tq._pass_through_bwd = True + tq.register_buffer("_amax", torch.ones(4) * amax_value) + return StaticBlockScaleQuantizer.from_tensor_quantizer(tq) + + def _make_tied_lsq_group(self, global_amax=3.0, n_members=3): + members = [self._make_member(amax_value=2.0) for _ in range(n_members)] + state = SharedWeightGlobalAmaxState() + state.global_amax = torch.tensor(float(global_amax)) + for member in members: + assert state.tie_member_quantizer(member) + # All members must alias the single shared buffer object. + assert all(m._global_amax is members[0]._global_amax for m in members) + for member in members: + member.enable_lsq(quantize_scales=True) + return members + + def test_per_tensor_scale_tracks_shared_update(self): + members = self._make_tied_lsq_group(global_amax=3.0) + new_value = 5.0 + # Mutate the shared buffer in place, mimicking export unification. + members[0]._global_amax.data.fill_(new_value) + + for member in members: + expected = _amax_to_scale(torch.tensor(new_value), member._quant_max_bound) + assert torch.allclose(member.per_tensor_scale, expected) + + def test_members_produce_identical_output_after_shared_update(self): + members = self._make_tied_lsq_group(global_amax=3.0) + members[0]._global_amax.data.fill_(5.0) + + x = torch.randn(4, 16) + outputs = [member._fake_quantize(x) for member in members] + for out in outputs[1:]: + assert torch.equal(out, outputs[0]) From 1142b23317bd4b69d821f8cd2b5ad83f3e363953 Mon Sep 17 00:00:00 2001 From: realAsma Date: Thu, 9 Jul 2026 20:51:52 +0000 Subject: [PATCH 12/19] Unify static block weight quantizer promotion Merge _promote_integer_static_weight_quantizers into the NVFP4 promotion as promote_static_block_weight_quantizers, iterating weight quantizers via QuantModule.iter_weights_for_calibration (with SequentialQuantizer support) instead of scanning all TensorQuantizers. Keep promote_nvfp4_static_quantizers as a compatibility wrapper and drop the NVFP4StaticQuantizer alias usage in model_calib. Co-Authored-By: Claude Fable 5 Signed-off-by: realAsma --- modelopt/torch/quantization/model_calib.py | 53 ++---------- modelopt/torch/quantization/utils/__init__.py | 2 + .../torch/quantization/utils/core_utils.py | 83 ++++++++++++------- .../torch/quantization/test_mse_calibrator.py | 9 +- 4 files changed, 67 insertions(+), 80 deletions(-) diff --git a/modelopt/torch/quantization/model_calib.py b/modelopt/torch/quantization/model_calib.py index 759cb4dabda..35bb6ebb558 100644 --- a/modelopt/torch/quantization/model_calib.py +++ b/modelopt/torch/quantization/model_calib.py @@ -44,13 +44,7 @@ from .calib import MseCalibrator, NVFP4MSECalibrator, _Calibrator from .conversion import create_and_replace_svdquant_linear_on_the_fly, set_quantizer_by_cfg_context -from .nn import ( - NVFP4StaticQuantizer, - QuantModule, - SequentialQuantizer, - StaticBlockScaleQuantizer, - TensorQuantizer, -) +from .nn import QuantModule, SequentialQuantizer, StaticBlockScaleQuantizer, TensorQuantizer from .utils import ( SHARED_PATTERNS, SharedWeightGlobalAmaxState, @@ -62,7 +56,7 @@ is_quantized_linear, is_quantized_row_parallel_linear, persistent_materialization, - promote_nvfp4_static_quantizers, + promote_static_block_weight_quantizers, ) from .utils.calib_utils import _GPTQ_HELPER_REGISTRY, GPTQHelper @@ -85,7 +79,7 @@ def _collect_weight_stats(quantizer: nn.Module, weight: torch.Tensor) -> None: def _is_calibrated_nvfp4_static(q) -> bool: """True iff ``q`` is an enabled NVFP4-static weight quantizer with ``_amax`` set.""" return ( - isinstance(q, NVFP4StaticQuantizer) + isinstance(q, StaticBlockScaleQuantizer) and not q._disabled and q.is_nvfp4_static and getattr(q, "_amax", None) is not None @@ -139,48 +133,17 @@ def _check_grouped_weight_global_amax_synced(model: nn.Module) -> None: ) -def _promote_integer_static_weight_quantizers(model: nn.Module) -> None: - """Promote calibrated integer static-block weight quantizers for LSQ.""" - candidate_ids = { - id(module) - for module in model.modules() - if isinstance(module, TensorQuantizer) - and module.is_enabled - and module.is_static_block_quant - and isinstance(module._num_bits, int) - and getattr(module, "_amax", None) is not None - } - if not candidate_ids: - return - - name_to_module = dict(model.named_modules()) - seen_modules: set[int] = set() - for module in name_to_module.values(): - if id(module) in seen_modules or not isinstance(module, QuantModule): - continue - seen_modules.add(id(module)) - with enable_weight_access_and_writeback(module, model, name_to_module): - for _, quantizer in module.iter_weights_for_calibration(): - if id(quantizer) not in candidate_ids: - continue - StaticBlockScaleQuantizer.from_tensor_quantizer(quantizer) - candidate_ids.remove(id(quantizer)) - if not candidate_ids: - return - - def _finalize_with_shared_state(model: nn.Module, weight_patterns: list[str]) -> None: """Finalize calibrated static quantizers and attached shared state. Aggregates each fusible group's shared weight ``global_amax`` and promotes it onto the member NVFP4-static quantizers, so siblings read the unified value instead of their own - ``_amax``. Promotes integer static-block weight quantizers after their ``_amax`` is final. - Under the default patterns, verifies the name groups were actually synced. - Call once ``_amax`` is final: single-process, or after the distributed amax sync. + ``_amax``. Promotes static-block weight quantizers after their ``_amax`` is final. Under + the default patterns, verifies the name groups were actually synced. Call once ``_amax`` + is final: single-process, or after the distributed amax sync. """ SharedWeightGlobalAmaxState.populate(model) - promote_nvfp4_static_quantizers(model) - _promote_integer_static_weight_quantizers(model) + promote_static_block_weight_quantizers(model) # Under the default patterns, verify the fusible name groups were actually synced. if weight_patterns == list(SHARED_PATTERNS): _check_grouped_weight_global_amax_synced(model) @@ -2026,7 +1989,7 @@ def gptq( Per-module steps: 1. ``max_calibrate`` to set amax values from the current activations. - 2. Promote eligible quantizers to ``NVFP4StaticQuantizer`` (two-level scaling). + 2. Promote eligible quantizers to ``StaticBlockScaleQuantizer`` (two-level scaling). 3. Collect per-linear-layer Hessian matrices via forward hooks. 4. Blockwise weight updates using the inverse Hessian to compensate for rounding error (the core GPTQ column-wise update). diff --git a/modelopt/torch/quantization/utils/__init__.py b/modelopt/torch/quantization/utils/__init__.py index 69969b2554d..9fb7eacffaf 100644 --- a/modelopt/torch/quantization/utils/__init__.py +++ b/modelopt/torch/quantization/utils/__init__.py @@ -34,6 +34,8 @@ "is_quantized_linear", "is_quantized_row_parallel_linear", "iter_shared_quant_states", + "promote_nvfp4_static_quantizers", + "promote_static_block_weight_quantizers", "reduce_amax", "reduce_sum", "replace_function", diff --git a/modelopt/torch/quantization/utils/core_utils.py b/modelopt/torch/quantization/utils/core_utils.py index 478788c4f1c..5c839f050ad 100644 --- a/modelopt/torch/quantization/utils/core_utils.py +++ b/modelopt/torch/quantization/utils/core_utils.py @@ -962,8 +962,8 @@ def update_quant_cfg_with_kv_cache_quant( return quant_cfg -def promote_nvfp4_static_quantizers(model: nn.Module) -> int: - """Convert eligible TensorQuantizers to NVFP4StaticQuantizer in-place. +def promote_static_block_weight_quantizers(model: nn.Module) -> int: + """Convert eligible static-block weight TensorQuantizers in-place. After max calibration sets per-block amax values, NVFP4 static quantizers need to be promoted so they use the two-level scaling path (global amax + @@ -973,9 +973,14 @@ def promote_nvfp4_static_quantizers(model: nn.Module) -> int: ``model``, the promoted quantizer's ``_global_amax`` buffer is tied to that canonical state buffer instead of receiving an independent copy. - Returns the number of quantizers converted. + Returns the number of NVFP4 quantizers converted. """ - from modelopt.torch.quantization.nn import NVFP4StaticQuantizer, TensorQuantizer + from modelopt.torch.quantization.nn import ( + QuantModule, + SequentialQuantizer, + StaticBlockScaleQuantizer, + TensorQuantizer, + ) from modelopt.torch.quantization.utils.shared_input import ( SharedWeightGlobalAmaxState, iter_shared_quant_states, @@ -988,33 +993,51 @@ def promote_nvfp4_static_quantizers(model: nn.Module) -> int: for state in iter_shared_quant_states(model, SharedWeightGlobalAmaxState) for quantizer in state._member_quantizers() } - converted = 0 for _name, module in list(model.named_modules()): - if not isinstance(module, TensorQuantizer) or not module.is_enabled: - continue - if not module.is_nvfp4_static: + if not isinstance(module, QuantModule): continue - amax = module.amax - if amax is None: - continue - - # Grouped siblings share one canonical global_amax (common FP8 grid); otherwise - # fall back to this quantizer's own per-block amax. - already_promoted = isinstance(module, NVFP4StaticQuantizer) - shared = shared_by_quantizer.get(id(module)) - if shared is not None and shared.global_amax is not None: - NVFP4StaticQuantizer.from_tensor_quantizer(module) - shared.tie_member_quantizer(module) - else: - if shared is not None and not amax.is_meta: - raise RuntimeError( - f"{_name}: weight quantizer is in a shared group whose global_amax was not " - "populated before promotion; run populate after calibration so siblings " - "share one scale instead of falling back to their own." - ) - global_amax = reduce_amax(amax.clone().detach(), axis=None) - NVFP4StaticQuantizer.from_tensor_quantizer(module, global_amax=global_amax) - if not already_promoted: - converted += 1 + for _, quantizer in module.iter_weights_for_calibration(): + if isinstance(quantizer, SequentialQuantizer): + if len(quantizer) == 0: + continue + quantizer = quantizer[0] + if not isinstance(quantizer, TensorQuantizer): + continue + quantizer_id = id(quantizer) + if not quantizer.is_enabled or not quantizer.is_static_block_quant: + continue + amax = quantizer.amax + if amax is None: + continue + if quantizer.is_nvfp4_static: + # Grouped siblings share one canonical global_amax (common FP8 grid); otherwise + # fall back to this quantizer's own per-block amax. + already_promoted = isinstance(quantizer, StaticBlockScaleQuantizer) + shared = shared_by_quantizer.get(quantizer_id) + if shared is not None and shared.global_amax is not None: + StaticBlockScaleQuantizer.from_tensor_quantizer(quantizer) + shared.tie_member_quantizer(quantizer) + else: + if shared is not None and not amax.is_meta: + raise RuntimeError( + f"{_name}: weight quantizer is in a shared group whose global_amax was " + "not populated before promotion; run populate after calibration so " + "siblings share one scale instead of falling back to their own." + ) + global_amax = reduce_amax(amax.clone().detach(), axis=None) + StaticBlockScaleQuantizer.from_tensor_quantizer( + quantizer, global_amax=global_amax + ) + if not already_promoted: + converted += 1 + elif isinstance(quantizer._num_bits, int): + # Integer static-block weights are promoted so LSQ can use + # StaticBlockScaleQuantizer. + StaticBlockScaleQuantizer.from_tensor_quantizer(quantizer) return converted + + +def promote_nvfp4_static_quantizers(model: nn.Module) -> int: + """Compatibility wrapper for static-block weight quantizer promotion.""" + return promote_static_block_weight_quantizers(model) diff --git a/tests/unit/torch/quantization/test_mse_calibrator.py b/tests/unit/torch/quantization/test_mse_calibrator.py index df63e51de20..b472d379000 100644 --- a/tests/unit/torch/quantization/test_mse_calibrator.py +++ b/tests/unit/torch/quantization/test_mse_calibrator.py @@ -26,7 +26,7 @@ _register_fp8_sweep_calibrator, mse_calibrate, ) -from modelopt.torch.quantization.nn import NVFP4StaticQuantizer, TensorQuantizer +from modelopt.torch.quantization.nn import NVFP4StaticQuantizer, QuantLinear, TensorQuantizer from modelopt.torch.quantization.nn.modules.tensor_quantizer import ( _QUANT_FUNCTIONAL_BACKENDS, register_quant_backend, @@ -645,7 +645,7 @@ def test_modelopt_static_nvfp4_uses_fp8_scale_sweep(self): ), amax=torch.tensor([1.0, 2.0]), ) - model = torch.nn.Module() + model = QuantLinear(16, 1, bias=False) model.weight_quantizer = q promote_nvfp4_static_quantizers(model) @@ -737,10 +737,9 @@ def forward(self, x): class TestStaticNVFP4Promotion: - class _LinearLike(torch.nn.Module): + class _LinearLike(QuantLinear): def __init__(self, amax): - super().__init__() - self.weight = torch.nn.Parameter(torch.empty(1, 16)) + super().__init__(16, 1, bias=False) cfg = QuantizerAttributeConfig( num_bits=(2, 1), block_sizes={-1: 16, "type": "static", "scale_bits": (4, 3)}, From 67f4d20370ee0a82a6a86a71905e629db799f469 Mon Sep 17 00:00:00 2001 From: realAsma Date: Thu, 9 Jul 2026 21:05:16 +0000 Subject: [PATCH 13/19] Simplify scale calibration dispatch Signed-off-by: realAsma --- modelopt/torch/quantization/model_calib.py | 31 +++++----------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/modelopt/torch/quantization/model_calib.py b/modelopt/torch/quantization/model_calib.py index 35bb6ebb558..2a8f9dba1bb 100644 --- a/modelopt/torch/quantization/model_calib.py +++ b/modelopt/torch/quantization/model_calib.py @@ -16,7 +16,6 @@ """Calibration utilities.""" import fnmatch -import inspect import math import time import warnings @@ -318,7 +317,7 @@ def max_calibrate( for name, module in model.named_modules(): if isinstance(module, QuantModule) and _has_expert_parallelism(module): for child in module.children(): - if isinstance(child, (TensorQuantizer, SequentialQuantizer)): + if isinstance(child, TensorQuantizer | SequentialQuantizer): _check_moe_calibration_complete(child, module.parallel_state) def sync_quantizer_amax_across_dp_ep(quantizer, parallel_state, parent_name, child_name): @@ -337,7 +336,7 @@ def sync_quantizer_amax_across_dp_ep(quantizer, parallel_state, parent_name, chi for name, module in model.named_modules(): if isinstance(module, QuantModule): for child_name, child in module.named_children(): - if isinstance(child, (TensorQuantizer, SequentialQuantizer)): + if isinstance(child, TensorQuantizer | SequentialQuantizer): sync_quantizer_amax_across_dp_ep(child, module.parallel_state, name, child_name) # Step 3: TP sync # Objective: the quantization parameters when TP = 8 then changed to TP=4 then back to TP=8 should be the same @@ -2051,38 +2050,22 @@ def _make_gptq_handle(name, m): print_rank_0(f"GPTQ time: {time.time() - total_start:.2f}s") -def _run_scale_calibration(model, forward_loop, scale_algorithm, caller_name): +def _run_scale_calibration(model, forward_loop, scale_algorithm): """Run scale calibration.""" if scale_algorithm is None: scale_algorithm = {"method": "mse"} - method = scale_algorithm.get("method") - supported = ("mse", "local_hessian", "max") - assert method in supported, f"{caller_name}: method must be one of {supported}, got '{method}'" - if isinstance(scale_algorithm, ModeloptBaseConfig): scale_algorithm = scale_algorithm.model_dump(exclude_unset=True) + + method = scale_algorithm.get("method") algo_kwargs = {k: v for k, v in scale_algorithm.items() if k != "method"} calib_funcs = { "mse": mse_calibrate, "local_hessian": local_hessian_calibrate, "max": max_calibrate, } - calib_func = calib_funcs[method] - accepted = { - name - for name, p in inspect.signature(calib_func).parameters.items() - if p.kind not in (inspect.Parameter.VAR_KEYWORD, inspect.Parameter.VAR_POSITIONAL) - } - ignored = sorted(k for k in algo_kwargs if k not in accepted) - if ignored: - warnings.warn( - f"{caller_name}: scale_algorithm kwargs {ignored} are not supported by " - f"'{method}' calibration and will be ignored.", - stacklevel=2, - ) - algo_kwargs = {k: v for k, v in algo_kwargs.items() if k in accepted} - calib_func(model, forward_loop=forward_loop, **algo_kwargs) + calib_funcs[method](model, forward_loop=forward_loop, **algo_kwargs) @torch.no_grad() @@ -2111,7 +2094,7 @@ def lsq( tied_amax: If True, pre and post share a single tensor. quantize_pre_scale: If False, skip FP8 quantization for the LSQ pre scale. """ - _run_scale_calibration(model, forward_loop, scale_algorithm, "lsq") + _run_scale_calibration(model, forward_loop, scale_algorithm) name_to_module = dict(model.named_modules()) seen_modules: set[int] = set() From 27da9d6d2cea033db2e7cf34232931a57f33a77c Mon Sep 17 00:00:00 2001 From: realAsma Date: Thu, 9 Jul 2026 21:32:02 +0000 Subject: [PATCH 14/19] Move scale calib alias into LSQ config Signed-off-by: realAsma --- modelopt/torch/quantization/config.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/modelopt/torch/quantization/config.py b/modelopt/torch/quantization/config.py index cd62837725c..fefb9e9b025 100644 --- a/modelopt/torch/quantization/config.py +++ b/modelopt/torch/quantization/config.py @@ -153,7 +153,7 @@ import re import warnings from collections.abc import Mapping, Sequence -from typing import Any, Literal +from typing import Any, ClassVar, Literal from pydantic import ( AliasChoices, @@ -1020,9 +1020,6 @@ class LocalHessianCalibConfig(_SharedStatesConfig, QuantizeAlgorithmConfig): ) -ScaleCalibConfig = MaxCalibConfig | MseCalibConfig | LocalHessianCalibConfig - - class SmoothQuantCalibConfig(QuantizeAlgorithmConfig): """The config for ``smoothquant`` algorithm (SmoothQuant). @@ -1244,6 +1241,8 @@ class LSQConfig(QuantizeAlgorithmConfig): while preserving the existing post-scale quantization behavior. """ + ScaleCalibConfig: ClassVar = MaxCalibConfig | MseCalibConfig | LocalHessianCalibConfig + method: Literal["lsq"] = ModeloptField("lsq") learnable_amax: list[Literal["pre", "post"]] | Literal["pre", "post"] = ModeloptField( From 70ba41787cb3917724e52df1479a31bd09115912 Mon Sep 17 00:00:00 2001 From: realAsma Date: Thu, 9 Jul 2026 22:21:27 +0000 Subject: [PATCH 15/19] Fix LSQ scale calibration config typing Signed-off-by: realAsma --- modelopt/torch/quantization/config.py | 10 ++++++---- tests/unit/torch/quantization/test_lsq.py | 4 +--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modelopt/torch/quantization/config.py b/modelopt/torch/quantization/config.py index fefb9e9b025..6b5bd9b3c21 100644 --- a/modelopt/torch/quantization/config.py +++ b/modelopt/torch/quantization/config.py @@ -153,7 +153,7 @@ import re import warnings from collections.abc import Mapping, Sequence -from typing import Any, ClassVar, Literal +from typing import Any, ClassVar, Literal, TypeAlias from pydantic import ( AliasChoices, @@ -1210,6 +1210,8 @@ def _gptq_qdq_default(self): ) return self +_ScaleCalibConfig: TypeAlias = MaxCalibConfig | MseCalibConfig | LocalHessianCalibConfig + class LSQConfig(QuantizeAlgorithmConfig): """Config for LSQ (Learnt Scale Quantization) and Dual-LSQ algorithms. @@ -1241,7 +1243,7 @@ class LSQConfig(QuantizeAlgorithmConfig): while preserving the existing post-scale quantization behavior. """ - ScaleCalibConfig: ClassVar = MaxCalibConfig | MseCalibConfig | LocalHessianCalibConfig + ScaleCalibConfig: ClassVar[Any] = _ScaleCalibConfig method: Literal["lsq"] = ModeloptField("lsq") @@ -1273,7 +1275,7 @@ class LSQConfig(QuantizeAlgorithmConfig): ), ) - scale_algorithm: ScaleCalibConfig | None = ModeloptField( + scale_algorithm: _ScaleCalibConfig | None = ModeloptField( default=None, title="Scale calibration algorithm to run first.", description=( @@ -1284,7 +1286,7 @@ class LSQConfig(QuantizeAlgorithmConfig): ) @field_serializer("scale_algorithm") - def _serialize_scale_algorithm(self, value: ScaleCalibConfig | None): + def _serialize_scale_algorithm(self, value: _ScaleCalibConfig | None): """Preserve the sparse public dict shape accepted by this field.""" if value is None: return None diff --git a/tests/unit/torch/quantization/test_lsq.py b/tests/unit/torch/quantization/test_lsq.py index a81fe7e22b5..e6cb43bd59f 100644 --- a/tests/unit/torch/quantization/test_lsq.py +++ b/tests/unit/torch/quantization/test_lsq.py @@ -129,9 +129,7 @@ def test_scale_algorithm_preserves_sparse_dict(self, monkeypatch): calibrate = create_autospec(model_calib_module.mse_calibrate) monkeypatch.setattr(model_calib_module, "mse_calibrate", calibrate) model = Mock() - model_calib_module._run_scale_calibration( - model, None, cfg.scale_algorithm, caller_name="lsq" - ) + model_calib_module._run_scale_calibration(model, None, cfg.scale_algorithm) calibrate.assert_called_once_with(model, forward_loop=None, fp8_scale_sweep=True) @pytest.mark.parametrize( From 0873ad1148d9bdfc34c49bc98d0227b19634e7fb Mon Sep 17 00:00:00 2001 From: realAsma Date: Fri, 10 Jul 2026 12:32:23 +0000 Subject: [PATCH 16/19] Fix static quantizer meta materialization Signed-off-by: realAsma --- modelopt/torch/quantization/config.py | 1 + .../torch/quantization/nn/modules/tensor_quantizer.py | 4 ++-- tests/unit/torch/quantization/test_lsq.py | 11 +++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/modelopt/torch/quantization/config.py b/modelopt/torch/quantization/config.py index 6b5bd9b3c21..8973ec28ed0 100644 --- a/modelopt/torch/quantization/config.py +++ b/modelopt/torch/quantization/config.py @@ -1210,6 +1210,7 @@ def _gptq_qdq_default(self): ) return self + _ScaleCalibConfig: TypeAlias = MaxCalibConfig | MseCalibConfig | LocalHessianCalibConfig diff --git a/modelopt/torch/quantization/nn/modules/tensor_quantizer.py b/modelopt/torch/quantization/nn/modules/tensor_quantizer.py index 69cebc59a16..716b8c4c429 100644 --- a/modelopt/torch/quantization/nn/modules/tensor_quantizer.py +++ b/modelopt/torch/quantization/nn/modules/tensor_quantizer.py @@ -1612,9 +1612,9 @@ def _apply(self, fn, recurse=True): module = super()._apply(fn, recurse=recurse) self._preserve_amax_in_fp32() - if amax is not None: + if amax is not None and amax.device.type != "meta": self.amax = amax - if global_amax is not None: + if global_amax is not None and global_amax.device.type != "meta": self.global_amax = global_amax return module diff --git a/tests/unit/torch/quantization/test_lsq.py b/tests/unit/torch/quantization/test_lsq.py index e6cb43bd59f..2db91f53b47 100644 --- a/tests/unit/torch/quantization/test_lsq.py +++ b/tests/unit/torch/quantization/test_lsq.py @@ -41,6 +41,7 @@ ) from modelopt.torch.quantization.tensor_quant import int_cast_ste from modelopt.torch.quantization.utils.shared_input import SharedWeightGlobalAmaxState +from modelopt.torch.utils import to_empty_if_meta_device def _make_int4_static_quantizer(): @@ -269,6 +270,16 @@ def test_align_lsq_amax_param_dtypes_uses_weight_dtype(self): assert module.weight_quantizer._amax_pre.dtype == torch.bfloat16 assert module.weight_quantizer._amax_post.dtype == torch.bfloat16 + def test_to_empty_if_meta_device_materializes_static_amax(self): + q = self._make_quantizer() + q._amax = q._amax.to("meta") + q.global_amax = torch.tensor(1.0, device="meta") + + to_empty_if_meta_device(q, device=torch.device("cpu")) + + assert q._amax.device.type == "cpu" + assert q.global_amax.device.type == "cpu" + class TestLSQWeightIteration: """Tests LSQ conversion for each weight exposed by QuantModule's iterator contract.""" From 726be8f6aa09e9b395245dc44cd29dabd38fbbcf Mon Sep 17 00:00:00 2001 From: realAsma Date: Fri, 10 Jul 2026 21:36:42 +0000 Subject: [PATCH 17/19] Revert quantize recipe rename Signed-off-by: realAsma --- CHANGELOG.rst | 1 - docs/source/guides/10_recipes.rst | 5 ++-- docs/source/guides/11_config_system.rst | 2 +- examples/hf_ptq/hf_ptq.py | 6 ++--- examples/llm_qat/simple_qat_train.py | 4 +-- examples/megatron_bridge/quantize.py | 4 +-- examples/torch_trt/torch_tensorrt_ptq.py | 4 +-- examples/vllm_serve/vllm_ptq_utils.py | 4 +-- modelopt/recipe/config.py | 26 +++++-------------- modelopt/recipe/loader.py | 12 +++------ .../plugins/transformers_trainer.py | 4 +-- .../general/ptq/nvfp4_default-kv_fp8.yaml | 2 +- .../qad/nvfp4_dual_lsq-mse_init-fp8_kv.yaml | 2 +- .../qad/nvfp4_lsq-mse_init-fp8_kv.yaml | 2 +- tests/unit/recipe/test_loader.py | 22 +++------------- tests/unit/recipe/test_lsq_recipes.py | 2 +- 16 files changed, 34 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6319ea412a5..d40ba8de1ce 100755 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -11,7 +11,6 @@ Changelog **Deprecations** -- Renamed ``modelopt.recipe.ModelOptPTQRecipe`` to ``ModelOptQuantizeRecipe`` because it now backs the ``ptq``, ``qat/qad``, and ``ptq/qat/qad`` recipe types (not just PTQ). The old ``ModelOptPTQRecipe`` name remains as a **deprecated alias** of ``ModelOptQuantizeRecipe`` and will be removed in a future release. Please update imports and ``isinstance`` checks to the new name. - ``examples/hf_ptq`` AutoQuantize is now driven by an **AutoQuantize recipe** (``--recipe``). The ``--auto_quantize_bits``, ``--auto_quantize_method``, ``--auto_quantize_score_size``, ``--auto_quantize_cost_model``, and ``--auto_quantize_active_moe_expert_ratio`` flags are **deprecated** but still work: they are converted into an ``AutoQuantizeConfig`` on the fly (emitting a ``DeprecationWarning``) and will be removed in a future release. Prefer a recipe under ``modelopt_recipes/general/auto_quantize/``. See ``examples/hf_ptq/README.md``. - Renamed ``examples/llm_ptq`` to ``examples/hf_ptq`` to reflect that it covers Hugging Face LLM **and** VLM PTQ. A relative symlink ``examples/llm_ptq`` -> ``hf_ptq`` keeps existing paths and commands working; it will be removed in a future release. Please update references to the new ``examples/hf_ptq`` path. diff --git a/docs/source/guides/10_recipes.rst b/docs/source/guides/10_recipes.rst index fa114c10289..ba96b823fe8 100644 --- a/docs/source/guides/10_recipes.rst +++ b/docs/source/guides/10_recipes.rst @@ -720,9 +720,8 @@ Recipes are validated at load time using Pydantic models: :class:`~modelopt.torch.opt.config.ModeloptBaseConfig` subclass exposing ``recipe_type`` and ``description`` as Pydantic fields. -:class:`~modelopt.recipe.config.ModelOptQuantizeRecipe` - Quantization recipe (PTQ, QAT/QAD, or both). Adds a required ``quantize`` - field typed as +:class:`~modelopt.recipe.config.ModelOptPTQRecipe` + PTQ-specific recipe. Adds a required ``quantize`` field typed as :class:`~modelopt.torch.quantization.config.QuantizeConfig` (also a ``ModeloptBaseConfig`` subclass, containing ``quant_cfg`` and ``algorithm``). diff --git a/docs/source/guides/11_config_system.rst b/docs/source/guides/11_config_system.rst index 0ee6ecd4933..cb659c2482a 100644 --- a/docs/source/guides/11_config_system.rst +++ b/docs/source/guides/11_config_system.rst @@ -529,7 +529,7 @@ the speculative-decoding variants); ``metadata`` is required for all types. ``metadata.recipe_type``, picks the matching recipe schema, and calls ``load_config(file, schema_type=schema)`` so list-typed ``$import`` resolution knows the element types. The returned object is a validated recipe instance - (for example a ``ModelOptQuantizeRecipe``). + (for example a ``ModelOptPTQRecipe``). * A **directory recipe** is a directory containing ``metadata.yml`` / ``metadata.yaml`` and ``quantize.yml`` / ``quantize.yaml``. Each file is loaded with its own schema (``RecipeMetadataConfig`` and ``QuantizeConfig``, diff --git a/examples/hf_ptq/hf_ptq.py b/examples/hf_ptq/hf_ptq.py index 2e8e087a64e..8dcc78afa27 100755 --- a/examples/hf_ptq/hf_ptq.py +++ b/examples/hf_ptq/hf_ptq.py @@ -56,7 +56,7 @@ import modelopt.torch.opt as mto import modelopt.torch.quantization as mtq import modelopt.torch.sparsity as mts -from modelopt.recipe import ModelOptAutoQuantizeRecipe, ModelOptQuantizeRecipe, load_recipe +from modelopt.recipe import ModelOptAutoQuantizeRecipe, ModelOptPTQRecipe, load_recipe from modelopt.recipe.presets import KV_CACHE_NONE, KV_QUANT_CFG_CHOICES, QUANT_CFG_CHOICES from modelopt.torch.export import ( export_hf_checkpoint, @@ -1072,7 +1072,7 @@ def quantize_main( if args.recipe is not None: print(f"Use recipe {args.recipe} for quantization") recipe = load_recipe(args.recipe) - if not isinstance(recipe, (ModelOptQuantizeRecipe, ModelOptAutoQuantizeRecipe)): + if not isinstance(recipe, (ModelOptPTQRecipe, ModelOptAutoQuantizeRecipe)): raise TypeError( f"Expected PTQ or AutoQuantize recipe, but got {type(recipe).__name__} " f"from {args.recipe}" @@ -1093,7 +1093,7 @@ def quantize_main( aq_config = None def _is_layerwise(obj): - if isinstance(obj, ModelOptQuantizeRecipe): + if isinstance(obj, ModelOptPTQRecipe): return _is_layerwise(obj.quantize.algorithm) if isinstance(obj, list): return any(_is_layerwise(a) for a in obj) diff --git a/examples/llm_qat/simple_qat_train.py b/examples/llm_qat/simple_qat_train.py index 7c33853c710..e3c3231494c 100644 --- a/examples/llm_qat/simple_qat_train.py +++ b/examples/llm_qat/simple_qat_train.py @@ -26,7 +26,7 @@ import modelopt.torch.opt as mto import modelopt.torch.quantization as mtq -from modelopt.recipe import ModelOptQuantizeRecipe, load_recipe +from modelopt.recipe import ModelOptPTQRecipe, load_recipe def get_dataloader(args, tokenizer): @@ -131,7 +131,7 @@ def calibrate(m: nn.Module): # Load recipe and quantize the model recipe = load_recipe(args.recipe) - if not isinstance(recipe, ModelOptQuantizeRecipe): + if not isinstance(recipe, ModelOptPTQRecipe): raise ValueError(f"Expected PTQ recipe, but got {type(recipe).__name__} from {args.recipe}") model = mtq.quantize(model, recipe.quantize, calibrate) diff --git a/examples/megatron_bridge/quantize.py b/examples/megatron_bridge/quantize.py index 5045e994137..d57e74277c6 100644 --- a/examples/megatron_bridge/quantize.py +++ b/examples/megatron_bridge/quantize.py @@ -65,7 +65,7 @@ import modelopt.torch.quantization as mtq import modelopt.torch.utils.distributed as dist -from modelopt.recipe import ModelOptQuantizeRecipe, load_recipe +from modelopt.recipe import ModelOptPTQRecipe, load_recipe from modelopt.recipe.presets import KV_CACHE_NONE, KV_QUANT_CFG_CHOICES, QUANT_CFG_CHOICES from modelopt.torch.utils import print_args, print_rank_0, warn_rank_0 from modelopt.torch.utils.dataset_utils import get_supported_datasets @@ -227,7 +227,7 @@ def get_quant_config(args: argparse.Namespace) -> dict: "--recipe is set; the recipe is authoritative." ) recipe = load_recipe(args.recipe) - if not isinstance(recipe, ModelOptQuantizeRecipe): + if not isinstance(recipe, ModelOptPTQRecipe): raise TypeError( f"Expected a PTQ recipe but got {type(recipe).__name__} from {args.recipe}" ) diff --git a/examples/torch_trt/torch_tensorrt_ptq.py b/examples/torch_trt/torch_tensorrt_ptq.py index fa4b5becbfd..dcd60534de7 100644 --- a/examples/torch_trt/torch_tensorrt_ptq.py +++ b/examples/torch_trt/torch_tensorrt_ptq.py @@ -41,7 +41,7 @@ import modelopt.torch.opt as mto import modelopt.torch.quantization as mtq -from modelopt.recipe import ModelOptQuantizeRecipe, load_recipe +from modelopt.recipe import ModelOptPTQRecipe, load_recipe from modelopt.torch.quantization.utils import export_torch_mode # Default ViT PTQ recipe under `modelopt_recipes/huggingface/vit/ptq/`. The @@ -97,7 +97,7 @@ def quantize_with_recipe(model, recipe_path: str, calib_batches): """Resolve the YAML recipe and run `mtq.quantize`.""" print(f"Loading recipe: {recipe_path}") recipe = load_recipe(recipe_path) - if not isinstance(recipe, ModelOptQuantizeRecipe): + if not isinstance(recipe, ModelOptPTQRecipe): raise TypeError(f"Expected PTQ recipe, got {type(recipe).__name__}") quant_cfg = recipe.quantize.model_dump() diff --git a/examples/vllm_serve/vllm_ptq_utils.py b/examples/vllm_serve/vllm_ptq_utils.py index 4f1cb4c0f88..88b31d54a70 100644 --- a/examples/vllm_serve/vllm_ptq_utils.py +++ b/examples/vllm_serve/vllm_ptq_utils.py @@ -24,7 +24,7 @@ from vllm.v1.core.sched.output import CachedRequestData, NewRequestData, SchedulerOutput import modelopt.torch.quantization as mtq -from modelopt.recipe import ModelOptQuantizeRecipe, load_recipe +from modelopt.recipe import ModelOptPTQRecipe, load_recipe def _create_new_data_cls(data_cls, **kwargs): @@ -144,7 +144,7 @@ def get_quant_config(quant_config: dict[str, Any], model: Any) -> dict[str, Any] if quant_config["recipe_path"]: recipe = load_recipe(quant_config["recipe_path"]) - assert isinstance(recipe, ModelOptQuantizeRecipe), ( + assert isinstance(recipe, ModelOptPTQRecipe), ( f"Expected PTQ recipe, but got {type(recipe).__name__} from {quant_config['recipe_path']}" ) quant_cfg = recipe.quantize diff --git a/modelopt/recipe/config.py b/modelopt/recipe/config.py index f2d268ded22..2cf5a2f0cfb 100644 --- a/modelopt/recipe/config.py +++ b/modelopt/recipe/config.py @@ -43,7 +43,6 @@ "ModelOptEagleRecipe", "ModelOptMedusaRecipe", "ModelOptPTQRecipe", - "ModelOptQuantizeRecipe", "ModelOptRecipeBase", "ModelOptSpeculativeRecipeBase", "RecipeMetadataConfig", @@ -55,8 +54,6 @@ class RecipeType(str, Enum): """List of recipe types. See ``RECIPE_TYPE_TO_CLASS`` at the bottom for the schema mapping.""" PTQ = "ptq" - QAT_QAD = "qat/qad" - PTQ_QAT_QAD = "ptq/qat/qad" AUTO_QUANTIZE = "auto_quantize" SPECULATIVE_EAGLE = "speculative_eagle" SPECULATIVE_DFLASH = "speculative_dflash" @@ -115,24 +112,17 @@ def description(self) -> str: return self.metadata.description -class ModelOptQuantizeRecipe(ModelOptRecipeBase): - """Config class for quantization recipes — PTQ, QAT/QAD, or both. - - ``metadata.recipe_type`` declares which workflow(s) the recipe is intended for. - """ +class ModelOptPTQRecipe(ModelOptRecipeBase): + """Our config class for PTQ recipes.""" quantize: QuantizeConfig = Field( - title="Quantization config", - description="Quantization config containing quant_cfg and algorithm. Required: a " - "quantization recipe without a ``quantize`` section is rejected so that a missing " - "section can't silently fall back to the default INT8 config.", + title="PTQ config", + description="PTQ config containing quant_cfg and algorithm. Required: a PTQ " + "recipe without a ``quantize`` section is rejected so that a missing section " + "can't silently fall back to the default INT8 config.", ) -# Deprecated alias (shipped in 0.43 as ModelOptPTQRecipe); remove in a future release. -ModelOptPTQRecipe = ModelOptQuantizeRecipe - - # Named alias so a shared layer-pattern unit (e.g. configs/auto_quantize/units/base_disabled_layers) # can declare ``modelopt-schema: modelopt.recipe.config.LayerPatternList`` and be spliced into a # ``list[str]`` field — mirrors how base_disable_all is imported into a PTQ quant_cfg list. @@ -368,9 +358,7 @@ class ModelOptMedusaRecipe(ModelOptSpeculativeRecipeBase): # Single source of truth mapping YAML ``metadata.recipe_type`` to its schema class. The loader # uses this for typed-list ``$import`` resolution; add a new entry when introducing a recipe. RECIPE_TYPE_TO_CLASS: dict[RecipeType, type[ModelOptRecipeBase]] = { - RecipeType.PTQ: ModelOptQuantizeRecipe, - RecipeType.QAT_QAD: ModelOptQuantizeRecipe, - RecipeType.PTQ_QAT_QAD: ModelOptQuantizeRecipe, + RecipeType.PTQ: ModelOptPTQRecipe, RecipeType.AUTO_QUANTIZE: ModelOptAutoQuantizeRecipe, RecipeType.SPECULATIVE_EAGLE: ModelOptEagleRecipe, RecipeType.SPECULATIVE_DFLASH: ModelOptDFlashRecipe, diff --git a/modelopt/recipe/loader.py b/modelopt/recipe/loader.py index 0a3c3b42a86..6af6d0a8a7a 100644 --- a/modelopt/recipe/loader.py +++ b/modelopt/recipe/loader.py @@ -29,7 +29,7 @@ from .config import ( RECIPE_TYPE_TO_CLASS, - ModelOptQuantizeRecipe, + ModelOptPTQRecipe, ModelOptRecipeBase, RecipeMetadataConfig, RecipeType, @@ -42,8 +42,6 @@ # must contain 'quantize'" instead of pydantic's generic missing-field error. _REQUIRED_SECTION_PER_RECIPE_TYPE: dict[RecipeType, str] = { RecipeType.PTQ: "quantize", - RecipeType.QAT_QAD: "quantize", - RecipeType.PTQ_QAT_QAD: "quantize", RecipeType.AUTO_QUANTIZE: "auto_quantize", RecipeType.SPECULATIVE_EAGLE: "eagle", RecipeType.SPECULATIVE_DFLASH: "dflash", @@ -226,12 +224,8 @@ def _load_recipe_from_dir(recipe_dir: Path | Traversable) -> ModelOptRecipeBase: metadata_file = _find_recipe_section_file(recipe_dir, "metadata") metadata = load_config(metadata_file, schema_type=RecipeMetadataConfig) - if metadata.recipe_type in { - RecipeType.PTQ, - RecipeType.QAT_QAD, - RecipeType.PTQ_QAT_QAD, - }: + if metadata.recipe_type == RecipeType.PTQ: quantize_file = _find_recipe_section_file(recipe_dir, "quantize") quantize_cfg = load_config(quantize_file, schema_type=QuantizeConfig) - return ModelOptQuantizeRecipe(metadata=metadata, quantize=quantize_cfg) + return ModelOptPTQRecipe(metadata=metadata, quantize=quantize_cfg) raise ValueError(f"Unsupported recipe type: {metadata.recipe_type!r}") diff --git a/modelopt/torch/quantization/plugins/transformers_trainer.py b/modelopt/torch/quantization/plugins/transformers_trainer.py index 00ea9626c3c..053d5de59fb 100644 --- a/modelopt/torch/quantization/plugins/transformers_trainer.py +++ b/modelopt/torch/quantization/plugins/transformers_trainer.py @@ -103,10 +103,10 @@ def resolve_quant_cfg_from_args( recipe_path = getattr(quant_args, "recipe", None) if recipe_path: - from modelopt.recipe import ModelOptQuantizeRecipe, load_recipe + from modelopt.recipe import ModelOptPTQRecipe, load_recipe recipe = load_recipe(recipe_path) - if not isinstance(recipe, ModelOptQuantizeRecipe): + if not isinstance(recipe, ModelOptPTQRecipe): raise ValueError( f"Expected PTQ recipe, but got {type(recipe).__name__} from {recipe_path}" ) diff --git a/modelopt_recipes/general/ptq/nvfp4_default-kv_fp8.yaml b/modelopt_recipes/general/ptq/nvfp4_default-kv_fp8.yaml index 5a83d2bdc86..9be27b7bae9 100644 --- a/modelopt_recipes/general/ptq/nvfp4_default-kv_fp8.yaml +++ b/modelopt_recipes/general/ptq/nvfp4_default-kv_fp8.yaml @@ -22,7 +22,7 @@ imports: kv_fp8: configs/ptq/units/kv_fp8 metadata: - recipe_type: ptq/qat/qad + recipe_type: ptq description: >- Composes dynamic NVFP4 W4A4 model quantization with FP8 KV-cache quantization for PTQ, QAT, and QAD; uses max calibration. diff --git a/modelopt_recipes/general/qad/nvfp4_dual_lsq-mse_init-fp8_kv.yaml b/modelopt_recipes/general/qad/nvfp4_dual_lsq-mse_init-fp8_kv.yaml index 772f24f0fc7..53a9651ed24 100644 --- a/modelopt_recipes/general/qad/nvfp4_dual_lsq-mse_init-fp8_kv.yaml +++ b/modelopt_recipes/general/qad/nvfp4_dual_lsq-mse_init-fp8_kv.yaml @@ -14,7 +14,7 @@ # limitations under the License. metadata: - recipe_type: qat/qad + recipe_type: ptq description: >- Learns separate pre-quantization and post-quantization NVFP4 weight scales with MSE initialization and FP8 scale sweep; uses dynamic NVFP4 activations and FP8 KV cache. diff --git a/modelopt_recipes/general/qad/nvfp4_lsq-mse_init-fp8_kv.yaml b/modelopt_recipes/general/qad/nvfp4_lsq-mse_init-fp8_kv.yaml index 9f422a229fa..dba0f7d98fe 100644 --- a/modelopt_recipes/general/qad/nvfp4_lsq-mse_init-fp8_kv.yaml +++ b/modelopt_recipes/general/qad/nvfp4_lsq-mse_init-fp8_kv.yaml @@ -14,7 +14,7 @@ # limitations under the License. metadata: - recipe_type: qat/qad + recipe_type: ptq description: >- Learns one shared pre-quantization and post-quantization NVFP4 weight scale with MSE initialization and FP8 scale sweep; uses dynamic NVFP4 activations and FP8 KV cache. diff --git a/tests/unit/recipe/test_loader.py b/tests/unit/recipe/test_loader.py index 90ceb1623a6..3aaacaa3e0e 100644 --- a/tests/unit/recipe/test_loader.py +++ b/tests/unit/recipe/test_loader.py @@ -30,7 +30,7 @@ ModelOptAutoQuantizeRecipe, ModelOptDFlashRecipe, ModelOptEagleRecipe, - ModelOptQuantizeRecipe, + ModelOptPTQRecipe, RecipeType, ) from modelopt.recipe.loader import _apply_dotlist, load_config, load_recipe @@ -138,7 +138,7 @@ def test_load_recipe_builtin_with_suffix(): """load_recipe loads a built-in PTQ recipe given the full YAML path.""" recipe = load_recipe("general/ptq/fp8_default-kv_fp8.yaml") assert recipe.recipe_type == RecipeType.PTQ - assert isinstance(recipe, ModelOptQuantizeRecipe) + assert isinstance(recipe, ModelOptPTQRecipe) assert recipe.quantize @@ -159,6 +159,7 @@ def test_load_recipe_builtin_description(): "general/ptq/fp8_default-kv_fp8", "general/ptq/fp8_default-kv_fp8_cast", "general/ptq/int4_blockwise_weight_only", + "general/ptq/nvfp4_default-kv_fp8", "general/ptq/nvfp4_default-kv_fp8_cast", "general/ptq/nvfp4_default-kv_nvfp4_cast", "general/ptq/nvfp4_default-kv_none-gptq", @@ -180,25 +181,10 @@ def test_load_recipe_all_builtins(recipe_path): """Smoke-test: every built-in PTQ recipe loads without error and has quantize.""" recipe = load_recipe(recipe_path) assert recipe.recipe_type == RecipeType.PTQ - assert isinstance(recipe, ModelOptQuantizeRecipe) + assert isinstance(recipe, ModelOptPTQRecipe) assert recipe.quantize -def test_load_recipe_builtin_shared_across_ptq_qat_qad(): - ptq_recipe = load_recipe("general/ptq/nvfp4_default-kv_fp8") - qad_recipe = load_recipe("general/qad/nvfp4_default-kv_fp8") - - assert ptq_recipe.recipe_type == RecipeType.PTQ_QAT_QAD - assert qad_recipe == ptq_recipe - - -def test_ptq_recipe_deprecated_alias(): - """ModelOptPTQRecipe is a back-compat alias of ModelOptQuantizeRecipe.""" - from modelopt.recipe import ModelOptPTQRecipe, ModelOptQuantizeRecipe - - assert ModelOptPTQRecipe is ModelOptQuantizeRecipe - - def test_nvfp4_weight_only_recipe_disables_vllm_marlin_incompatible_projections(): recipe = load_recipe("general/ptq/nvfp4_weight_only-kv_fp16") disabled_quantizers = { diff --git a/tests/unit/recipe/test_lsq_recipes.py b/tests/unit/recipe/test_lsq_recipes.py index 52451040004..dfc864a4009 100644 --- a/tests/unit/recipe/test_lsq_recipes.py +++ b/tests/unit/recipe/test_lsq_recipes.py @@ -43,7 +43,7 @@ def test_qad_default_nvfp4_recipe_reuses_ptq_recipe(): assert recipe.is_symlink() assert recipe.resolve() == CONFIGS_DIR.parent / "ptq" / recipe.name - assert load_recipe(recipe).recipe_type.value == "ptq/qat/qad" + assert load_recipe(recipe).recipe_type.value == "ptq" @pytest.mark.parametrize( From 6133a91d2bafb8008413dbc22934060fba8aa0a7 Mon Sep 17 00:00:00 2001 From: realAsma Date: Fri, 10 Jul 2026 21:54:16 +0000 Subject: [PATCH 18/19] Remove redundant LSQ per-tensor scale property Signed-off-by: realAsma --- .../nn/modules/tensor_quantizer.py | 48 +++++++------------ tests/unit/torch/quantization/test_lsq.py | 10 ++-- 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/modelopt/torch/quantization/nn/modules/tensor_quantizer.py b/modelopt/torch/quantization/nn/modules/tensor_quantizer.py index 716b8c4c429..ddc7ac2b045 100644 --- a/modelopt/torch/quantization/nn/modules/tensor_quantizer.py +++ b/modelopt/torch/quantization/nn/modules/tensor_quantizer.py @@ -1588,18 +1588,6 @@ def global_amax(self, value): global_amax.data.copy_(value.clone().detach().to(global_amax.device)) self._preserve_amax_in_fp32() - @property - def per_tensor_scale(self): - """Runtime per-tensor scale derived from ``global_amax``. - - Computed on the fly (fp32) rather than snapshotted so that updates to the - possibly tied/shared ``global_amax`` (e.g. export unification of a fusible - sibling group) are always reflected. Returns None when ``global_amax`` is None. - """ - if self.global_amax is None: - return None - return _amax_to_scale(self._global_amax, self._quant_max_bound) - @property def has_quantized_block_scale(self): """True when per-block scales are FP8 (E4M3) quantized (format-only check).""" @@ -1642,8 +1630,8 @@ def enable_lsq( """LSQ mode with configurable learnable/frozen amax tensors. The per-block amax params are initialized from the calibrated ``_amax``. The - per-tensor scale is never materialized; it is derived from ``global_amax`` at - runtime (see ``per_tensor_scale``) so shared-group updates are always reflected. + per-tensor scale is derived from ``global_amax`` at runtime so shared-group + updates are always reflected. Args: quantize_scales: Whether to FP8-quantize per-block scales (NVFP4). When None, @@ -1696,9 +1684,12 @@ def _cast_ste(self, inputs): def _block_scale_from_amax(self, amax: torch.Tensor, quantize: bool) -> torch.Tensor: """Compute the per-block scale from a per-block amax, optionally FP8-quantizing it.""" - min_value = _FP8_E4M3_MIN_POSITIVE * self.per_tensor_scale.view(-1) if quantize else 1e-8 - scale = _amax_to_scale(amax, self._quant_max_bound, min_value=min_value) - return scaled_e4m3(scale, self.per_tensor_scale, None, 4, 3) if quantize else scale + if quantize: + per_tensor_scale = _amax_to_scale(self.global_amax, self._quant_max_bound) + min_value = _FP8_E4M3_MIN_POSITIVE * per_tensor_scale.view(-1) + scale = _amax_to_scale(amax, self._quant_max_bound, min_value=min_value) + return scaled_e4m3(scale, per_tensor_scale, None, 4, 3) + return _amax_to_scale(amax, self._quant_max_bound, min_value=1e-8) def _fake_quantize(self, inputs): """Fake quantization using two-level scaling with _amax and _global_amax.""" @@ -1713,19 +1704,16 @@ def _fake_quantize(self, inputs): w_cast = self._cast_ste(quant_input) return (w_cast * scale_post.view(-1, 1).to(w_cast.dtype)).to(inputs.dtype) - if self.amax is not None: - if self.is_nvfp4_static: - return static_blockwise_fp4_fake_quant( - inputs, - self.amax, - self.global_amax, - True, - fp8_max_for_normalization(self), - inputs.dtype, - self._pass_through_bwd, - ) - else: - return super()._fake_quantize(inputs) + if self.amax is not None and self.is_nvfp4_static: + return static_blockwise_fp4_fake_quant( + inputs, + self.amax, + self.global_amax, + True, + fp8_max_for_normalization(self), + inputs.dtype, + self._pass_through_bwd, + ) return super()._fake_quantize(inputs) diff --git a/tests/unit/torch/quantization/test_lsq.py b/tests/unit/torch/quantization/test_lsq.py index 2db91f53b47..e24ceca9690 100644 --- a/tests/unit/torch/quantization/test_lsq.py +++ b/tests/unit/torch/quantization/test_lsq.py @@ -455,7 +455,7 @@ def test_skip_pre_scale_quantization_uses_raw_scale_floor(self, monkeypatch): min_values = [] def fake_amax_to_scale(amax, maxbound, min_value=1e-8): - # Only record the per-block (shape-4) scale calls, not per_tensor_scale. + # Only record the per-block (shape-4) scale calls, not global scale derivation. if amax.numel() == 4: min_values.append(min_value) return torch.ones_like(amax) @@ -476,7 +476,7 @@ class TestLSQSharedGlobalAmax: """Regression: LSQ must honor the shared/tied weight global_amax invariant. A q/k/v-style fusible group ties ``_global_amax`` to a single shared buffer object. - Since LSQ derives ``per_tensor_scale`` from ``global_amax`` at runtime (no snapshot), + Since LSQ derives the per-tensor scale from ``global_amax`` at runtime (no snapshot), an in-place update of the shared buffer (e.g. export unification) must propagate to every member. Uses INT4 (FP8-quantized scales) members so the forward runs on CPU; the shared-buffer mechanism under test is format-agnostic. @@ -505,7 +505,7 @@ def _make_tied_lsq_group(self, global_amax=3.0, n_members=3): member.enable_lsq(quantize_scales=True) return members - def test_per_tensor_scale_tracks_shared_update(self): + def test_block_scale_tracks_shared_update(self): members = self._make_tied_lsq_group(global_amax=3.0) new_value = 5.0 # Mutate the shared buffer in place, mimicking export unification. @@ -513,7 +513,9 @@ def test_per_tensor_scale_tracks_shared_update(self): for member in members: expected = _amax_to_scale(torch.tensor(new_value), member._quant_max_bound) - assert torch.allclose(member.per_tensor_scale, expected) + scale = member._block_scale_from_amax(member.amax_post, quantize=True) + assert scale.shape == member.amax_post.shape + assert torch.all(scale >= _FP8_E4M3_MIN_POSITIVE * expected) def test_members_produce_identical_output_after_shared_update(self): members = self._make_tied_lsq_group(global_amax=3.0) From 4dd5d6730795dbdf3ac5bea8cc975a48bd8a12e6 Mon Sep 17 00:00:00 2001 From: realAsma Date: Fri, 10 Jul 2026 21:59:57 +0000 Subject: [PATCH 19/19] Remove redundant LSQ amax dtype patch Signed-off-by: realAsma --- .../plugins/transformers_trainer.py | 27 ------------------- tests/unit/torch/quantization/test_lsq.py | 22 --------------- 2 files changed, 49 deletions(-) diff --git a/modelopt/torch/quantization/plugins/transformers_trainer.py b/modelopt/torch/quantization/plugins/transformers_trainer.py index 053d5de59fb..981f3d990d4 100644 --- a/modelopt/torch/quantization/plugins/transformers_trainer.py +++ b/modelopt/torch/quantization/plugins/transformers_trainer.py @@ -38,9 +38,7 @@ disable_lora_quantizers_in_config, get_quantizer_state_dict, is_quantized, - quantizer_attr_names, set_quantizer_state_dict, - weight_attr_names, ) # TODO: Enable documentation rendering for this class @@ -171,29 +169,6 @@ def _patched_post_backward(self): FSDPParamGroup.post_backward = _patched_post_backward -def _align_lsq_amax_param_dtypes(model): - """Cast LSQ learnable amax params to their owning weight dtype for FSDP2.""" - # FSDP2 currently requires all parameters in a module to use the same dtype, - # so align the LSQ amax parameters with their owning weights. - # TODO: Remove this once a stable PyTorch release supports mixed-dtype - # parameters within an FSDP2 module. - for module in model.modules(): - for weight_name in weight_attr_names(module): - weight = getattr(module, weight_name, None) - if weight is None: - continue - - quantizer_name = quantizer_attr_names(weight_name).weight_quantizer - quantizer = getattr(module, quantizer_name, None) - if not isinstance(quantizer, TensorQuantizer) or not getattr(quantizer, "_lsq", False): - continue - - for amax_name in ("_amax_pre", "_amax_post"): - amax = getattr(quantizer, amax_name, None) - if isinstance(amax, torch.nn.Parameter) and amax.dtype != weight.dtype: - amax.data = amax.data.to(dtype=weight.dtype) - - def check_awq_smoothquant(quant_cfg): # TODO: Remove this once deepspeed for AWQ and SmoothQuant is added """Get the quantization type from the configuration.""" @@ -397,8 +372,6 @@ def _modelopt_prepare(self, *args, **kwargs): if model is None: return self._original_prepare(*args, **kwargs) - _align_lsq_amax_param_dtypes(model) - # Hide TQ buffers from accelerate's FSDP2 state_dict handling. tq_og_non_prsist_buffers = {} for tq in (m for m in model.modules() if isinstance(m, TensorQuantizer)): diff --git a/tests/unit/torch/quantization/test_lsq.py b/tests/unit/torch/quantization/test_lsq.py index e24ceca9690..50fd1ffc870 100644 --- a/tests/unit/torch/quantization/test_lsq.py +++ b/tests/unit/torch/quantization/test_lsq.py @@ -248,28 +248,6 @@ def test_dtype_cast_updates_learnable_amax_dtype(self): assert q._amax_pre.dtype == torch.bfloat16 assert q._amax_post.dtype == torch.bfloat16 - def test_align_lsq_amax_param_dtypes_uses_weight_dtype(self): - pytest.importorskip("transformers") - from modelopt.torch.quantization.plugins.transformers_trainer import ( - _align_lsq_amax_param_dtypes, - ) - - module = nn.Module() - module.weight = nn.Parameter(torch.ones(8, 16, dtype=torch.bfloat16)) - module.weight_quantizer = self._make_quantizer() - module.weight_quantizer.enable_lsq( - quantize_scales=False, - learnable_amax=["pre", "post"], - ) - - assert module.weight_quantizer._amax_pre.dtype == torch.float32 - assert module.weight_quantizer._amax_post.dtype == torch.float32 - - _align_lsq_amax_param_dtypes(module) - - assert module.weight_quantizer._amax_pre.dtype == torch.bfloat16 - assert module.weight_quantizer._amax_post.dtype == torch.bfloat16 - def test_to_empty_if_meta_device_materializes_static_amax(self): q = self._make_quantizer() q._amax = q._amax.to("meta")