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.
Files changed (272) hide show
  1. modelopt/__init__.py +20 -0
  2. modelopt/deploy/__init__.py +16 -0
  3. modelopt/deploy/llm/__init__.py +30 -0
  4. modelopt/deploy/llm/generate.py +345 -0
  5. modelopt/onnx/__init__.py +34 -0
  6. modelopt/onnx/autocast/__init__.py +19 -0
  7. modelopt/onnx/autocast/__main__.py +187 -0
  8. modelopt/onnx/autocast/convert.py +202 -0
  9. modelopt/onnx/autocast/graphsanitizer.py +422 -0
  10. modelopt/onnx/autocast/logging_config.py +78 -0
  11. modelopt/onnx/autocast/nodeclassifier.py +416 -0
  12. modelopt/onnx/autocast/precisionconverter.py +1032 -0
  13. modelopt/onnx/autocast/referencerunner.py +159 -0
  14. modelopt/onnx/autocast/utils.py +117 -0
  15. modelopt/onnx/llm_export_utils/__init__.py +16 -0
  16. modelopt/onnx/llm_export_utils/export_utils.py +162 -0
  17. modelopt/onnx/llm_export_utils/quantization_utils.py +122 -0
  18. modelopt/onnx/llm_export_utils/surgeon_utils.py +120 -0
  19. modelopt/onnx/logging_config.py +77 -0
  20. modelopt/onnx/op_types.py +300 -0
  21. modelopt/onnx/quantization/__init__.py +20 -0
  22. modelopt/onnx/quantization/__main__.py +291 -0
  23. modelopt/onnx/quantization/calib_utils.py +178 -0
  24. modelopt/onnx/quantization/extensions.py +35 -0
  25. modelopt/onnx/quantization/fp8.py +375 -0
  26. modelopt/onnx/quantization/graph_utils.py +1479 -0
  27. modelopt/onnx/quantization/gs_patching.py +112 -0
  28. modelopt/onnx/quantization/int4.py +1347 -0
  29. modelopt/onnx/quantization/int8.py +283 -0
  30. modelopt/onnx/quantization/operators.py +121 -0
  31. modelopt/onnx/quantization/ort_patching.py +1766 -0
  32. modelopt/onnx/quantization/ort_utils.py +346 -0
  33. modelopt/onnx/quantization/partitioning.py +439 -0
  34. modelopt/onnx/quantization/qdq_utils.py +1349 -0
  35. modelopt/onnx/quantization/quant_utils.py +283 -0
  36. modelopt/onnx/quantization/quantize.py +528 -0
  37. modelopt/onnx/quantization/src/modelopt_round_and_pack_ext.cpp +127 -0
  38. modelopt/onnx/trt_utils.py +424 -0
  39. modelopt/onnx/utils.py +753 -0
  40. modelopt/torch/__init__.py +41 -0
  41. modelopt/torch/_deploy/__init__.py +23 -0
  42. modelopt/torch/_deploy/_runtime/__init__.py +29 -0
  43. modelopt/torch/_deploy/_runtime/common.py +72 -0
  44. modelopt/torch/_deploy/_runtime/ort_client.py +193 -0
  45. modelopt/torch/_deploy/_runtime/registry.py +83 -0
  46. modelopt/torch/_deploy/_runtime/runtime_client.py +154 -0
  47. modelopt/torch/_deploy/_runtime/tensorrt/constants.py +108 -0
  48. modelopt/torch/_deploy/_runtime/tensorrt/engine_builder.py +324 -0
  49. modelopt/torch/_deploy/_runtime/tensorrt/hw_param_config.py +51 -0
  50. modelopt/torch/_deploy/_runtime/tensorrt/layerwise_profiling.py +178 -0
  51. modelopt/torch/_deploy/_runtime/tensorrt/parse_trtexec_log.py +151 -0
  52. modelopt/torch/_deploy/_runtime/tensorrt/tensorrt_utils.py +200 -0
  53. modelopt/torch/_deploy/_runtime/trt_client.py +219 -0
  54. modelopt/torch/_deploy/compilation.py +142 -0
  55. modelopt/torch/_deploy/device_model.py +157 -0
  56. modelopt/torch/_deploy/profiling.py +193 -0
  57. modelopt/torch/_deploy/utils/__init__.py +18 -0
  58. modelopt/torch/_deploy/utils/onnx_optimizer.py +120 -0
  59. modelopt/torch/_deploy/utils/onnx_utils.py +58 -0
  60. modelopt/torch/_deploy/utils/torch_onnx.py +593 -0
  61. modelopt/torch/distill/__init__.py +28 -0
  62. modelopt/torch/distill/config.py +130 -0
  63. modelopt/torch/distill/distillation.py +84 -0
  64. modelopt/torch/distill/distillation_model.py +318 -0
  65. modelopt/torch/distill/loss_balancers.py +140 -0
  66. modelopt/torch/distill/losses.py +275 -0
  67. modelopt/torch/distill/mode.py +223 -0
  68. modelopt/torch/distill/plugins/__init__.py +24 -0
  69. modelopt/torch/distill/plugins/huggingface.py +110 -0
  70. modelopt/torch/distill/plugins/megatron.py +476 -0
  71. modelopt/torch/distill/registry.py +23 -0
  72. modelopt/torch/export/__init__.py +24 -0
  73. modelopt/torch/export/convert_hf_config.py +117 -0
  74. modelopt/torch/export/distribute.py +300 -0
  75. modelopt/torch/export/hf_config_map.py +84 -0
  76. modelopt/torch/export/layer_utils.py +1893 -0
  77. modelopt/torch/export/mcore_config_map.py +25 -0
  78. modelopt/torch/export/model_config.py +623 -0
  79. modelopt/torch/export/model_config_export.py +552 -0
  80. modelopt/torch/export/model_config_utils.py +392 -0
  81. modelopt/torch/export/model_utils.py +71 -0
  82. modelopt/torch/export/plugins/__init__.py +21 -0
  83. modelopt/torch/export/plugins/mcore_common.py +67 -0
  84. modelopt/torch/export/plugins/mcore_custom.py +530 -0
  85. modelopt/torch/export/plugins/mcore_deepseek.py +143 -0
  86. modelopt/torch/export/plugins/mcore_gptoss.py +71 -0
  87. modelopt/torch/export/plugins/mcore_llama.py +164 -0
  88. modelopt/torch/export/plugins/mcore_nemotron.py +90 -0
  89. modelopt/torch/export/plugins/mcore_qwen.py +99 -0
  90. modelopt/torch/export/plugins/megatron_importer.py +647 -0
  91. modelopt/torch/export/postprocess.py +847 -0
  92. modelopt/torch/export/quant_utils.py +1069 -0
  93. modelopt/torch/export/tensorrt_llm_type.py +42 -0
  94. modelopt/torch/export/tensorrt_llm_utils.py +405 -0
  95. modelopt/torch/export/transformer_engine.py +94 -0
  96. modelopt/torch/export/unified_export_hf.py +537 -0
  97. modelopt/torch/export/unified_export_megatron.py +1164 -0
  98. modelopt/torch/nas/__init__.py +27 -0
  99. modelopt/torch/nas/algorithms.py +856 -0
  100. modelopt/torch/nas/autonas.py +808 -0
  101. modelopt/torch/nas/conversion.py +119 -0
  102. modelopt/torch/nas/hparams/__init__.py +19 -0
  103. modelopt/torch/nas/hparams/concat.py +319 -0
  104. modelopt/torch/nas/hparams/container.py +48 -0
  105. modelopt/torch/nas/modules/__init__.py +21 -0
  106. modelopt/torch/nas/modules/container.py +99 -0
  107. modelopt/torch/nas/modules/conv.py +254 -0
  108. modelopt/torch/nas/modules/linear.py +76 -0
  109. modelopt/torch/nas/modules/norm.py +193 -0
  110. modelopt/torch/nas/modules/utils.py +61 -0
  111. modelopt/torch/nas/patch.py +261 -0
  112. modelopt/torch/nas/plugins/__init__.py +29 -0
  113. modelopt/torch/nas/plugins/megatron.py +1497 -0
  114. modelopt/torch/nas/plugins/torch.py +71 -0
  115. modelopt/torch/nas/plugins/transformer_engine.py +42 -0
  116. modelopt/torch/nas/plugins/transformers.py +210 -0
  117. modelopt/torch/nas/registry.py +23 -0
  118. modelopt/torch/nas/search_space.py +260 -0
  119. modelopt/torch/nas/traced_hp.py +149 -0
  120. modelopt/torch/nas/utils.py +408 -0
  121. modelopt/torch/opt/__init__.py +41 -0
  122. modelopt/torch/opt/_hooks.py +98 -0
  123. modelopt/torch/opt/config.py +383 -0
  124. modelopt/torch/opt/conversion.py +620 -0
  125. modelopt/torch/opt/dynamic.py +1367 -0
  126. modelopt/torch/opt/hparam.py +275 -0
  127. modelopt/torch/opt/mode.py +353 -0
  128. modelopt/torch/opt/plugins/__init__.py +38 -0
  129. modelopt/torch/opt/plugins/diffusers.py +40 -0
  130. modelopt/torch/opt/plugins/huggingface.py +162 -0
  131. modelopt/torch/opt/plugins/mcore_dist_checkpointing.py +211 -0
  132. modelopt/torch/opt/plugins/megatron.py +142 -0
  133. modelopt/torch/opt/plugins/peft.py +108 -0
  134. modelopt/torch/opt/plugins/transformers.py +160 -0
  135. modelopt/torch/opt/searcher.py +363 -0
  136. modelopt/torch/opt/utils.py +125 -0
  137. modelopt/torch/prune/__init__.py +26 -0
  138. modelopt/torch/prune/fastnas.py +376 -0
  139. modelopt/torch/prune/gradnas.py +349 -0
  140. modelopt/torch/prune/plugins/__init__.py +24 -0
  141. modelopt/torch/prune/plugins/mcore_minitron.py +263 -0
  142. modelopt/torch/prune/plugins/transformers.py +41 -0
  143. modelopt/torch/prune/pruning.py +211 -0
  144. modelopt/torch/quantization/__init__.py +26 -0
  145. modelopt/torch/quantization/algorithms.py +671 -0
  146. modelopt/torch/quantization/backends/__init__.py +20 -0
  147. modelopt/torch/quantization/backends/fp8_per_tensor_gemm.py +204 -0
  148. modelopt/torch/quantization/backends/gemm_registry.py +156 -0
  149. modelopt/torch/quantization/backends/nvfp4_gemm.py +201 -0
  150. modelopt/torch/quantization/backends/utils.py +28 -0
  151. modelopt/torch/quantization/calib/__init__.py +25 -0
  152. modelopt/torch/quantization/calib/bias.py +172 -0
  153. modelopt/torch/quantization/calib/calibrator.py +63 -0
  154. modelopt/torch/quantization/calib/histogram.py +434 -0
  155. modelopt/torch/quantization/calib/max.py +110 -0
  156. modelopt/torch/quantization/compress.py +227 -0
  157. modelopt/torch/quantization/config.py +1180 -0
  158. modelopt/torch/quantization/conversion.py +389 -0
  159. modelopt/torch/quantization/export_onnx.py +639 -0
  160. modelopt/torch/quantization/extensions.py +89 -0
  161. modelopt/torch/quantization/mode.py +428 -0
  162. modelopt/torch/quantization/model_calib.py +949 -0
  163. modelopt/torch/quantization/model_quant.py +477 -0
  164. modelopt/torch/quantization/nn/__init__.py +26 -0
  165. modelopt/torch/quantization/nn/functional.py +109 -0
  166. modelopt/torch/quantization/nn/modules/__init__.py +16 -0
  167. modelopt/torch/quantization/nn/modules/quant_activations.py +22 -0
  168. modelopt/torch/quantization/nn/modules/quant_batchnorm.py +24 -0
  169. modelopt/torch/quantization/nn/modules/quant_conv.py +123 -0
  170. modelopt/torch/quantization/nn/modules/quant_instancenorm.py +39 -0
  171. modelopt/torch/quantization/nn/modules/quant_linear.py +258 -0
  172. modelopt/torch/quantization/nn/modules/quant_module.py +211 -0
  173. modelopt/torch/quantization/nn/modules/quant_pooling.py +99 -0
  174. modelopt/torch/quantization/nn/modules/quant_rnn.py +527 -0
  175. modelopt/torch/quantization/nn/modules/tensor_quantizer.py +1293 -0
  176. modelopt/torch/quantization/plugins/__init__.py +73 -0
  177. modelopt/torch/quantization/plugins/accelerate.py +214 -0
  178. modelopt/torch/quantization/plugins/apex.py +52 -0
  179. modelopt/torch/quantization/plugins/attention.py +312 -0
  180. modelopt/torch/quantization/plugins/custom.py +192 -0
  181. modelopt/torch/quantization/plugins/diffusers.py +237 -0
  182. modelopt/torch/quantization/plugins/fairscale.py +45 -0
  183. modelopt/torch/quantization/plugins/huggingface.py +736 -0
  184. modelopt/torch/quantization/plugins/megatron.py +462 -0
  185. modelopt/torch/quantization/plugins/peft.py +148 -0
  186. modelopt/torch/quantization/plugins/transformer_engine.py +60 -0
  187. modelopt/torch/quantization/plugins/transformers.py +52 -0
  188. modelopt/torch/quantization/plugins/transformers_trainer.py +426 -0
  189. modelopt/torch/quantization/plugins/trl.py +27 -0
  190. modelopt/torch/quantization/plugins/vllm.py +199 -0
  191. modelopt/torch/quantization/qtensor/__init__.py +24 -0
  192. modelopt/torch/quantization/qtensor/base_qtensor.py +370 -0
  193. modelopt/torch/quantization/qtensor/fp8_tensor.py +151 -0
  194. modelopt/torch/quantization/qtensor/int4_tensor.py +130 -0
  195. modelopt/torch/quantization/qtensor/int8_tensor.py +124 -0
  196. modelopt/torch/quantization/qtensor/mxfp4_tensor.py +144 -0
  197. modelopt/torch/quantization/qtensor/nf4_tensor.py +199 -0
  198. modelopt/torch/quantization/qtensor/nvfp4_tensor.py +295 -0
  199. modelopt/torch/quantization/src/tensor_quant.cpp +77 -0
  200. modelopt/torch/quantization/src/tensor_quant.h +69 -0
  201. modelopt/torch/quantization/src/tensor_quant_fp8.cpp +48 -0
  202. modelopt/torch/quantization/src/tensor_quant_gpu.cu +361 -0
  203. modelopt/torch/quantization/src/tensor_quant_gpu_fp8.cu +122 -0
  204. modelopt/torch/quantization/src/tensor_quant_mx.cu +411 -0
  205. modelopt/torch/quantization/src/tensor_quant_mx.h +247 -0
  206. modelopt/torch/quantization/tensor_quant.py +816 -0
  207. modelopt/torch/quantization/triton/__init__.py +36 -0
  208. modelopt/torch/quantization/triton/fp4_kernel.py +303 -0
  209. modelopt/torch/quantization/utils.py +443 -0
  210. modelopt/torch/sparsity/__init__.py +19 -0
  211. modelopt/torch/sparsity/config.py +51 -0
  212. modelopt/torch/sparsity/magnitude.py +148 -0
  213. modelopt/torch/sparsity/mode.py +203 -0
  214. modelopt/torch/sparsity/module.py +87 -0
  215. modelopt/torch/sparsity/plugins/__init__.py +27 -0
  216. modelopt/torch/sparsity/plugins/megatron.py +93 -0
  217. modelopt/torch/sparsity/searcher.py +84 -0
  218. modelopt/torch/sparsity/sparsegpt.py +276 -0
  219. modelopt/torch/sparsity/sparsification.py +123 -0
  220. modelopt/torch/speculative/__init__.py +20 -0
  221. modelopt/torch/speculative/config.py +100 -0
  222. modelopt/torch/speculative/eagle/__init__.py +20 -0
  223. modelopt/torch/speculative/eagle/conversion.py +67 -0
  224. modelopt/torch/speculative/eagle/default_config.py +50 -0
  225. modelopt/torch/speculative/eagle/eagle_model.py +51 -0
  226. modelopt/torch/speculative/eagle/utils.py +91 -0
  227. modelopt/torch/speculative/medusa/__init__.py +19 -0
  228. modelopt/torch/speculative/medusa/conversion.py +59 -0
  229. modelopt/torch/speculative/medusa/medusa_model.py +32 -0
  230. modelopt/torch/speculative/mode.py +86 -0
  231. modelopt/torch/speculative/plugins/__init__.py +33 -0
  232. modelopt/torch/speculative/plugins/megatron_eagle.py +2119 -0
  233. modelopt/torch/speculative/plugins/megatron_medusa.py +312 -0
  234. modelopt/torch/speculative/plugins/transformers.py +1138 -0
  235. modelopt/torch/speculative/speculative_decoding.py +59 -0
  236. modelopt/torch/speculative/utils.py +364 -0
  237. modelopt/torch/trace/__init__.py +25 -0
  238. modelopt/torch/trace/analyzer.py +1368 -0
  239. modelopt/torch/trace/modules/__init__.py +19 -0
  240. modelopt/torch/trace/modules/concat.py +384 -0
  241. modelopt/torch/trace/modules/nn.py +153 -0
  242. modelopt/torch/trace/plugins/__init__.py +34 -0
  243. modelopt/torch/trace/plugins/megatron.py +36 -0
  244. modelopt/torch/trace/plugins/transformers.py +58 -0
  245. modelopt/torch/trace/symbols.py +545 -0
  246. modelopt/torch/trace/tracer.py +331 -0
  247. modelopt/torch/utils/__init__.py +28 -0
  248. modelopt/torch/utils/_pytree.py +133 -0
  249. modelopt/torch/utils/cpp_extension.py +91 -0
  250. modelopt/torch/utils/dataset_utils.py +484 -0
  251. modelopt/torch/utils/distributed.py +311 -0
  252. modelopt/torch/utils/graph.py +123 -0
  253. modelopt/torch/utils/image_processor.py +112 -0
  254. modelopt/torch/utils/import_utils.py +35 -0
  255. modelopt/torch/utils/list.py +54 -0
  256. modelopt/torch/utils/logging.py +127 -0
  257. modelopt/torch/utils/memory_monitor.py +146 -0
  258. modelopt/torch/utils/network.py +658 -0
  259. modelopt/torch/utils/perf.py +174 -0
  260. modelopt/torch/utils/plugins/__init__.py +27 -0
  261. modelopt/torch/utils/plugins/megatron_generate.py +299 -0
  262. modelopt/torch/utils/plugins/megatron_mmlu.py +152 -0
  263. modelopt/torch/utils/plugins/megatron_preprocess_data.py +200 -0
  264. modelopt/torch/utils/random.py +163 -0
  265. modelopt/torch/utils/speech_dataset_utils.py +134 -0
  266. modelopt/torch/utils/tensor.py +87 -0
  267. modelopt/torch/utils/vlm_dataset_utils.py +110 -0
  268. nvidia_modelopt-0.35.0.dist-info/METADATA +171 -0
  269. nvidia_modelopt-0.35.0.dist-info/RECORD +272 -0
  270. nvidia_modelopt-0.35.0.dist-info/WHEEL +5 -0
  271. nvidia_modelopt-0.35.0.dist-info/licenses/LICENSE +14 -0
  272. 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())