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,276 @@
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
+ """Utility functions of SparseGPT."""
17
+
18
+ import math
19
+ import warnings
20
+
21
+ import torch
22
+ import torch.nn as nn
23
+
24
+ from modelopt.torch.opt.searcher import SearchConfig
25
+ from modelopt.torch.utils import print_rank_0
26
+
27
+ from .magnitude import get_nmprune_info
28
+ from .module import SparseModule
29
+ from .searcher import BaseSparseSearcher
30
+
31
+
32
+ def invert(hessian: torch.Tensor) -> torch.Tensor:
33
+ """Invert a Hessian matrix."""
34
+ try:
35
+ hessian_inv = torch.linalg.cholesky(hessian)
36
+ hessian_inv = torch.cholesky_inverse(hessian_inv)
37
+ hessian_inv = torch.linalg.cholesky(hessian_inv, upper=True)
38
+ except RuntimeError:
39
+ cols = hessian.size(0)
40
+ eps = 1e-6 * torch.eye(cols).to(hessian.device)
41
+ hessian_inv = torch.cholesky_inverse(torch.linalg.cholesky(hessian + eps))
42
+
43
+ return hessian_inv
44
+
45
+
46
+ def prepare(
47
+ tensor: torch.Tensor, hessian: torch.Tensor, hessian_damp: float
48
+ ) -> tuple[torch.Tensor, torch.Tensor]:
49
+ """Prepare the inverse Hessian matrix."""
50
+ weight = tensor.detach().clone()
51
+ # move the hessian matrix from CPU to GPU for acceleration
52
+ hessian = hessian.to(weight.device)
53
+ if len(weight.size()) == 4:
54
+ weight = weight.flatten(1)
55
+
56
+ zero = torch.diag(hessian) == 0
57
+ hessian[zero, zero] = 1
58
+ weight[:, zero] = 0
59
+
60
+ damp = hessian_damp * torch.mean(torch.diag(hessian))
61
+ cols = weight.size(1)
62
+ diag = torch.arange(cols)
63
+ hessian[diag, diag] += damp
64
+
65
+ hessian_inv = invert(hessian)
66
+
67
+ # remove the Hessian matrix to save GPU memory
68
+ del hessian
69
+ torch.cuda.empty_cache()
70
+
71
+ return weight, hessian_inv
72
+
73
+
74
+ @torch.no_grad()
75
+ def create_sgpt_mask(
76
+ tensor: torch.Tensor, hessian: torch.Tensor, config: SearchConfig
77
+ ) -> torch.Tensor:
78
+ """Create a sparse mask for the given tensor."""
79
+ shape = tensor.size()
80
+ weight, hessian_inv = prepare(tensor, hessian, config["hessian_damp"])
81
+ rows, cols = weight.size()
82
+ hessian_inv_diag = torch.diagonal(hessian_inv, dim1=0, dim2=1)
83
+
84
+ is_nm_prune, n, m = get_nmprune_info(config["pattern"])
85
+ col_bs = config["col_block_size"]
86
+ row_bs = config["row_block_size"]
87
+ # if row_bs is not specified, prune the whole weight block
88
+ if row_bs == -1:
89
+ row_bs = rows
90
+
91
+ for r1 in range(0, rows, row_bs):
92
+ r2 = min(r1 + row_bs, rows)
93
+ # the mask of the weights not to be pruned
94
+ w_rows = weight[r1:r2].float()
95
+
96
+ # pruning the weight block W[row:row+row_bs, i1:i1+col_bs]
97
+ for i1 in range(0, cols, col_bs):
98
+ i2 = min(i1 + col_bs, cols)
99
+ w_blk = w_rows[:, i1:i2].clone()
100
+ q_blk = torch.zeros_like(w_blk)
101
+ # the error of the weights to be pruned
102
+ delta_blk = torch.zeros_like(w_blk)
103
+ hinv_blk = hessian_inv[i1:i2, i1:i2]
104
+ hinv_diag_blk = hessian_inv_diag[i1:i2]
105
+
106
+ errors_blk = (w_blk**2) / (hinv_diag_blk**2 + 1e-9)
107
+ if torch.isnan(errors_blk).any():
108
+ print("nan in errors_blk.")
109
+
110
+ mask_blk = torch.zeros_like(w_blk, dtype=torch.bool)
111
+
112
+ for j in range(i2 - i1):
113
+ # compute the error of the weights to be pruned
114
+ w = w_blk[:, j]
115
+ d = hinv_diag_blk[j]
116
+ if is_nm_prune and j % m == 0:
117
+ errors_blk = (w_blk[:, j : j + m] ** 2) / (hinv_diag_blk[j : j + m] ** 2 + 1e-9)
118
+ mask_blk.scatter_(
119
+ 1, j + torch.topk(errors_blk, n, dim=1, largest=False)[1], True
120
+ )
121
+
122
+ q = w.clone()
123
+ q[mask_blk[:, j]] = 0
124
+ q_blk[:, j] = q
125
+
126
+ # update the remaining weights in the col_bs block to compensate the error caused by pruning W[:, j]
127
+ err = (w - q) / d
128
+ w_blk[:, j:] -= err.unsqueeze(1).matmul(hinv_blk[j, j:].unsqueeze(0))
129
+ delta_blk[:, j] = err
130
+
131
+ # compensate the error caused by pruning W[:, i: i + col_bs] with the weights update in W[:, i + col_bs:]
132
+ w_rows[:, i1:i2] = q_blk
133
+ w_rows[:, i2:] -= delta_blk.matmul(hessian_inv[i1:i2, i2:])
134
+ if torch.isnan(w_rows[:, i2:]).any():
135
+ print("nan")
136
+
137
+ weight[r1:r2] = w_rows
138
+
139
+ mask = weight != 0
140
+
141
+ return mask.view(shape)
142
+
143
+
144
+ class SparseGPTSearcher(BaseSparseSearcher):
145
+ """SparseGPT-based sparse mask searching algorithm."""
146
+
147
+ @property
148
+ def default_search_config(self) -> SearchConfig:
149
+ """Get the default config for the searcher."""
150
+ return {
151
+ **super().default_search_config,
152
+ "col_block_size": 128, # column block size in sparsegpt
153
+ "row_block_size": -1, # row block size in sparsegpt
154
+ "hessian_damp": 0.1, # hessian damp in sparsegpt
155
+ "calib_size": 256, # calibration size for hessian matrix calculation
156
+ "device": "cuda", # device of hessian matrix
157
+ }
158
+
159
+ def _check_weight_size(self, weight, mod_name) -> bool:
160
+ """Check if the weight size is supported by SparseGPT."""
161
+ _, _, m = get_nmprune_info(self.config["pattern"])
162
+
163
+ # the column size must be divisible by m
164
+ if weight.size(0) % m != 0 or weight.size(1) % m != 0:
165
+ warnings.warn(
166
+ f"Skipping pruning {mod_name} of size={weight.size()!s} and"
167
+ f" type={weight.dtype!s} for SparseGPT"
168
+ )
169
+ return False
170
+
171
+ return True
172
+
173
+ def _compute_mask(self, module: SparseModule) -> torch.BoolTensor:
174
+ """Compute the mask (and weight update) for the given module."""
175
+ return create_sgpt_mask(module.weight, module.hessian, self.config)
176
+
177
+ @torch.no_grad()
178
+ def before_search(self):
179
+ """Register the forward hook to collect the hessian matrix."""
180
+ super().before_search()
181
+
182
+ handles = []
183
+ for _, module in self._named_sparsifiable_modules():
184
+ # setup and register the forward hook
185
+ self._setup_forward_hook(module)
186
+ handles.append(module.register_forward_hook(self._hook_compute_hessian))
187
+
188
+ print_rank_0(f"Collecting Hessian statistics for {len(handles)} modules.")
189
+
190
+ # run a forward loop to collect the hessian matrix
191
+ assert self.forward_loop is not None, "Please provide `data_loader` or `forward_loop`!"
192
+ self.forward_loop(self.model)
193
+
194
+ # remove the forward hooks
195
+ for handle in handles:
196
+ handle.remove()
197
+
198
+ def after_search(self):
199
+ """Remove Hessian artifacts from network."""
200
+ super().after_search()
201
+ for _, module in self._named_sparsifiable_modules():
202
+ del module.hessian
203
+ del module.samples
204
+
205
+ @staticmethod
206
+ def _is_memory_sufficient(device_id, threshold):
207
+ """Check if the memory usage on the CUDA device is below the threshold."""
208
+ total_memory = torch.cuda.get_device_properties(device_id).total_memory
209
+ allocated_memory = torch.cuda.memory_allocated(device_id)
210
+ free_memory = total_memory - allocated_memory
211
+ return free_memory / total_memory > (1 - threshold)
212
+
213
+ @classmethod
214
+ def _setup_forward_hook(cls, mod: SparseModule) -> None:
215
+ """Setup the attributes we need for our forward hook during the SparseGPT search."""
216
+ # initialize the hessian matrix
217
+ if isinstance(mod, nn.Conv2d):
218
+ # For conv2d layers, the hessian matrix is calculated as X * X^T, where X is the
219
+ # flattened weight matrix.
220
+ cols = mod.weight.size(1) * mod.weight.size(2) * mod.weight.size(3)
221
+ else:
222
+ # For linear layers, the hessian matrix is calculated as X * X^T, where X is the
223
+ # weight matrix.
224
+ cols = mod.weight.size(1)
225
+
226
+ target_device = mod.weight.device
227
+ # Hessian matrix is stored in the GPU memory by default
228
+ if target_device.type == "cuda" and cls._is_memory_sufficient(target_device.index, 0.8):
229
+ hessian = torch.zeros((cols, cols), dtype=torch.float32).to(target_device)
230
+ else:
231
+ hessian = torch.zeros((cols, cols), dtype=torch.float32).to("cpu")
232
+
233
+ # store the hessian matrix and the number of samples
234
+ # TODO: this should probably be improved eventually!!
235
+ mod.hessian = hessian
236
+ mod.samples = 0
237
+
238
+ @classmethod
239
+ def _hook_compute_hessian(cls, mod: nn.Module, inp: torch.Tensor, out: torch.Tensor):
240
+ with torch.inference_mode():
241
+ # TODO: move the hessian matrix to GPU memory if possible
242
+ if isinstance(inp, tuple):
243
+ inp = inp[0]
244
+ # use torch.float32 to avoid overflow in Hessian
245
+ if len(inp.shape) == 2:
246
+ inp = inp.unsqueeze(0)
247
+ tmp = inp.shape[0]
248
+ # nn.Linear and *ParallelLinear in mcore
249
+ if "Linear" in type(mod).__name__:
250
+ if len(inp.shape) == 3:
251
+ inp = inp.reshape((-1, inp.shape[-1]))
252
+ inp.t_()
253
+ if isinstance(mod, nn.Conv2d):
254
+ unfold = nn.Unfold(
255
+ mod.kernel_size,
256
+ dilation=mod.dilation,
257
+ stride=mod.stride,
258
+ )
259
+ inp = unfold(inp)
260
+ inp = inp.permute([1, 0, 2])
261
+ inp = inp.flatten(1)
262
+ mod.hessian *= mod.samples / (mod.samples + tmp)
263
+ mod.samples += tmp
264
+ inp = math.sqrt(2 / mod.samples) * inp.float()
265
+
266
+ # the hessian matrix is calculated as X * X^T
267
+ target_device = mod.hessian.device
268
+ if mod.hessian.device.type == "cuda":
269
+ if cls._is_memory_sufficient(mod.hessian.device.index, 0.8):
270
+ mod.hessian += inp.matmul(inp.t()).to(mod.hessian.device)
271
+ else:
272
+ target_device = "cpu"
273
+ mod.hessian = mod.hessian.to("cpu")
274
+ mod.hessian += inp.matmul(inp.t()).to(target_device)
275
+
276
+ assert not torch.isinf(mod.hessian).any(), "Hessian contains inf"
@@ -0,0 +1,123 @@
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
+ """High-level API to automatically sparsify your model with various algorithms."""
17
+
18
+ from typing import Any
19
+
20
+ from torch import nn
21
+
22
+ from modelopt.torch.opt.conversion import apply_mode, get_mode
23
+ from modelopt.torch.opt.mode import ModeLike
24
+ from modelopt.torch.opt.searcher import BaseSearcher, SearchConfig
25
+ from modelopt.torch.utils import unwrap_model
26
+
27
+ from .mode import SparsityModeRegistry
28
+
29
+ __all__ = ["export", "sparsify"]
30
+
31
+
32
+ def sparsify(
33
+ model: nn.Module, mode: ModeLike, config: SearchConfig | None = None
34
+ ) -> tuple[nn.Module, dict[str, Any]]:
35
+ """Sparsify a given model and search for they optimal sparsified weights.
36
+
37
+ Args:
38
+ model: A standard model that contains standard building blocks to be sparsified in-place.
39
+ mode: A (list of) string(s) or Mode(s) or a list of tuples containing the mode and its
40
+ config indicating the desired mode(s) (and configurations) for the convert
41
+ process. Modes set up the model for different algorithms for model optimization. The
42
+ following modes are available:
43
+
44
+ * :class:`"sparse_magnitude"<modelopt.torch.sparsity.mode.SparseMagnitudeModeDescriptor>`:
45
+ The ``model`` will be sparsified according to the magnitude of weights in each
46
+ layer. The mode's config is described in
47
+ :class:`SparseMagnitudeConfig<modelopt.torch.sparsity.config.SparseMagnitudeConfig>`.
48
+ * :class:`"sparsegpt"<modelopt.torch.sparsity.mode.SparseGPTModeDescriptor>`:
49
+ The ``model`` will be sparsified and weights are updated optimally using an Hessian
50
+ approximation of the loss function (see SparseGPT paper for details). The mode's
51
+ config is described in
52
+ :class:`SparseGPTConfig<modelopt.torch.sparsity.config.SparseGPTConfig>`.
53
+
54
+ If the mode argument is specified as a dictionary, the keys should indicate the mode and
55
+ the values specify the per-mode configuration. If not provided, then default
56
+ configuration would be used.
57
+
58
+ config: Additional optional arguments to configure the search. Currently, we support:
59
+
60
+ * ``verbose``: Whether to print detailed search stats during search.
61
+ * ``forward_loop``: A ``Callable`` that takes a model as input and runs a forward loop
62
+ on it. It is recommended to choose the data loader used inside the forward loop
63
+ carefully to reduce the runtime. Cannot be provided at the same time as
64
+ ``data_loader`` and ``collect_func``.
65
+ * ``data_loader``: An iterator yielding batches of data for calibrating the
66
+ normalization layers in the model or compute gradient scores. It is recommended to use
67
+ the same data loader as for training but with significantly fewer iterations. Cannot
68
+ be provided at the same time as ``forward_loop``.
69
+ * ``collect_func``: A ``Callable`` that takes a batch of data from the data loader as
70
+ input and returns the input to ``model.forward()`` as described in
71
+ :meth:`run_forward_loop <modelopt.torch.utils.network.run_forward_loop>`. Cannot
72
+ be provided at the same time as ``forward_loop``.
73
+
74
+ .. note::
75
+
76
+ Additional configuration options may be added by individual algorithms. Please
77
+ refer to the documentation of the individual algorithms for more information.
78
+
79
+ Returns: A sparsified model
80
+
81
+ .. note::
82
+
83
+ The given model is sparsified in-place. The returned model is thus a reference to the same
84
+ model instance as the input model.
85
+ """
86
+ # apply sparsity to the model
87
+ model = apply_mode(model, mode, registry=SparsityModeRegistry)
88
+
89
+ # retrieve searcher class
90
+ searcher_cls: type[BaseSearcher] = getattr(get_mode(model), "search_algorithm")
91
+
92
+ # run search+sparsification algorithm
93
+ searcher = searcher_cls()
94
+ searcher.search(model, {}, (), config)
95
+
96
+ # return the sparsified model
97
+ return model
98
+
99
+
100
+ def export(model: nn.Module) -> nn.Module:
101
+ """Export a sparse dynamic model to a regular model.
102
+
103
+ This should be done after the model is fine-tuned and the weights are fixed.
104
+
105
+ .. warning::
106
+
107
+ After the call to ``export()``, the sparsity mask will no longer be enforced. This means any
108
+ future weight updates would destroy the sparsity pattern. If you want to continue training,
109
+ call ``export()`` after training is finished.
110
+ """
111
+ # unwrap a DP/DDP model
112
+ model = unwrap_model(
113
+ model,
114
+ warn=True,
115
+ msg=(
116
+ f"Unwrapping a {type(model).__name__} model for export! Note that the export is"
117
+ " in-place and the model wrapper should be re-created after export since the wrapper"
118
+ " might not support changing parameters after initialization."
119
+ ),
120
+ )
121
+
122
+ # apply export mode and return model
123
+ return apply_mode(model, "export_sparse", registry=SparsityModeRegistry)
@@ -0,0 +1,20 @@
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
+ """Speculative Decoding Optimizations."""
17
+
18
+ from . import eagle, medusa, mode, plugins
19
+ from .config import *
20
+ from .speculative_decoding import *
@@ -0,0 +1,100 @@
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
+ """Configurations for speculative decoding modes."""
17
+
18
+ from copy import deepcopy
19
+
20
+ from modelopt.torch.opt.config import ModeloptBaseConfig, ModeloptField
21
+
22
+ from .eagle.default_config import default_eagle_config
23
+
24
+ eagle3_default_config = deepcopy(default_eagle_config)
25
+ eagle_mtp_default_config = deepcopy(default_eagle_config)
26
+
27
+ eagle3_default_config.update({"use_aux_hidden_state": True, "use_last_layernorm": True})
28
+ eagle_mtp_default_config.update({"use_last_layernorm": True, "use_mtp_layernorm": True})
29
+
30
+ EAGLE1_DEFAULT_CFG = {
31
+ "algorithm": "eagle",
32
+ "config": {
33
+ "eagle_architecture_config": deepcopy(default_eagle_config),
34
+ },
35
+ }
36
+
37
+ EAGLE3_DEFAULT_CFG = {
38
+ "algorithm": "eagle",
39
+ "config": {
40
+ "eagle_architecture_config": eagle3_default_config,
41
+ },
42
+ }
43
+
44
+ EAGLE_MTP_DEFAULT_CFG = {
45
+ "algorithm": "eagle",
46
+ "config": {
47
+ "eagle_reuse_base_decoder": True,
48
+ "eagle_architecture_config": eagle_mtp_default_config,
49
+ },
50
+ }
51
+
52
+
53
+ class MedusaConfig(ModeloptBaseConfig):
54
+ """Medusa config."""
55
+
56
+ medusa_num_heads: int = ModeloptField(
57
+ default=2,
58
+ description=("The number of medusa heads added to the model."),
59
+ )
60
+
61
+ medusa_num_layers: int = ModeloptField(
62
+ default=1,
63
+ description=("The number of ResBlocks used in medusa head."),
64
+ )
65
+
66
+
67
+ class EagleConfig(ModeloptBaseConfig):
68
+ """Eagle config."""
69
+
70
+ eagle_offline: bool = ModeloptField(
71
+ default=False, description=("Whether to use detached Eagle.")
72
+ )
73
+
74
+ eagle_hidden_state_distillation: bool = ModeloptField(
75
+ default=False, description=("Whether to use feature hidden states distillation.")
76
+ )
77
+
78
+ eagle_self_logit_distillation: bool = ModeloptField(
79
+ default=True, description=("Whether to use logit distillation.")
80
+ )
81
+
82
+ eagle_freeze_base_model: bool = ModeloptField(
83
+ default=True, description=("Whether to freeze base model during eagle module training.")
84
+ )
85
+
86
+ eagle_report_acc: bool = ModeloptField(
87
+ default=True, description=("Whether to report eval accuracy.")
88
+ )
89
+
90
+ eagle_reuse_base_decoder: bool = ModeloptField(
91
+ default=False, description=("Whether to reuse base model decoder in eagle module.")
92
+ )
93
+
94
+ eagle_loss_decay_factor: float = ModeloptField(
95
+ default=0.9, description=("The decay factor for multiple eagle_loss.")
96
+ )
97
+
98
+ eagle_architecture_config: dict = ModeloptField(
99
+ default={}, description=("The config for eagle module architecture.")
100
+ )
@@ -0,0 +1,20 @@
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
+ """Eagle Optimization Method."""
17
+
18
+ from .conversion import *
19
+ from .default_config import *
20
+ from .eagle_model import *
@@ -0,0 +1,67 @@
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
+ """Eagle conversion/restore utilities."""
17
+
18
+ from torch import nn
19
+
20
+ from modelopt.torch.opt.conversion import ModelLikeModule
21
+ from modelopt.torch.opt.dynamic import _DMRegistryCls
22
+ from modelopt.torch.opt.mode import ConvertReturnType, MetadataDict
23
+
24
+ from ..config import EagleConfig
25
+
26
+ EagleDMRegistry = _DMRegistryCls(prefix="Eagle") # global instance for the registry
27
+ OfflineEagleDMRegistry = _DMRegistryCls(prefix="DetachedEagle") # global instance for the registry
28
+
29
+
30
+ def convert_to_eagle_model(model: nn.Module, config: EagleConfig) -> ConvertReturnType:
31
+ """Convert the model to a eagle model as per `config`."""
32
+ # initialize the true module if necessary
33
+ model = model.init_modellike() if isinstance(model, ModelLikeModule) else model
34
+
35
+ registry = OfflineEagleDMRegistry if config.eagle_offline else EagleDMRegistry
36
+
37
+ original_cls = type(model)
38
+ if original_cls not in registry:
39
+ for cls in registry._registry:
40
+ if issubclass(original_cls, cls):
41
+ registry.register({original_cls: "base_model_class"})(registry[cls])
42
+ break
43
+
44
+ eagle_model = registry.convert(model)
45
+ eagle_model.modify(
46
+ eagle_offline=config.eagle_offline,
47
+ eagle_hidden_state_distillation=config.eagle_hidden_state_distillation,
48
+ eagle_self_logit_distillation=config.eagle_self_logit_distillation,
49
+ eagle_freeze_base_model=config.eagle_freeze_base_model,
50
+ eagle_report_acc=config.eagle_report_acc,
51
+ eagle_reuse_base_decoder=config.eagle_reuse_base_decoder,
52
+ eagle_loss_decay_factor=config.eagle_loss_decay_factor,
53
+ eagle_architecture_config=config.eagle_architecture_config,
54
+ )
55
+
56
+ # no metadata, all specified via config.
57
+ metadata = {}
58
+
59
+ return eagle_model, metadata
60
+
61
+
62
+ def restore_eagle_model(model: nn.Module, config: EagleConfig, metadata: MetadataDict) -> nn.Module:
63
+ """Function for restoring a previously convert model to a eagle model."""
64
+ # the metadata should be empty
65
+ assert not metadata, "No metadata expected!"
66
+
67
+ return convert_to_eagle_model(model, config)[0]
@@ -0,0 +1,50 @@
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
+ """Default EAGLE architecture config."""
17
+
18
+ default_eagle_config = {
19
+ "hidden_act": "silu",
20
+ "torch_dtype": "bfloat16",
21
+ "vocab_size": 128256,
22
+ "draft_vocab_size": 128256,
23
+ "max_position_embeddings": 8192,
24
+ "position_embedding_type": "rope",
25
+ "rope_scaling": {
26
+ "factor": 8.0,
27
+ "low_freq_factor": 1.0,
28
+ "high_freq_factor": 4.0,
29
+ "original_max_position_embeddings": 8192,
30
+ "rope_type": "llama3",
31
+ },
32
+ "rope_theta": 500000.0,
33
+ "num_hidden_layers": 1,
34
+ "hidden_size": 4096,
35
+ "intermediate_size": 14336,
36
+ "num_attention_heads": 32,
37
+ "num_key_value_heads": 8,
38
+ "initializer_range": 0.01,
39
+ "rms_norm_eps": 1e-05,
40
+ "mlp_bias": False,
41
+ "attention_bias": False,
42
+ "attention_dropout": 0.0,
43
+ "use_input_layernorm_in_first_layer": True,
44
+ "use_last_layernorm": False,
45
+ "use_aux_hidden_state": False,
46
+ "eagle_aux_hidden_state_layer_ids": [],
47
+ "use_mtp_layernorm": False,
48
+ "parallel_draft_step": 1,
49
+ "has_lm_head": False,
50
+ }