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,291 @@
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
+ """Command-line entrypoint for ONNX PTQ."""
17
+
18
+ import argparse
19
+
20
+ import numpy as np
21
+
22
+ from modelopt.onnx.quantization.quantize import quantize
23
+
24
+ __all__ = ["main"]
25
+
26
+
27
+ def get_parser() -> argparse.ArgumentParser:
28
+ """Get the argument parser for ONNX PTQ."""
29
+ argparser = argparse.ArgumentParser("python -m modelopt.onnx.quantization")
30
+ group = argparser.add_mutually_exclusive_group(required=False)
31
+ argparser.add_argument(
32
+ "--onnx_path", required=True, type=str, help="Input onnx model without Q/DQ nodes."
33
+ )
34
+ argparser.add_argument(
35
+ "--quantize_mode",
36
+ type=str,
37
+ choices=["fp8", "int8", "int4"],
38
+ default="int8",
39
+ help=("Quantization mode for the given ONNX model."),
40
+ )
41
+ argparser.add_argument(
42
+ "--calibration_method",
43
+ type=str,
44
+ choices=["max", "entropy", "awq_clip", "rtn_dq"],
45
+ help=(
46
+ "Calibration method choices for int8/fp8: {entropy (default), max}, "
47
+ "int4: {awq_clip (default), rtn_dq}."
48
+ ),
49
+ )
50
+ group.add_argument(
51
+ "--calibration_data_path",
52
+ type=str,
53
+ help="Calibration data in npz/npy format. If None, random data for calibration will be used.",
54
+ )
55
+ group.add_argument(
56
+ "--calibration_cache_path",
57
+ type=str,
58
+ help="Pre-calculated activation tensor scaling factors aka calibration cache path.",
59
+ )
60
+ argparser.add_argument(
61
+ "--calibration_shapes",
62
+ type=str,
63
+ required=False,
64
+ help=(
65
+ "Optional model input shapes for calibration."
66
+ "Users should provide the shapes specifically if the model has non-batch dynamic dimensions."
67
+ "Example input shapes spec: input0:1x3x256x256,input1:1x3x128x128"
68
+ ),
69
+ )
70
+ argparser.add_argument(
71
+ "--calibration_eps",
72
+ type=str,
73
+ default=["cpu", "cuda:0", "trt"],
74
+ nargs="+",
75
+ help=(
76
+ "Priority order for the execution providers (EP) to calibrate the model. "
77
+ "Any subset of ['trt', 'cuda:x', dml:x, 'cpu'], where 'x' is the device id."
78
+ "If a custom op is detected in the model, 'trt' will automatically be added to the EP list."
79
+ ),
80
+ )
81
+ argparser.add_argument(
82
+ "--override_shapes",
83
+ type=str,
84
+ required=False,
85
+ help=(
86
+ "Override model input shapes with static shapes."
87
+ "Example input shapes spec: input0:1x3x256x256,input1:1x3x128x128"
88
+ ),
89
+ )
90
+ argparser.add_argument(
91
+ "--op_types_to_quantize",
92
+ type=str,
93
+ default=[],
94
+ nargs="+",
95
+ help="A space-separated list of node types to quantize.",
96
+ )
97
+ argparser.add_argument(
98
+ "--op_types_to_exclude",
99
+ type=str,
100
+ default=[],
101
+ nargs="+",
102
+ help="A space-separated list of node types to exclude from quantization.",
103
+ )
104
+ argparser.add_argument(
105
+ "--nodes_to_quantize",
106
+ type=str,
107
+ default=[],
108
+ nargs="+",
109
+ help="A space-separated list of node names to quantize. Regular expressions are supported.",
110
+ )
111
+ argparser.add_argument(
112
+ "--nodes_to_exclude",
113
+ type=str,
114
+ default=[],
115
+ nargs="+",
116
+ help="A space-separated list of node names to exclude from quantization. Regular expressions are supported.",
117
+ )
118
+ argparser.add_argument(
119
+ "--use_external_data_format",
120
+ action="store_true",
121
+ help=(
122
+ "If True or model size is larger than 2GB, "
123
+ "<MODEL_NAME>.onnx_data will be used to write weights and constants."
124
+ ),
125
+ )
126
+ argparser.add_argument(
127
+ "--keep_intermediate_files",
128
+ action="store_true",
129
+ help=(
130
+ "If True, keep the files generated during the ONNX models' conversion/calibration. "
131
+ "Otherwise, only the converted ONNX file is kept for the user."
132
+ ),
133
+ )
134
+ argparser.add_argument(
135
+ "--output_path",
136
+ type=str,
137
+ help=(
138
+ "Output filename to save the converted ONNX model. If None, save it in the same dir as "
139
+ "the original ONNX model with an appropriate suffix."
140
+ ),
141
+ )
142
+ argparser.add_argument(
143
+ "--log_level",
144
+ type=str,
145
+ choices=["DEBUG", "INFO", "WARNING", "ERROR", "debug", "info", "warning", "error"],
146
+ default="INFO",
147
+ help="Set the logging level for the quantization process.",
148
+ )
149
+ argparser.add_argument(
150
+ "--log_file",
151
+ type=str,
152
+ default=None,
153
+ help="Path to the log file for the quantization process.",
154
+ )
155
+ argparser.add_argument(
156
+ "--trt_plugins",
157
+ type=str,
158
+ default=None,
159
+ nargs="+",
160
+ help=(
161
+ "A space-separated list with the custom TensorRT plugin library paths in .so format (compiled shared "
162
+ "library). If this is not None, the TensorrtExecutionProvider is invoked, so make sure that the TensorRT "
163
+ "libraries are in the PATH or LD_LIBRARY_PATH variables."
164
+ ),
165
+ )
166
+ argparser.add_argument(
167
+ "--trt_plugins_precision",
168
+ type=str,
169
+ default=None,
170
+ nargs="+",
171
+ help=(
172
+ "A space-separated list indicating the precision for each custom op. "
173
+ "Each item should have the format <op_type>:<precision> (all inputs and outputs have the same precision) "
174
+ "or <op_type>:[<inp1_precision>,<inp2_precision>,...]:[<out1_precision>,<out2_precision>,...] "
175
+ "(inputs and outputs can have different precisions), where precision can be fp32 (default), "
176
+ "fp16, int8, or fp8. Note that int8/fp8 should be the same as the quantization mode. "
177
+ "For example: op_type_1:fp16 op_type_2:[int8,fp32]:[int8]."
178
+ ),
179
+ )
180
+ argparser.add_argument(
181
+ "--high_precision_dtype",
182
+ type=str,
183
+ default=None,
184
+ choices=["fp32", "fp16", "bf16"],
185
+ help=(
186
+ "High precision data type, one of ['fp32', 'fp16', 'bf16']. For int8 quantization, the default value is "
187
+ "'fp32' and 'fp16' for other quantization modes."
188
+ ),
189
+ )
190
+ argparser.add_argument(
191
+ "--mha_accumulation_dtype",
192
+ type=str,
193
+ default="fp16",
194
+ help=(
195
+ "Accumulation dtype of MHA. This flag will only take effect when mha_accumulation_dtype == 'fp32' "
196
+ "and quantize_mode == 'fp8'. One of ['fp32', 'fp16']"
197
+ ),
198
+ )
199
+ argparser.add_argument(
200
+ "--disable_mha_qdq",
201
+ action="store_true",
202
+ help="If True, Q/DQ will not be added to MatMuls in MHA pattern.",
203
+ )
204
+ argparser.add_argument(
205
+ "--dq_only",
206
+ action="store_true",
207
+ help=(
208
+ "If True, FP32/FP16 weights will be converted to INT8/FP8 weights. Q nodes will get removed from the "
209
+ "weights and have only DQ nodes with those converted INT8/FP8 weights in the output model."
210
+ ),
211
+ )
212
+ argparser.add_argument(
213
+ "--use_zero_point",
214
+ type=bool,
215
+ default=False,
216
+ help=(
217
+ "If True, zero-point based quantization will be used - currently, applicable for awq_lite algorithm."
218
+ ),
219
+ )
220
+ argparser.add_argument(
221
+ "--passes",
222
+ type=str,
223
+ choices=["concat_elimination"],
224
+ default=["concat_elimination"],
225
+ nargs="+",
226
+ help=(
227
+ "A space-separated list of optimization passes name, if set, appropriate pre/post-processing passes will "
228
+ "be invoked."
229
+ ),
230
+ )
231
+ argparser.add_argument(
232
+ "--simplify",
233
+ action="store_true",
234
+ help="If True, the given ONNX model will be simplified before quantization is performed.",
235
+ )
236
+ argparser.add_argument(
237
+ "--calibrate_per_node",
238
+ action="store_true",
239
+ help=(
240
+ "If set, performs calibration per node instead of running inference over the entire network. "
241
+ "Useful for reducing memory consumption during large model inference."
242
+ ),
243
+ )
244
+ return argparser
245
+
246
+
247
+ def main():
248
+ """Command-line entrypoint for ONNX PTQ."""
249
+ args = get_parser().parse_args()
250
+ calibration_data = None
251
+ if args.calibration_data_path:
252
+ calibration_data = np.load(args.calibration_data_path, allow_pickle=True)
253
+ if args.calibration_data_path.endswith(".npz"):
254
+ # Convert the NpzFile object to a Python dictionary
255
+ calibration_data = {key: calibration_data[key] for key in calibration_data.files}
256
+
257
+ default_high_precision_dtype = "fp32" if args.quantize_mode == "int8" else "fp16"
258
+
259
+ quantize(
260
+ args.onnx_path,
261
+ quantize_mode=args.quantize_mode,
262
+ calibration_data=calibration_data,
263
+ calibration_method=args.calibration_method,
264
+ calibration_cache_path=args.calibration_cache_path,
265
+ calibration_shapes=args.calibration_shapes,
266
+ calibration_eps=args.calibration_eps,
267
+ override_shapes=args.override_shapes,
268
+ op_types_to_quantize=args.op_types_to_quantize,
269
+ op_types_to_exclude=args.op_types_to_exclude,
270
+ nodes_to_quantize=args.nodes_to_quantize,
271
+ nodes_to_exclude=args.nodes_to_exclude,
272
+ use_external_data_format=args.use_external_data_format,
273
+ keep_intermediate_files=args.keep_intermediate_files,
274
+ output_path=args.output_path,
275
+ log_level=args.log_level,
276
+ log_file=args.log_file,
277
+ trt_plugins=args.trt_plugins,
278
+ trt_plugins_precision=args.trt_plugins_precision,
279
+ high_precision_dtype=args.high_precision_dtype or default_high_precision_dtype,
280
+ mha_accumulation_dtype=args.mha_accumulation_dtype,
281
+ disable_mha_qdq=args.disable_mha_qdq,
282
+ dq_only=args.dq_only,
283
+ use_zero_point=args.use_zero_point,
284
+ passes=args.passes,
285
+ simplify=args.simplify,
286
+ calibrate_per_node=args.calibrate_per_node,
287
+ )
288
+
289
+
290
+ if __name__ == "__main__":
291
+ main()
@@ -0,0 +1,178 @@
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
+ """Provides basic calibration utils."""
17
+
18
+ import struct
19
+ from typing import Union
20
+
21
+ import numpy as np
22
+ import onnx
23
+ from onnxruntime.quantization.calibrate import CalibrationDataReader
24
+
25
+ from modelopt.onnx.logging_config import logger
26
+ from modelopt.onnx.utils import (
27
+ gen_random_inputs,
28
+ get_input_names,
29
+ get_input_shapes,
30
+ parse_shapes_spec,
31
+ )
32
+
33
+ CalibrationDataType = Union[np.ndarray, dict[str, np.ndarray]] # noqa: UP007
34
+
35
+
36
+ class CalibrationDataProvider(CalibrationDataReader):
37
+ """Calibration data provider class."""
38
+
39
+ def __init__(
40
+ self,
41
+ onnx_path: str,
42
+ calibration_data: CalibrationDataType,
43
+ calibration_shapes: str | None = None,
44
+ ):
45
+ """Initializes the data provider class with the calibration data iterator.
46
+
47
+ Args:
48
+ onnx_path: Path to the ONNX model.
49
+ calibration_data: Numpy data to calibrate the model.
50
+ Ex. If a model has input shapes like {"sample": (2, 4, 64, 64), "timestep": (1,),
51
+ "encoder_hidden_states": (2, 16, 768)}, the calibration data should have dictionary
52
+ of tensors with shapes like {"sample": (1024, 4, 64, 64), "timestep": (512,),
53
+ "encoder_hidden_states": (1024, 16, 768)} to calibrate with 512 samples.
54
+ calibration_shapes: A string representing the shape of each input tensors for one calibration step.
55
+ If the shape is not provided for an input tensor, the shape is inferred from the onnx model directly,
56
+ with all the unknown dims filled with 1.
57
+ """
58
+ logger.info("Setting up CalibrationDataProvider for calibration")
59
+ # Tensor data is not required to generate the calibration data
60
+ # So even if the model has external data, we don't need to load them here
61
+ onnx_model = onnx.load(onnx_path)
62
+ input_names = get_input_names(onnx_model)
63
+ input_shapes = {} if calibration_shapes is None else parse_shapes_spec(calibration_shapes)
64
+ inferred_input_shapes = get_input_shapes(onnx_model)
65
+ for name in input_names:
66
+ if name not in input_shapes:
67
+ input_shapes[name] = inferred_input_shapes[name]
68
+ logger.debug(f"Inferred shape for {name}: {inferred_input_shapes[name]}")
69
+
70
+ # Validate calibration data against expected inputs by the model
71
+ if isinstance(calibration_data, np.ndarray):
72
+ assert len(input_names) == 1, "Calibration data has only one tensor."
73
+ calibration_data = {input_names[0]: calibration_data}
74
+ logger.debug(
75
+ f"Single tensor calibration data shape: {calibration_data[input_names[0]].shape}"
76
+ )
77
+ elif isinstance(calibration_data, dict):
78
+ assert len(input_names) == len(calibration_data), (
79
+ "Model input count and calibration data doesn't match."
80
+ )
81
+ for input_name in input_names:
82
+ assert input_name in calibration_data
83
+ logger.debug(f"Multi-tensor calibration data with {len(calibration_data)} inputs")
84
+ else:
85
+ raise ValueError(
86
+ f"calibration data must be numpy array or dict, got {type(calibration_data)}"
87
+ )
88
+
89
+ # Create list of model inputs with appropriate batch size
90
+ n_itr = int(calibration_data[input_names[0]].shape[0] / input_shapes[input_names[0]][0])
91
+ logger.debug(f"Creating {n_itr} calibration iterations")
92
+ self.calibration_data_list = [{}] * n_itr
93
+ for input_name in input_names:
94
+ for idx, calib_data in enumerate(
95
+ np.array_split(calibration_data[input_name], n_itr, axis=0)
96
+ ):
97
+ self.calibration_data_list[idx][input_name] = calib_data
98
+
99
+ self.calibration_data_reader = iter(self.calibration_data_list)
100
+
101
+ def get_next(self):
102
+ """Returns the next available calibration input from the reader."""
103
+ return next(self.calibration_data_reader, None)
104
+
105
+ def get_first(self):
106
+ """Returns the first calibration input from the reader without incrementing the iterator.
107
+
108
+ This is useful when doing a test run for the session.
109
+ """
110
+ assert len(self.calibration_data_list) > 0, "Calibration data list is empty!"
111
+ return self.calibration_data_list[0]
112
+
113
+ def rewind(self):
114
+ """Rewinds the data reader to the first index."""
115
+ self.calibration_data_reader = iter(self.calibration_data_list)
116
+
117
+
118
+ class RandomDataProvider(CalibrationDataReader):
119
+ """Calibration data reader class with random data provider."""
120
+
121
+ def __init__(self, onnx_model: str | onnx.ModelProto, calibration_shapes: str | None = None):
122
+ """Initializes the data reader class with random calibration data."""
123
+ logger.info("Initializing RandomDataProvider")
124
+ if isinstance(onnx_model, str):
125
+ onnx_path = onnx_model
126
+ logger.debug(
127
+ f"Loading ONNX model from: {onnx_path} to read the input shapes for RandomDataProvider"
128
+ )
129
+ # Tensor data is not required to generate the calibration data
130
+ # So even if the model has external data, we don't need to load them here
131
+ onnx_model = onnx.load(onnx_path)
132
+ self.calibration_data_list: list[dict[str, np.ndarray]] = [
133
+ gen_random_inputs(onnx_model, calibration_shapes)
134
+ ]
135
+ self.calibration_data_reader = iter(self.calibration_data_list)
136
+
137
+ def get_next(self):
138
+ """Returns the next available calibration input from the reader."""
139
+ return next(self.calibration_data_reader, None)
140
+
141
+ def get_first(self):
142
+ """Returns the first calibration input from the reader without incrementing the iterator.
143
+
144
+ This is useful when doing a test run for the session.
145
+ """
146
+ assert len(self.calibration_data_list) > 0, "Calibration data list is empty!"
147
+ return self.calibration_data_list[0]
148
+
149
+ def rewind(self):
150
+ """Rewinds the data reader to the first index."""
151
+ self.calibration_data_reader = iter(self.calibration_data_list)
152
+
153
+
154
+ def import_scales_from_calib_cache(cache_path: str) -> dict[str, float]:
155
+ """Reads TensorRT calibration cache and returns as dictionary.
156
+
157
+ Args:
158
+ cache_path: Calibration cache path.
159
+
160
+ Returns:
161
+ Dictionary with scales in the format {tensor_name: float_scale}.
162
+ """
163
+ logger.info(f"Importing scales from calibration cache: {cache_path}")
164
+ with open(cache_path) as f:
165
+ scales_dict = {}
166
+ lines = f.readlines()
167
+ for i, line in enumerate(lines):
168
+ if i > 0: # Skips the first line (i.e., TRT-8501-EntropyCalibration2)
169
+ layer_name, hex_value = line.replace("\n", "").split(": ")
170
+ try:
171
+ scale = struct.unpack("!f", bytes.fromhex(hex_value))[0]
172
+ scales_dict[layer_name + "_scale"] = scale
173
+ logger.debug(f"Imported scale for {layer_name}: {scale}")
174
+ except Exception as e:
175
+ logger.error(f"Failed to parse scale for tensor {layer_name}: {e!s}")
176
+ raise ValueError(f"Scale value for tensor {layer_name} was not found!")
177
+
178
+ return scales_dict
@@ -0,0 +1,35 @@
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
+ """Module to load C++ extensions."""
17
+
18
+ import os
19
+ import sys
20
+
21
+ import cppimport
22
+
23
+ from modelopt.onnx.logging_config import logger
24
+
25
+ try:
26
+ logger.info("Loading extension modelopt_round_and_pack_ext...")
27
+ path = os.path.join(os.path.dirname(__file__), "src")
28
+ sys.path.append(path)
29
+ round_and_pack_ext = cppimport.imp("modelopt_round_and_pack_ext")
30
+ sys.path.remove(path)
31
+ except Exception as e:
32
+ logger.warning(
33
+ f"{e}\nUnable to load `modelopt_round_and_pack_ext', falling back to python based optimized version"
34
+ )
35
+ round_and_pack_ext = None