nvidia-modelopt 0.35.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- modelopt/__init__.py +20 -0
- modelopt/deploy/__init__.py +16 -0
- modelopt/deploy/llm/__init__.py +30 -0
- modelopt/deploy/llm/generate.py +345 -0
- modelopt/onnx/__init__.py +34 -0
- modelopt/onnx/autocast/__init__.py +19 -0
- modelopt/onnx/autocast/__main__.py +187 -0
- modelopt/onnx/autocast/convert.py +202 -0
- modelopt/onnx/autocast/graphsanitizer.py +422 -0
- modelopt/onnx/autocast/logging_config.py +78 -0
- modelopt/onnx/autocast/nodeclassifier.py +416 -0
- modelopt/onnx/autocast/precisionconverter.py +1032 -0
- modelopt/onnx/autocast/referencerunner.py +159 -0
- modelopt/onnx/autocast/utils.py +117 -0
- modelopt/onnx/llm_export_utils/__init__.py +16 -0
- modelopt/onnx/llm_export_utils/export_utils.py +162 -0
- modelopt/onnx/llm_export_utils/quantization_utils.py +122 -0
- modelopt/onnx/llm_export_utils/surgeon_utils.py +120 -0
- modelopt/onnx/logging_config.py +77 -0
- modelopt/onnx/op_types.py +300 -0
- modelopt/onnx/quantization/__init__.py +20 -0
- modelopt/onnx/quantization/__main__.py +291 -0
- modelopt/onnx/quantization/calib_utils.py +178 -0
- modelopt/onnx/quantization/extensions.py +35 -0
- modelopt/onnx/quantization/fp8.py +375 -0
- modelopt/onnx/quantization/graph_utils.py +1479 -0
- modelopt/onnx/quantization/gs_patching.py +112 -0
- modelopt/onnx/quantization/int4.py +1347 -0
- modelopt/onnx/quantization/int8.py +283 -0
- modelopt/onnx/quantization/operators.py +121 -0
- modelopt/onnx/quantization/ort_patching.py +1766 -0
- modelopt/onnx/quantization/ort_utils.py +346 -0
- modelopt/onnx/quantization/partitioning.py +439 -0
- modelopt/onnx/quantization/qdq_utils.py +1349 -0
- modelopt/onnx/quantization/quant_utils.py +283 -0
- modelopt/onnx/quantization/quantize.py +528 -0
- modelopt/onnx/quantization/src/modelopt_round_and_pack_ext.cpp +127 -0
- modelopt/onnx/trt_utils.py +424 -0
- modelopt/onnx/utils.py +753 -0
- modelopt/torch/__init__.py +41 -0
- modelopt/torch/_deploy/__init__.py +23 -0
- modelopt/torch/_deploy/_runtime/__init__.py +29 -0
- modelopt/torch/_deploy/_runtime/common.py +72 -0
- modelopt/torch/_deploy/_runtime/ort_client.py +193 -0
- modelopt/torch/_deploy/_runtime/registry.py +83 -0
- modelopt/torch/_deploy/_runtime/runtime_client.py +154 -0
- modelopt/torch/_deploy/_runtime/tensorrt/constants.py +108 -0
- modelopt/torch/_deploy/_runtime/tensorrt/engine_builder.py +324 -0
- modelopt/torch/_deploy/_runtime/tensorrt/hw_param_config.py +51 -0
- modelopt/torch/_deploy/_runtime/tensorrt/layerwise_profiling.py +178 -0
- modelopt/torch/_deploy/_runtime/tensorrt/parse_trtexec_log.py +151 -0
- modelopt/torch/_deploy/_runtime/tensorrt/tensorrt_utils.py +200 -0
- modelopt/torch/_deploy/_runtime/trt_client.py +219 -0
- modelopt/torch/_deploy/compilation.py +142 -0
- modelopt/torch/_deploy/device_model.py +157 -0
- modelopt/torch/_deploy/profiling.py +193 -0
- modelopt/torch/_deploy/utils/__init__.py +18 -0
- modelopt/torch/_deploy/utils/onnx_optimizer.py +120 -0
- modelopt/torch/_deploy/utils/onnx_utils.py +58 -0
- modelopt/torch/_deploy/utils/torch_onnx.py +593 -0
- modelopt/torch/distill/__init__.py +28 -0
- modelopt/torch/distill/config.py +130 -0
- modelopt/torch/distill/distillation.py +84 -0
- modelopt/torch/distill/distillation_model.py +318 -0
- modelopt/torch/distill/loss_balancers.py +140 -0
- modelopt/torch/distill/losses.py +275 -0
- modelopt/torch/distill/mode.py +223 -0
- modelopt/torch/distill/plugins/__init__.py +24 -0
- modelopt/torch/distill/plugins/huggingface.py +110 -0
- modelopt/torch/distill/plugins/megatron.py +476 -0
- modelopt/torch/distill/registry.py +23 -0
- modelopt/torch/export/__init__.py +24 -0
- modelopt/torch/export/convert_hf_config.py +117 -0
- modelopt/torch/export/distribute.py +300 -0
- modelopt/torch/export/hf_config_map.py +84 -0
- modelopt/torch/export/layer_utils.py +1893 -0
- modelopt/torch/export/mcore_config_map.py +25 -0
- modelopt/torch/export/model_config.py +623 -0
- modelopt/torch/export/model_config_export.py +552 -0
- modelopt/torch/export/model_config_utils.py +392 -0
- modelopt/torch/export/model_utils.py +71 -0
- modelopt/torch/export/plugins/__init__.py +21 -0
- modelopt/torch/export/plugins/mcore_common.py +67 -0
- modelopt/torch/export/plugins/mcore_custom.py +530 -0
- modelopt/torch/export/plugins/mcore_deepseek.py +143 -0
- modelopt/torch/export/plugins/mcore_gptoss.py +71 -0
- modelopt/torch/export/plugins/mcore_llama.py +164 -0
- modelopt/torch/export/plugins/mcore_nemotron.py +90 -0
- modelopt/torch/export/plugins/mcore_qwen.py +99 -0
- modelopt/torch/export/plugins/megatron_importer.py +647 -0
- modelopt/torch/export/postprocess.py +847 -0
- modelopt/torch/export/quant_utils.py +1069 -0
- modelopt/torch/export/tensorrt_llm_type.py +42 -0
- modelopt/torch/export/tensorrt_llm_utils.py +405 -0
- modelopt/torch/export/transformer_engine.py +94 -0
- modelopt/torch/export/unified_export_hf.py +537 -0
- modelopt/torch/export/unified_export_megatron.py +1164 -0
- modelopt/torch/nas/__init__.py +27 -0
- modelopt/torch/nas/algorithms.py +856 -0
- modelopt/torch/nas/autonas.py +808 -0
- modelopt/torch/nas/conversion.py +119 -0
- modelopt/torch/nas/hparams/__init__.py +19 -0
- modelopt/torch/nas/hparams/concat.py +319 -0
- modelopt/torch/nas/hparams/container.py +48 -0
- modelopt/torch/nas/modules/__init__.py +21 -0
- modelopt/torch/nas/modules/container.py +99 -0
- modelopt/torch/nas/modules/conv.py +254 -0
- modelopt/torch/nas/modules/linear.py +76 -0
- modelopt/torch/nas/modules/norm.py +193 -0
- modelopt/torch/nas/modules/utils.py +61 -0
- modelopt/torch/nas/patch.py +261 -0
- modelopt/torch/nas/plugins/__init__.py +29 -0
- modelopt/torch/nas/plugins/megatron.py +1497 -0
- modelopt/torch/nas/plugins/torch.py +71 -0
- modelopt/torch/nas/plugins/transformer_engine.py +42 -0
- modelopt/torch/nas/plugins/transformers.py +210 -0
- modelopt/torch/nas/registry.py +23 -0
- modelopt/torch/nas/search_space.py +260 -0
- modelopt/torch/nas/traced_hp.py +149 -0
- modelopt/torch/nas/utils.py +408 -0
- modelopt/torch/opt/__init__.py +41 -0
- modelopt/torch/opt/_hooks.py +98 -0
- modelopt/torch/opt/config.py +383 -0
- modelopt/torch/opt/conversion.py +620 -0
- modelopt/torch/opt/dynamic.py +1367 -0
- modelopt/torch/opt/hparam.py +275 -0
- modelopt/torch/opt/mode.py +353 -0
- modelopt/torch/opt/plugins/__init__.py +38 -0
- modelopt/torch/opt/plugins/diffusers.py +40 -0
- modelopt/torch/opt/plugins/huggingface.py +162 -0
- modelopt/torch/opt/plugins/mcore_dist_checkpointing.py +211 -0
- modelopt/torch/opt/plugins/megatron.py +142 -0
- modelopt/torch/opt/plugins/peft.py +108 -0
- modelopt/torch/opt/plugins/transformers.py +160 -0
- modelopt/torch/opt/searcher.py +363 -0
- modelopt/torch/opt/utils.py +125 -0
- modelopt/torch/prune/__init__.py +26 -0
- modelopt/torch/prune/fastnas.py +376 -0
- modelopt/torch/prune/gradnas.py +349 -0
- modelopt/torch/prune/plugins/__init__.py +24 -0
- modelopt/torch/prune/plugins/mcore_minitron.py +263 -0
- modelopt/torch/prune/plugins/transformers.py +41 -0
- modelopt/torch/prune/pruning.py +211 -0
- modelopt/torch/quantization/__init__.py +26 -0
- modelopt/torch/quantization/algorithms.py +671 -0
- modelopt/torch/quantization/backends/__init__.py +20 -0
- modelopt/torch/quantization/backends/fp8_per_tensor_gemm.py +204 -0
- modelopt/torch/quantization/backends/gemm_registry.py +156 -0
- modelopt/torch/quantization/backends/nvfp4_gemm.py +201 -0
- modelopt/torch/quantization/backends/utils.py +28 -0
- modelopt/torch/quantization/calib/__init__.py +25 -0
- modelopt/torch/quantization/calib/bias.py +172 -0
- modelopt/torch/quantization/calib/calibrator.py +63 -0
- modelopt/torch/quantization/calib/histogram.py +434 -0
- modelopt/torch/quantization/calib/max.py +110 -0
- modelopt/torch/quantization/compress.py +227 -0
- modelopt/torch/quantization/config.py +1180 -0
- modelopt/torch/quantization/conversion.py +389 -0
- modelopt/torch/quantization/export_onnx.py +639 -0
- modelopt/torch/quantization/extensions.py +89 -0
- modelopt/torch/quantization/mode.py +428 -0
- modelopt/torch/quantization/model_calib.py +949 -0
- modelopt/torch/quantization/model_quant.py +477 -0
- modelopt/torch/quantization/nn/__init__.py +26 -0
- modelopt/torch/quantization/nn/functional.py +109 -0
- modelopt/torch/quantization/nn/modules/__init__.py +16 -0
- modelopt/torch/quantization/nn/modules/quant_activations.py +22 -0
- modelopt/torch/quantization/nn/modules/quant_batchnorm.py +24 -0
- modelopt/torch/quantization/nn/modules/quant_conv.py +123 -0
- modelopt/torch/quantization/nn/modules/quant_instancenorm.py +39 -0
- modelopt/torch/quantization/nn/modules/quant_linear.py +258 -0
- modelopt/torch/quantization/nn/modules/quant_module.py +211 -0
- modelopt/torch/quantization/nn/modules/quant_pooling.py +99 -0
- modelopt/torch/quantization/nn/modules/quant_rnn.py +527 -0
- modelopt/torch/quantization/nn/modules/tensor_quantizer.py +1293 -0
- modelopt/torch/quantization/plugins/__init__.py +73 -0
- modelopt/torch/quantization/plugins/accelerate.py +214 -0
- modelopt/torch/quantization/plugins/apex.py +52 -0
- modelopt/torch/quantization/plugins/attention.py +312 -0
- modelopt/torch/quantization/plugins/custom.py +192 -0
- modelopt/torch/quantization/plugins/diffusers.py +237 -0
- modelopt/torch/quantization/plugins/fairscale.py +45 -0
- modelopt/torch/quantization/plugins/huggingface.py +736 -0
- modelopt/torch/quantization/plugins/megatron.py +462 -0
- modelopt/torch/quantization/plugins/peft.py +148 -0
- modelopt/torch/quantization/plugins/transformer_engine.py +60 -0
- modelopt/torch/quantization/plugins/transformers.py +52 -0
- modelopt/torch/quantization/plugins/transformers_trainer.py +426 -0
- modelopt/torch/quantization/plugins/trl.py +27 -0
- modelopt/torch/quantization/plugins/vllm.py +199 -0
- modelopt/torch/quantization/qtensor/__init__.py +24 -0
- modelopt/torch/quantization/qtensor/base_qtensor.py +370 -0
- modelopt/torch/quantization/qtensor/fp8_tensor.py +151 -0
- modelopt/torch/quantization/qtensor/int4_tensor.py +130 -0
- modelopt/torch/quantization/qtensor/int8_tensor.py +124 -0
- modelopt/torch/quantization/qtensor/mxfp4_tensor.py +144 -0
- modelopt/torch/quantization/qtensor/nf4_tensor.py +199 -0
- modelopt/torch/quantization/qtensor/nvfp4_tensor.py +295 -0
- modelopt/torch/quantization/src/tensor_quant.cpp +77 -0
- modelopt/torch/quantization/src/tensor_quant.h +69 -0
- modelopt/torch/quantization/src/tensor_quant_fp8.cpp +48 -0
- modelopt/torch/quantization/src/tensor_quant_gpu.cu +361 -0
- modelopt/torch/quantization/src/tensor_quant_gpu_fp8.cu +122 -0
- modelopt/torch/quantization/src/tensor_quant_mx.cu +411 -0
- modelopt/torch/quantization/src/tensor_quant_mx.h +247 -0
- modelopt/torch/quantization/tensor_quant.py +816 -0
- modelopt/torch/quantization/triton/__init__.py +36 -0
- modelopt/torch/quantization/triton/fp4_kernel.py +303 -0
- modelopt/torch/quantization/utils.py +443 -0
- modelopt/torch/sparsity/__init__.py +19 -0
- modelopt/torch/sparsity/config.py +51 -0
- modelopt/torch/sparsity/magnitude.py +148 -0
- modelopt/torch/sparsity/mode.py +203 -0
- modelopt/torch/sparsity/module.py +87 -0
- modelopt/torch/sparsity/plugins/__init__.py +27 -0
- modelopt/torch/sparsity/plugins/megatron.py +93 -0
- modelopt/torch/sparsity/searcher.py +84 -0
- modelopt/torch/sparsity/sparsegpt.py +276 -0
- modelopt/torch/sparsity/sparsification.py +123 -0
- modelopt/torch/speculative/__init__.py +20 -0
- modelopt/torch/speculative/config.py +100 -0
- modelopt/torch/speculative/eagle/__init__.py +20 -0
- modelopt/torch/speculative/eagle/conversion.py +67 -0
- modelopt/torch/speculative/eagle/default_config.py +50 -0
- modelopt/torch/speculative/eagle/eagle_model.py +51 -0
- modelopt/torch/speculative/eagle/utils.py +91 -0
- modelopt/torch/speculative/medusa/__init__.py +19 -0
- modelopt/torch/speculative/medusa/conversion.py +59 -0
- modelopt/torch/speculative/medusa/medusa_model.py +32 -0
- modelopt/torch/speculative/mode.py +86 -0
- modelopt/torch/speculative/plugins/__init__.py +33 -0
- modelopt/torch/speculative/plugins/megatron_eagle.py +2119 -0
- modelopt/torch/speculative/plugins/megatron_medusa.py +312 -0
- modelopt/torch/speculative/plugins/transformers.py +1138 -0
- modelopt/torch/speculative/speculative_decoding.py +59 -0
- modelopt/torch/speculative/utils.py +364 -0
- modelopt/torch/trace/__init__.py +25 -0
- modelopt/torch/trace/analyzer.py +1368 -0
- modelopt/torch/trace/modules/__init__.py +19 -0
- modelopt/torch/trace/modules/concat.py +384 -0
- modelopt/torch/trace/modules/nn.py +153 -0
- modelopt/torch/trace/plugins/__init__.py +34 -0
- modelopt/torch/trace/plugins/megatron.py +36 -0
- modelopt/torch/trace/plugins/transformers.py +58 -0
- modelopt/torch/trace/symbols.py +545 -0
- modelopt/torch/trace/tracer.py +331 -0
- modelopt/torch/utils/__init__.py +28 -0
- modelopt/torch/utils/_pytree.py +133 -0
- modelopt/torch/utils/cpp_extension.py +91 -0
- modelopt/torch/utils/dataset_utils.py +484 -0
- modelopt/torch/utils/distributed.py +311 -0
- modelopt/torch/utils/graph.py +123 -0
- modelopt/torch/utils/image_processor.py +112 -0
- modelopt/torch/utils/import_utils.py +35 -0
- modelopt/torch/utils/list.py +54 -0
- modelopt/torch/utils/logging.py +127 -0
- modelopt/torch/utils/memory_monitor.py +146 -0
- modelopt/torch/utils/network.py +658 -0
- modelopt/torch/utils/perf.py +174 -0
- modelopt/torch/utils/plugins/__init__.py +27 -0
- modelopt/torch/utils/plugins/megatron_generate.py +299 -0
- modelopt/torch/utils/plugins/megatron_mmlu.py +152 -0
- modelopt/torch/utils/plugins/megatron_preprocess_data.py +200 -0
- modelopt/torch/utils/random.py +163 -0
- modelopt/torch/utils/speech_dataset_utils.py +134 -0
- modelopt/torch/utils/tensor.py +87 -0
- modelopt/torch/utils/vlm_dataset_utils.py +110 -0
- nvidia_modelopt-0.35.0.dist-info/METADATA +171 -0
- nvidia_modelopt-0.35.0.dist-info/RECORD +272 -0
- nvidia_modelopt-0.35.0.dist-info/WHEEL +5 -0
- nvidia_modelopt-0.35.0.dist-info/licenses/LICENSE +14 -0
- nvidia_modelopt-0.35.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,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
|
+
}
|