nvidia-modelopt 0.35.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- modelopt/__init__.py +20 -0
- modelopt/deploy/__init__.py +16 -0
- modelopt/deploy/llm/__init__.py +30 -0
- modelopt/deploy/llm/generate.py +345 -0
- modelopt/onnx/__init__.py +34 -0
- modelopt/onnx/autocast/__init__.py +19 -0
- modelopt/onnx/autocast/__main__.py +187 -0
- modelopt/onnx/autocast/convert.py +202 -0
- modelopt/onnx/autocast/graphsanitizer.py +422 -0
- modelopt/onnx/autocast/logging_config.py +78 -0
- modelopt/onnx/autocast/nodeclassifier.py +416 -0
- modelopt/onnx/autocast/precisionconverter.py +1032 -0
- modelopt/onnx/autocast/referencerunner.py +159 -0
- modelopt/onnx/autocast/utils.py +117 -0
- modelopt/onnx/llm_export_utils/__init__.py +16 -0
- modelopt/onnx/llm_export_utils/export_utils.py +162 -0
- modelopt/onnx/llm_export_utils/quantization_utils.py +122 -0
- modelopt/onnx/llm_export_utils/surgeon_utils.py +120 -0
- modelopt/onnx/logging_config.py +77 -0
- modelopt/onnx/op_types.py +300 -0
- modelopt/onnx/quantization/__init__.py +20 -0
- modelopt/onnx/quantization/__main__.py +291 -0
- modelopt/onnx/quantization/calib_utils.py +178 -0
- modelopt/onnx/quantization/extensions.py +35 -0
- modelopt/onnx/quantization/fp8.py +375 -0
- modelopt/onnx/quantization/graph_utils.py +1479 -0
- modelopt/onnx/quantization/gs_patching.py +112 -0
- modelopt/onnx/quantization/int4.py +1347 -0
- modelopt/onnx/quantization/int8.py +283 -0
- modelopt/onnx/quantization/operators.py +121 -0
- modelopt/onnx/quantization/ort_patching.py +1766 -0
- modelopt/onnx/quantization/ort_utils.py +346 -0
- modelopt/onnx/quantization/partitioning.py +439 -0
- modelopt/onnx/quantization/qdq_utils.py +1349 -0
- modelopt/onnx/quantization/quant_utils.py +283 -0
- modelopt/onnx/quantization/quantize.py +528 -0
- modelopt/onnx/quantization/src/modelopt_round_and_pack_ext.cpp +127 -0
- modelopt/onnx/trt_utils.py +424 -0
- modelopt/onnx/utils.py +753 -0
- modelopt/torch/__init__.py +41 -0
- modelopt/torch/_deploy/__init__.py +23 -0
- modelopt/torch/_deploy/_runtime/__init__.py +29 -0
- modelopt/torch/_deploy/_runtime/common.py +72 -0
- modelopt/torch/_deploy/_runtime/ort_client.py +193 -0
- modelopt/torch/_deploy/_runtime/registry.py +83 -0
- modelopt/torch/_deploy/_runtime/runtime_client.py +154 -0
- modelopt/torch/_deploy/_runtime/tensorrt/constants.py +108 -0
- modelopt/torch/_deploy/_runtime/tensorrt/engine_builder.py +324 -0
- modelopt/torch/_deploy/_runtime/tensorrt/hw_param_config.py +51 -0
- modelopt/torch/_deploy/_runtime/tensorrt/layerwise_profiling.py +178 -0
- modelopt/torch/_deploy/_runtime/tensorrt/parse_trtexec_log.py +151 -0
- modelopt/torch/_deploy/_runtime/tensorrt/tensorrt_utils.py +200 -0
- modelopt/torch/_deploy/_runtime/trt_client.py +219 -0
- modelopt/torch/_deploy/compilation.py +142 -0
- modelopt/torch/_deploy/device_model.py +157 -0
- modelopt/torch/_deploy/profiling.py +193 -0
- modelopt/torch/_deploy/utils/__init__.py +18 -0
- modelopt/torch/_deploy/utils/onnx_optimizer.py +120 -0
- modelopt/torch/_deploy/utils/onnx_utils.py +58 -0
- modelopt/torch/_deploy/utils/torch_onnx.py +593 -0
- modelopt/torch/distill/__init__.py +28 -0
- modelopt/torch/distill/config.py +130 -0
- modelopt/torch/distill/distillation.py +84 -0
- modelopt/torch/distill/distillation_model.py +318 -0
- modelopt/torch/distill/loss_balancers.py +140 -0
- modelopt/torch/distill/losses.py +275 -0
- modelopt/torch/distill/mode.py +223 -0
- modelopt/torch/distill/plugins/__init__.py +24 -0
- modelopt/torch/distill/plugins/huggingface.py +110 -0
- modelopt/torch/distill/plugins/megatron.py +476 -0
- modelopt/torch/distill/registry.py +23 -0
- modelopt/torch/export/__init__.py +24 -0
- modelopt/torch/export/convert_hf_config.py +117 -0
- modelopt/torch/export/distribute.py +300 -0
- modelopt/torch/export/hf_config_map.py +84 -0
- modelopt/torch/export/layer_utils.py +1893 -0
- modelopt/torch/export/mcore_config_map.py +25 -0
- modelopt/torch/export/model_config.py +623 -0
- modelopt/torch/export/model_config_export.py +552 -0
- modelopt/torch/export/model_config_utils.py +392 -0
- modelopt/torch/export/model_utils.py +71 -0
- modelopt/torch/export/plugins/__init__.py +21 -0
- modelopt/torch/export/plugins/mcore_common.py +67 -0
- modelopt/torch/export/plugins/mcore_custom.py +530 -0
- modelopt/torch/export/plugins/mcore_deepseek.py +143 -0
- modelopt/torch/export/plugins/mcore_gptoss.py +71 -0
- modelopt/torch/export/plugins/mcore_llama.py +164 -0
- modelopt/torch/export/plugins/mcore_nemotron.py +90 -0
- modelopt/torch/export/plugins/mcore_qwen.py +99 -0
- modelopt/torch/export/plugins/megatron_importer.py +647 -0
- modelopt/torch/export/postprocess.py +847 -0
- modelopt/torch/export/quant_utils.py +1069 -0
- modelopt/torch/export/tensorrt_llm_type.py +42 -0
- modelopt/torch/export/tensorrt_llm_utils.py +405 -0
- modelopt/torch/export/transformer_engine.py +94 -0
- modelopt/torch/export/unified_export_hf.py +537 -0
- modelopt/torch/export/unified_export_megatron.py +1164 -0
- modelopt/torch/nas/__init__.py +27 -0
- modelopt/torch/nas/algorithms.py +856 -0
- modelopt/torch/nas/autonas.py +808 -0
- modelopt/torch/nas/conversion.py +119 -0
- modelopt/torch/nas/hparams/__init__.py +19 -0
- modelopt/torch/nas/hparams/concat.py +319 -0
- modelopt/torch/nas/hparams/container.py +48 -0
- modelopt/torch/nas/modules/__init__.py +21 -0
- modelopt/torch/nas/modules/container.py +99 -0
- modelopt/torch/nas/modules/conv.py +254 -0
- modelopt/torch/nas/modules/linear.py +76 -0
- modelopt/torch/nas/modules/norm.py +193 -0
- modelopt/torch/nas/modules/utils.py +61 -0
- modelopt/torch/nas/patch.py +261 -0
- modelopt/torch/nas/plugins/__init__.py +29 -0
- modelopt/torch/nas/plugins/megatron.py +1497 -0
- modelopt/torch/nas/plugins/torch.py +71 -0
- modelopt/torch/nas/plugins/transformer_engine.py +42 -0
- modelopt/torch/nas/plugins/transformers.py +210 -0
- modelopt/torch/nas/registry.py +23 -0
- modelopt/torch/nas/search_space.py +260 -0
- modelopt/torch/nas/traced_hp.py +149 -0
- modelopt/torch/nas/utils.py +408 -0
- modelopt/torch/opt/__init__.py +41 -0
- modelopt/torch/opt/_hooks.py +98 -0
- modelopt/torch/opt/config.py +383 -0
- modelopt/torch/opt/conversion.py +620 -0
- modelopt/torch/opt/dynamic.py +1367 -0
- modelopt/torch/opt/hparam.py +275 -0
- modelopt/torch/opt/mode.py +353 -0
- modelopt/torch/opt/plugins/__init__.py +38 -0
- modelopt/torch/opt/plugins/diffusers.py +40 -0
- modelopt/torch/opt/plugins/huggingface.py +162 -0
- modelopt/torch/opt/plugins/mcore_dist_checkpointing.py +211 -0
- modelopt/torch/opt/plugins/megatron.py +142 -0
- modelopt/torch/opt/plugins/peft.py +108 -0
- modelopt/torch/opt/plugins/transformers.py +160 -0
- modelopt/torch/opt/searcher.py +363 -0
- modelopt/torch/opt/utils.py +125 -0
- modelopt/torch/prune/__init__.py +26 -0
- modelopt/torch/prune/fastnas.py +376 -0
- modelopt/torch/prune/gradnas.py +349 -0
- modelopt/torch/prune/plugins/__init__.py +24 -0
- modelopt/torch/prune/plugins/mcore_minitron.py +263 -0
- modelopt/torch/prune/plugins/transformers.py +41 -0
- modelopt/torch/prune/pruning.py +211 -0
- modelopt/torch/quantization/__init__.py +26 -0
- modelopt/torch/quantization/algorithms.py +671 -0
- modelopt/torch/quantization/backends/__init__.py +20 -0
- modelopt/torch/quantization/backends/fp8_per_tensor_gemm.py +204 -0
- modelopt/torch/quantization/backends/gemm_registry.py +156 -0
- modelopt/torch/quantization/backends/nvfp4_gemm.py +201 -0
- modelopt/torch/quantization/backends/utils.py +28 -0
- modelopt/torch/quantization/calib/__init__.py +25 -0
- modelopt/torch/quantization/calib/bias.py +172 -0
- modelopt/torch/quantization/calib/calibrator.py +63 -0
- modelopt/torch/quantization/calib/histogram.py +434 -0
- modelopt/torch/quantization/calib/max.py +110 -0
- modelopt/torch/quantization/compress.py +227 -0
- modelopt/torch/quantization/config.py +1180 -0
- modelopt/torch/quantization/conversion.py +389 -0
- modelopt/torch/quantization/export_onnx.py +639 -0
- modelopt/torch/quantization/extensions.py +89 -0
- modelopt/torch/quantization/mode.py +428 -0
- modelopt/torch/quantization/model_calib.py +949 -0
- modelopt/torch/quantization/model_quant.py +477 -0
- modelopt/torch/quantization/nn/__init__.py +26 -0
- modelopt/torch/quantization/nn/functional.py +109 -0
- modelopt/torch/quantization/nn/modules/__init__.py +16 -0
- modelopt/torch/quantization/nn/modules/quant_activations.py +22 -0
- modelopt/torch/quantization/nn/modules/quant_batchnorm.py +24 -0
- modelopt/torch/quantization/nn/modules/quant_conv.py +123 -0
- modelopt/torch/quantization/nn/modules/quant_instancenorm.py +39 -0
- modelopt/torch/quantization/nn/modules/quant_linear.py +258 -0
- modelopt/torch/quantization/nn/modules/quant_module.py +211 -0
- modelopt/torch/quantization/nn/modules/quant_pooling.py +99 -0
- modelopt/torch/quantization/nn/modules/quant_rnn.py +527 -0
- modelopt/torch/quantization/nn/modules/tensor_quantizer.py +1293 -0
- modelopt/torch/quantization/plugins/__init__.py +73 -0
- modelopt/torch/quantization/plugins/accelerate.py +214 -0
- modelopt/torch/quantization/plugins/apex.py +52 -0
- modelopt/torch/quantization/plugins/attention.py +312 -0
- modelopt/torch/quantization/plugins/custom.py +192 -0
- modelopt/torch/quantization/plugins/diffusers.py +237 -0
- modelopt/torch/quantization/plugins/fairscale.py +45 -0
- modelopt/torch/quantization/plugins/huggingface.py +736 -0
- modelopt/torch/quantization/plugins/megatron.py +462 -0
- modelopt/torch/quantization/plugins/peft.py +148 -0
- modelopt/torch/quantization/plugins/transformer_engine.py +60 -0
- modelopt/torch/quantization/plugins/transformers.py +52 -0
- modelopt/torch/quantization/plugins/transformers_trainer.py +426 -0
- modelopt/torch/quantization/plugins/trl.py +27 -0
- modelopt/torch/quantization/plugins/vllm.py +199 -0
- modelopt/torch/quantization/qtensor/__init__.py +24 -0
- modelopt/torch/quantization/qtensor/base_qtensor.py +370 -0
- modelopt/torch/quantization/qtensor/fp8_tensor.py +151 -0
- modelopt/torch/quantization/qtensor/int4_tensor.py +130 -0
- modelopt/torch/quantization/qtensor/int8_tensor.py +124 -0
- modelopt/torch/quantization/qtensor/mxfp4_tensor.py +144 -0
- modelopt/torch/quantization/qtensor/nf4_tensor.py +199 -0
- modelopt/torch/quantization/qtensor/nvfp4_tensor.py +295 -0
- modelopt/torch/quantization/src/tensor_quant.cpp +77 -0
- modelopt/torch/quantization/src/tensor_quant.h +69 -0
- modelopt/torch/quantization/src/tensor_quant_fp8.cpp +48 -0
- modelopt/torch/quantization/src/tensor_quant_gpu.cu +361 -0
- modelopt/torch/quantization/src/tensor_quant_gpu_fp8.cu +122 -0
- modelopt/torch/quantization/src/tensor_quant_mx.cu +411 -0
- modelopt/torch/quantization/src/tensor_quant_mx.h +247 -0
- modelopt/torch/quantization/tensor_quant.py +816 -0
- modelopt/torch/quantization/triton/__init__.py +36 -0
- modelopt/torch/quantization/triton/fp4_kernel.py +303 -0
- modelopt/torch/quantization/utils.py +443 -0
- modelopt/torch/sparsity/__init__.py +19 -0
- modelopt/torch/sparsity/config.py +51 -0
- modelopt/torch/sparsity/magnitude.py +148 -0
- modelopt/torch/sparsity/mode.py +203 -0
- modelopt/torch/sparsity/module.py +87 -0
- modelopt/torch/sparsity/plugins/__init__.py +27 -0
- modelopt/torch/sparsity/plugins/megatron.py +93 -0
- modelopt/torch/sparsity/searcher.py +84 -0
- modelopt/torch/sparsity/sparsegpt.py +276 -0
- modelopt/torch/sparsity/sparsification.py +123 -0
- modelopt/torch/speculative/__init__.py +20 -0
- modelopt/torch/speculative/config.py +100 -0
- modelopt/torch/speculative/eagle/__init__.py +20 -0
- modelopt/torch/speculative/eagle/conversion.py +67 -0
- modelopt/torch/speculative/eagle/default_config.py +50 -0
- modelopt/torch/speculative/eagle/eagle_model.py +51 -0
- modelopt/torch/speculative/eagle/utils.py +91 -0
- modelopt/torch/speculative/medusa/__init__.py +19 -0
- modelopt/torch/speculative/medusa/conversion.py +59 -0
- modelopt/torch/speculative/medusa/medusa_model.py +32 -0
- modelopt/torch/speculative/mode.py +86 -0
- modelopt/torch/speculative/plugins/__init__.py +33 -0
- modelopt/torch/speculative/plugins/megatron_eagle.py +2119 -0
- modelopt/torch/speculative/plugins/megatron_medusa.py +312 -0
- modelopt/torch/speculative/plugins/transformers.py +1138 -0
- modelopt/torch/speculative/speculative_decoding.py +59 -0
- modelopt/torch/speculative/utils.py +364 -0
- modelopt/torch/trace/__init__.py +25 -0
- modelopt/torch/trace/analyzer.py +1368 -0
- modelopt/torch/trace/modules/__init__.py +19 -0
- modelopt/torch/trace/modules/concat.py +384 -0
- modelopt/torch/trace/modules/nn.py +153 -0
- modelopt/torch/trace/plugins/__init__.py +34 -0
- modelopt/torch/trace/plugins/megatron.py +36 -0
- modelopt/torch/trace/plugins/transformers.py +58 -0
- modelopt/torch/trace/symbols.py +545 -0
- modelopt/torch/trace/tracer.py +331 -0
- modelopt/torch/utils/__init__.py +28 -0
- modelopt/torch/utils/_pytree.py +133 -0
- modelopt/torch/utils/cpp_extension.py +91 -0
- modelopt/torch/utils/dataset_utils.py +484 -0
- modelopt/torch/utils/distributed.py +311 -0
- modelopt/torch/utils/graph.py +123 -0
- modelopt/torch/utils/image_processor.py +112 -0
- modelopt/torch/utils/import_utils.py +35 -0
- modelopt/torch/utils/list.py +54 -0
- modelopt/torch/utils/logging.py +127 -0
- modelopt/torch/utils/memory_monitor.py +146 -0
- modelopt/torch/utils/network.py +658 -0
- modelopt/torch/utils/perf.py +174 -0
- modelopt/torch/utils/plugins/__init__.py +27 -0
- modelopt/torch/utils/plugins/megatron_generate.py +299 -0
- modelopt/torch/utils/plugins/megatron_mmlu.py +152 -0
- modelopt/torch/utils/plugins/megatron_preprocess_data.py +200 -0
- modelopt/torch/utils/random.py +163 -0
- modelopt/torch/utils/speech_dataset_utils.py +134 -0
- modelopt/torch/utils/tensor.py +87 -0
- modelopt/torch/utils/vlm_dataset_utils.py +110 -0
- nvidia_modelopt-0.35.0.dist-info/METADATA +171 -0
- nvidia_modelopt-0.35.0.dist-info/RECORD +272 -0
- nvidia_modelopt-0.35.0.dist-info/WHEEL +5 -0
- nvidia_modelopt-0.35.0.dist-info/licenses/LICENSE +14 -0
- nvidia_modelopt-0.35.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
"""Calibrator that returns the absolute max of all collected tensors."""
|
|
17
|
+
|
|
18
|
+
import torch
|
|
19
|
+
|
|
20
|
+
from .. import utils as quant_utils
|
|
21
|
+
from .calibrator import _Calibrator
|
|
22
|
+
|
|
23
|
+
__all__ = ["MaxCalibrator"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MaxCalibrator(_Calibrator):
|
|
27
|
+
"""Max calibrator, tracks the maximum value globally.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
calib_desc: A MaxCalibDescriptor.
|
|
31
|
+
num_bits: An integer. Number of bits of quantization.
|
|
32
|
+
axis: A tuple. see :class:`QuantizerAttributeConfig <..config.QuantizerAttributeConfig>`.
|
|
33
|
+
unsigned: A boolean. using unsigned quantization.
|
|
34
|
+
|
|
35
|
+
Readonly Properties:
|
|
36
|
+
amaxs: A list of amax. Numpy array is saved as it is likely to be used for some plot.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, num_bits=8, axis=None, unsigned=False, track_amax=False):
|
|
40
|
+
"""Initialize."""
|
|
41
|
+
super().__init__(num_bits, axis, unsigned)
|
|
42
|
+
self._track_amax = track_amax
|
|
43
|
+
if self._track_amax:
|
|
44
|
+
self._amaxs = [] # shall we have a better name?
|
|
45
|
+
self._calib_amax = None
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def amaxs(self):
|
|
49
|
+
"""Returns the list of amax`s collected so far."""
|
|
50
|
+
return self._amaxs
|
|
51
|
+
|
|
52
|
+
@torch.no_grad()
|
|
53
|
+
def collect(self, x):
|
|
54
|
+
"""Tracks the absolute max of all tensors.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
x: A tensor
|
|
58
|
+
|
|
59
|
+
Raises:
|
|
60
|
+
RuntimeError: If amax shape changes
|
|
61
|
+
"""
|
|
62
|
+
# Swap axis to reduce.
|
|
63
|
+
reduce_axis = quant_utils.convert_quantization_axis_to_reduce_axis(x, self._axis)
|
|
64
|
+
local_amax = quant_utils.reduce_amax(x, axis=reduce_axis).detach()
|
|
65
|
+
# meta device is used for initialization
|
|
66
|
+
if x.device.type == "meta":
|
|
67
|
+
self._calib_amax = local_amax
|
|
68
|
+
return
|
|
69
|
+
assert torch.all(local_amax >= 0), (
|
|
70
|
+
"detected negative values after abs, could be torch or cuda bug"
|
|
71
|
+
)
|
|
72
|
+
assert not torch.any(torch.isinf(local_amax)), (
|
|
73
|
+
f"detected inf values in amax. inf in original tensor: {torch.any(torch.isinf(x))}"
|
|
74
|
+
)
|
|
75
|
+
assert not torch.any(torch.isnan(local_amax)), (
|
|
76
|
+
f"detected nan values in amax. nan in original tensor: {torch.any(torch.isnan(x))}"
|
|
77
|
+
)
|
|
78
|
+
if self._calib_amax is None:
|
|
79
|
+
self._calib_amax = local_amax
|
|
80
|
+
else:
|
|
81
|
+
if local_amax.shape != self._calib_amax.shape:
|
|
82
|
+
raise RuntimeError("amax shape changed!")
|
|
83
|
+
self._calib_amax = torch.max(self._calib_amax, local_amax)
|
|
84
|
+
|
|
85
|
+
if self._track_amax:
|
|
86
|
+
self._amaxs.append(local_amax.cpu().numpy())
|
|
87
|
+
|
|
88
|
+
def reset(self):
|
|
89
|
+
"""Reset the collected absolute max."""
|
|
90
|
+
self._calib_amax = None
|
|
91
|
+
|
|
92
|
+
def compute_amax(self):
|
|
93
|
+
"""Return the absolute max of all tensors collected."""
|
|
94
|
+
return self._calib_amax
|
|
95
|
+
|
|
96
|
+
def __str__(self):
|
|
97
|
+
s = "MaxCalibrator("
|
|
98
|
+
s += "track_amax={_track_amax}"
|
|
99
|
+
s += ")"
|
|
100
|
+
return s.format(**self.__dict__)
|
|
101
|
+
|
|
102
|
+
def __repr__(self):
|
|
103
|
+
s = "MaxCalibrator("
|
|
104
|
+
s += super().__repr__()
|
|
105
|
+
s += " calib_amax={_calib_amax}"
|
|
106
|
+
s += " track_amax={_track_amax}"
|
|
107
|
+
if self._track_amax:
|
|
108
|
+
s += " amaxs={_amaxs}"
|
|
109
|
+
s += ")"
|
|
110
|
+
return s.format(**self.__dict__)
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
"""Module for compressing the model weights after quantization."""
|
|
17
|
+
|
|
18
|
+
__all__ = ["compress"]
|
|
19
|
+
|
|
20
|
+
import fnmatch
|
|
21
|
+
import warnings
|
|
22
|
+
|
|
23
|
+
import torch
|
|
24
|
+
import torch.nn as nn
|
|
25
|
+
|
|
26
|
+
from modelopt.torch.opt import apply_mode
|
|
27
|
+
from modelopt.torch.opt.conversion import ModelLikeModule, ModeloptStateManager
|
|
28
|
+
from modelopt.torch.opt.dynamic import _DMRegistryCls
|
|
29
|
+
from modelopt.torch.opt.mode import ConvertReturnType, MetadataDict
|
|
30
|
+
|
|
31
|
+
from .backends.gemm_registry import disable_real_quant_gemm, enable_real_quant_gemm
|
|
32
|
+
from .config import CompressCfgType, CompressConfig
|
|
33
|
+
from .conversion import _replace_quant_module, set_quantizer_attribute
|
|
34
|
+
from .nn.modules.quant_linear import RealQuantLinear
|
|
35
|
+
from .qtensor import QTensorWrapper, pack_real_quantize_weight
|
|
36
|
+
from .utils import is_quantized_linear
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
from .plugins.megatron import (
|
|
40
|
+
_MegatronColumnParallelLinear,
|
|
41
|
+
_MegatronRowParallelLinear,
|
|
42
|
+
_RealQuantMegatronColumnParallelLinear,
|
|
43
|
+
_RealQuantMegatronRowParallelLinear,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
mcore_available = True
|
|
47
|
+
except ImportError:
|
|
48
|
+
mcore_available = False
|
|
49
|
+
|
|
50
|
+
RealQuantModuleRegistry = _DMRegistryCls("RealQuant")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def compress_convert(
|
|
54
|
+
model,
|
|
55
|
+
config: CompressConfig,
|
|
56
|
+
skip_real_quantize_weight: bool = False,
|
|
57
|
+
) -> ConvertReturnType:
|
|
58
|
+
"""Compress entry point.
|
|
59
|
+
|
|
60
|
+
This function converts the model to a real quantized model.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
model: The model to compress.
|
|
64
|
+
config: The compression configuration.
|
|
65
|
+
skip_real_quantize_weight: Whether to skip the real quantize step. Currently, it is
|
|
66
|
+
only set to True in the Megatron restore path to unify the restore behavior regardless
|
|
67
|
+
of whether the model is initialized on meta device or not.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
The compressed model.
|
|
71
|
+
"""
|
|
72
|
+
for _, module in model.named_modules():
|
|
73
|
+
if is_quantized_linear(module) and type(module) not in RealQuantModuleRegistry:
|
|
74
|
+
class_to_register = RealQuantLinear
|
|
75
|
+
if mcore_available:
|
|
76
|
+
if issubclass(type(module), _MegatronRowParallelLinear):
|
|
77
|
+
class_to_register = _RealQuantMegatronRowParallelLinear
|
|
78
|
+
elif issubclass(type(module), _MegatronColumnParallelLinear):
|
|
79
|
+
class_to_register = _RealQuantMegatronColumnParallelLinear
|
|
80
|
+
RealQuantModuleRegistry.register({type(module): module.__class__.__name__})(
|
|
81
|
+
class_to_register
|
|
82
|
+
)
|
|
83
|
+
# Convert QuantLinear to RealQuantLinear
|
|
84
|
+
_replace_quant_module(
|
|
85
|
+
model, version=ModeloptStateManager(model).state_version, registry=RealQuantModuleRegistry
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
compress_cfg = config.compress
|
|
89
|
+
if "default" in compress_cfg and isinstance(compress_cfg["default"], bool):
|
|
90
|
+
set_quantizer_attribute(
|
|
91
|
+
model, "*weight_quantizer*", {"fake_quant": not compress_cfg["default"]}
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
for pattern, to_compress in compress_cfg.items():
|
|
95
|
+
if pattern == "default":
|
|
96
|
+
continue
|
|
97
|
+
if isinstance(to_compress, bool):
|
|
98
|
+
|
|
99
|
+
def filter_func(name):
|
|
100
|
+
return fnmatch.fnmatch(name, pattern) and "weight_quantizer" in name
|
|
101
|
+
|
|
102
|
+
set_quantizer_attribute(model, filter_func, {"fake_quant": not to_compress})
|
|
103
|
+
else:
|
|
104
|
+
raise ValueError(
|
|
105
|
+
f"Invalid compression configuration: {to_compress}, expected a boolean as value."
|
|
106
|
+
)
|
|
107
|
+
# If real quant quantizer is present, real quantize the weights.
|
|
108
|
+
if not skip_real_quantize_weight:
|
|
109
|
+
pack_real_quantize_weight(model)
|
|
110
|
+
|
|
111
|
+
def _has_qtensorwrapper(module):
|
|
112
|
+
if hasattr(module, "weight") and isinstance(module.weight, QTensorWrapper):
|
|
113
|
+
return True
|
|
114
|
+
return any(_has_qtensorwrapper(submodule) for _, submodule in module.named_children())
|
|
115
|
+
|
|
116
|
+
if _has_qtensorwrapper(model):
|
|
117
|
+
warnings.warn(
|
|
118
|
+
"Real quantization has been applied to the model. This feature is still "
|
|
119
|
+
"experimental, and some functionalities may not be supported. For example, "
|
|
120
|
+
"converting the model back to its original state or saving and restoring "
|
|
121
|
+
"the quantized model may not be available."
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# Turn on real quant gemm after compression
|
|
125
|
+
if config.quant_gemm:
|
|
126
|
+
enable_real_quant_gemm(model)
|
|
127
|
+
else:
|
|
128
|
+
disable_real_quant_gemm(model)
|
|
129
|
+
|
|
130
|
+
metadata = {}
|
|
131
|
+
update_compress_metadata(model, config, metadata)
|
|
132
|
+
|
|
133
|
+
return model, metadata
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def compress_restore(
|
|
137
|
+
model: ModelLikeModule, config: CompressConfig, metadata: MetadataDict
|
|
138
|
+
) -> nn.Module:
|
|
139
|
+
"""Restore the model from the compressed state.
|
|
140
|
+
|
|
141
|
+
Note:
|
|
142
|
+
When restoring Megatron distributed checkpoint, real_quantizer_state and q_tensor_state
|
|
143
|
+
have been removed from metadata and stored as a part of QuantModule.extra_state.
|
|
144
|
+
Restoring happens in set_extra_state when load_state_dict is called. We also skip real
|
|
145
|
+
quantize weight (skip_real_quantize_weight). All these steps are
|
|
146
|
+
delayed. For details, see plugins.megatron.quant_module_set_extra_state.
|
|
147
|
+
"""
|
|
148
|
+
# Compress with dummy weights
|
|
149
|
+
model, _ = compress_convert(
|
|
150
|
+
model,
|
|
151
|
+
config,
|
|
152
|
+
skip_real_quantize_weight=("q_tensor_state" not in metadata),
|
|
153
|
+
)
|
|
154
|
+
# restore scale state in weight quantizer
|
|
155
|
+
if "real_quantizer_state" in metadata:
|
|
156
|
+
for name, module in model.named_modules():
|
|
157
|
+
if isinstance(module, RealQuantLinear) and name in metadata["real_quantizer_state"]:
|
|
158
|
+
if not metadata["real_quantizer_state"][name].items():
|
|
159
|
+
raise ValueError(f"Cannot find real quantizer state for {name}")
|
|
160
|
+
module.weight_quantizer.set_from_modelopt_state(
|
|
161
|
+
metadata["real_quantizer_state"][name]
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# restore real quant tensor states
|
|
165
|
+
if "q_tensor_state" in metadata:
|
|
166
|
+
for name, module in model.named_modules():
|
|
167
|
+
if isinstance(module, RealQuantLinear) and name in metadata["q_tensor_state"]:
|
|
168
|
+
module._parameters["weight"] = QTensorWrapper(
|
|
169
|
+
qtensor=torch.empty(
|
|
170
|
+
metadata["q_tensor_state"][name]["quantized_data.shape"],
|
|
171
|
+
dtype=metadata["q_tensor_state"][name]["quantized_data.dtype"],
|
|
172
|
+
device=module.weight.device,
|
|
173
|
+
),
|
|
174
|
+
metadata=metadata["q_tensor_state"][name]["metadata"],
|
|
175
|
+
)
|
|
176
|
+
return model
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def update_compress_metadata(model: nn.Module, config: CompressConfig, metadata: MetadataDict):
|
|
180
|
+
# save scales state in weight quantizer
|
|
181
|
+
real_quantizer_state = {}
|
|
182
|
+
for name, module in model.named_modules():
|
|
183
|
+
if isinstance(module, RealQuantLinear):
|
|
184
|
+
real_quantizer_state[name] = module.weight_quantizer.get_modelopt_state()
|
|
185
|
+
|
|
186
|
+
# real quant tensor states
|
|
187
|
+
q_tensor_state = {}
|
|
188
|
+
for name, module in model.named_modules():
|
|
189
|
+
if isinstance(module, RealQuantLinear) and isinstance(module.weight, QTensorWrapper):
|
|
190
|
+
q_tensor_state[name] = module.weight.get_state()
|
|
191
|
+
|
|
192
|
+
metadata["real_quantizer_state"] = real_quantizer_state
|
|
193
|
+
metadata["q_tensor_state"] = q_tensor_state
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def compress(model, config: CompressCfgType = None):
|
|
197
|
+
"""Compress model weights of quantized model.
|
|
198
|
+
|
|
199
|
+
This function compresses weights in layers that have an enabled `weight_quantizer` with
|
|
200
|
+
a supported quantization format. The compression is controlled by a pattern-based configuration.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
model: The quantized model to compress.
|
|
204
|
+
config: Dictionary mapping layer patterns to boolean compression flags.
|
|
205
|
+
If ``None``, defaults to ``{"default": True}`` which compresses all supported layers.
|
|
206
|
+
|
|
207
|
+
Example configuration::
|
|
208
|
+
|
|
209
|
+
{
|
|
210
|
+
"*.mlp.fc1*": False, # Skip compression for fc1 layers
|
|
211
|
+
"default": True, # Compress all other layers
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
Note: Each configuration except "default" is applied sequentially; therefore the later
|
|
215
|
+
configurations will override the previous ones if the same layer is matched.
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
Note: This function modifies the input model in-place.
|
|
219
|
+
"""
|
|
220
|
+
if config is None:
|
|
221
|
+
config = CompressConfig()
|
|
222
|
+
apply_mode(model, [("real_quantize", config)])
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def is_real_quantized(model):
|
|
226
|
+
"""Check if the model is real quantized."""
|
|
227
|
+
return any(isinstance(_module, RealQuantLinear) for _module in model.modules())
|