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,99 @@
|
|
|
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
|
+
"""Quantized Pooling modules."""
|
|
17
|
+
|
|
18
|
+
from torch.nn.modules import pooling
|
|
19
|
+
|
|
20
|
+
from .quant_module import QuantInputBase, QuantModuleRegistry, _LegacyQuantInputBaseMixin
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"AdaptiveAvgPool1d",
|
|
24
|
+
"AdaptiveAvgPool2d",
|
|
25
|
+
"AdaptiveAvgPool3d",
|
|
26
|
+
"AvgPool1d",
|
|
27
|
+
"AvgPool2d",
|
|
28
|
+
"AvgPool3d",
|
|
29
|
+
"MaxPool1d",
|
|
30
|
+
"MaxPool2d",
|
|
31
|
+
"MaxPool3d",
|
|
32
|
+
"QuantAdaptiveAvgPool1d",
|
|
33
|
+
"QuantAdaptiveAvgPool2d",
|
|
34
|
+
"QuantAdaptiveAvgPool3d",
|
|
35
|
+
"QuantAvgPool1d",
|
|
36
|
+
"QuantAvgPool2d",
|
|
37
|
+
"QuantAvgPool3d",
|
|
38
|
+
"QuantMaxPool1d",
|
|
39
|
+
"QuantMaxPool2d",
|
|
40
|
+
"QuantMaxPool3d",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class QuantMaxPool1d(_LegacyQuantInputBaseMixin, pooling.MaxPool1d):
|
|
45
|
+
"""Quantized version of nn.MaxPool1d."""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class QuantMaxPool2d(_LegacyQuantInputBaseMixin, pooling.MaxPool2d):
|
|
49
|
+
"""Quantized version of nn.MaxPool2d."""
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class QuantMaxPool3d(_LegacyQuantInputBaseMixin, pooling.MaxPool3d):
|
|
53
|
+
"""Quantized version of nn.MaxPool3d."""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class QuantAvgPool1d(_LegacyQuantInputBaseMixin, pooling.AvgPool1d):
|
|
57
|
+
"""Quantized version of nn.AvgPool1d."""
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class QuantAvgPool2d(_LegacyQuantInputBaseMixin, pooling.AvgPool2d):
|
|
61
|
+
"""Quantized version of nn.AvgPool2d."""
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class QuantAvgPool3d(_LegacyQuantInputBaseMixin, pooling.AvgPool3d):
|
|
65
|
+
"""Quantized version of nn.AvgPool3d."""
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class QuantAdaptiveAvgPool1d(_LegacyQuantInputBaseMixin, pooling.AdaptiveAvgPool1d):
|
|
69
|
+
"""Quantized version of nn.AdaptiveAvgPool1d."""
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class QuantAdaptiveAvgPool2d(_LegacyQuantInputBaseMixin, pooling.AdaptiveAvgPool2d):
|
|
73
|
+
"""Quantized version of nn.AdaptiveAvgPool2d."""
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class QuantAdaptiveAvgPool3d(_LegacyQuantInputBaseMixin, pooling.AdaptiveAvgPool3d):
|
|
77
|
+
"""Quantized version of nn.AdaptiveAvgPool3d."""
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# Define alias with Quant prefix
|
|
81
|
+
MaxPool1d = QuantMaxPool1d
|
|
82
|
+
MaxPool2d = QuantMaxPool2d
|
|
83
|
+
MaxPool3d = QuantMaxPool3d
|
|
84
|
+
AvgPool1d = QuantAvgPool1d
|
|
85
|
+
AvgPool2d = QuantAvgPool2d
|
|
86
|
+
AvgPool3d = QuantAvgPool3d
|
|
87
|
+
AdaptiveAvgPool1d = QuantAdaptiveAvgPool1d
|
|
88
|
+
AdaptiveAvgPool2d = QuantAdaptiveAvgPool2d
|
|
89
|
+
AdaptiveAvgPool3d = QuantAdaptiveAvgPool3d
|
|
90
|
+
|
|
91
|
+
QuantModuleRegistry.register({pooling.MaxPool1d: "nn.MaxPool1d"})(QuantInputBase)
|
|
92
|
+
QuantModuleRegistry.register({pooling.MaxPool2d: "nn.MaxPool2d"})(QuantInputBase)
|
|
93
|
+
QuantModuleRegistry.register({pooling.MaxPool3d: "nn.MaxPool3d"})(QuantInputBase)
|
|
94
|
+
QuantModuleRegistry.register({pooling.AvgPool1d: "nn.AvgPool1d"})(QuantInputBase)
|
|
95
|
+
QuantModuleRegistry.register({pooling.AvgPool2d: "nn.AvgPool2d"})(QuantInputBase)
|
|
96
|
+
QuantModuleRegistry.register({pooling.AvgPool3d: "nn.AvgPool3d"})(QuantInputBase)
|
|
97
|
+
QuantModuleRegistry.register({pooling.AdaptiveAvgPool1d: "nn.AdaptiveAvgPool1d"})(QuantInputBase)
|
|
98
|
+
QuantModuleRegistry.register({pooling.AdaptiveAvgPool2d: "nn.AdaptiveAvgPool2d"})(QuantInputBase)
|
|
99
|
+
QuantModuleRegistry.register({pooling.AdaptiveAvgPool3d: "nn.AdaptiveAvgPool3d"})(QuantInputBase)
|
|
@@ -0,0 +1,527 @@
|
|
|
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
|
+
"""Quantized RNN."""
|
|
17
|
+
|
|
18
|
+
import contextlib
|
|
19
|
+
from collections.abc import Callable, Iterator
|
|
20
|
+
from types import ModuleType
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
import torch
|
|
24
|
+
import torch._VF as _VF
|
|
25
|
+
import torch.nn as nn
|
|
26
|
+
import torch.nn.functional as F
|
|
27
|
+
|
|
28
|
+
from ...tensor_quant import QUANT_DESC_8BIT_PER_TENSOR
|
|
29
|
+
from ...utils import is_torch_export_mode, multi_context, replace_function
|
|
30
|
+
from .quant_module import QuantModule, QuantModuleRegistry
|
|
31
|
+
from .tensor_quantizer import SequentialQuantizer, TensorQuantizer
|
|
32
|
+
|
|
33
|
+
_cell_call_map = {
|
|
34
|
+
"RNN_TANH": _VF.rnn_tanh_cell,
|
|
35
|
+
"RNN_RELU": _VF.rnn_relu_cell,
|
|
36
|
+
"LSTM": _VF.lstm_cell,
|
|
37
|
+
"GRU": _VF.gru_cell,
|
|
38
|
+
}
|
|
39
|
+
_layer_call_name_map = {
|
|
40
|
+
"RNN_TANH": "rnn_tanh",
|
|
41
|
+
"RNN_RELU": "rnn_relu",
|
|
42
|
+
"LSTM": "lstm",
|
|
43
|
+
"GRU": "gru",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class QuantRNNBase(QuantModule):
|
|
48
|
+
"""Base class for quantized RNN modules."""
|
|
49
|
+
|
|
50
|
+
weight_quantizer: TensorQuantizer | SequentialQuantizer
|
|
51
|
+
_enable_weight_quantization: bool
|
|
52
|
+
default_quant_desc_weight = QUANT_DESC_8BIT_PER_TENSOR
|
|
53
|
+
default_quant_desc_input = QUANT_DESC_8BIT_PER_TENSOR
|
|
54
|
+
_functionals_to_replace: list[tuple[ModuleType, str, Callable]] = []
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def functionals_to_replace(self) -> Iterator[tuple[ModuleType, str, Callable]]:
|
|
58
|
+
"""Replace functions of packages on the fly."""
|
|
59
|
+
return (
|
|
60
|
+
(package, func_name, quantized_func)
|
|
61
|
+
for package, func_name, quantized_func in self._functionals_to_replace
|
|
62
|
+
if hasattr(package, func_name)
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def all_input_quantizers_disabled(self):
|
|
67
|
+
"""Check if all input quantizer are disabled."""
|
|
68
|
+
return all(not iq.is_enabled for iq in self._input_quantizers + self._proj_input_quantizers)
|
|
69
|
+
|
|
70
|
+
@contextlib.contextmanager
|
|
71
|
+
def quantize_weight(self):
|
|
72
|
+
"""Context in which ``self.weight`` is quantized."""
|
|
73
|
+
self._enable_weight_quantization = True
|
|
74
|
+
yield
|
|
75
|
+
self._enable_weight_quantization = False
|
|
76
|
+
|
|
77
|
+
@staticmethod
|
|
78
|
+
def _get_quantized_weight_handler(weight_quantizer_name: str):
|
|
79
|
+
def _get_quantized_weight(module: "QuantRNNBase", weight: torch.Tensor):
|
|
80
|
+
if module._enable_weight_quantization:
|
|
81
|
+
weight_quantizer = getattr(module, weight_quantizer_name)
|
|
82
|
+
return weight_quantizer(weight)
|
|
83
|
+
return weight
|
|
84
|
+
|
|
85
|
+
return _get_quantized_weight
|
|
86
|
+
|
|
87
|
+
def forward(self, input, *args, **kwargs):
|
|
88
|
+
"""Quantize the input and the weight before calling the original forward method."""
|
|
89
|
+
contexts = (
|
|
90
|
+
replace_function(package, func_name, quantized_func)
|
|
91
|
+
for package, func_name, quantized_func in self.functionals_to_replace
|
|
92
|
+
)
|
|
93
|
+
if is_torch_export_mode():
|
|
94
|
+
return super().forward(input, *args, **kwargs)
|
|
95
|
+
with multi_context(
|
|
96
|
+
self.quantize_weight(),
|
|
97
|
+
*contexts,
|
|
98
|
+
):
|
|
99
|
+
return super().forward(input, *args, **kwargs)
|
|
100
|
+
|
|
101
|
+
def _setup(self):
|
|
102
|
+
for name, _ in self.named_parameters():
|
|
103
|
+
if name.startswith("weight"):
|
|
104
|
+
# to be compatible with our current config, the name is some what weird
|
|
105
|
+
# it would be weight_xxx_weight_quantizer
|
|
106
|
+
weight_quantizer_name = name + "_weight_quantizer"
|
|
107
|
+
self._register_temp_attribute(
|
|
108
|
+
weight_quantizer_name, TensorQuantizer(self.default_quant_desc_weight)
|
|
109
|
+
)
|
|
110
|
+
self._register_dynamic_attribute(
|
|
111
|
+
name, self._get_quantized_weight_handler(weight_quantizer_name)
|
|
112
|
+
)
|
|
113
|
+
# for cells
|
|
114
|
+
self._register_temp_attribute("_input_quantizers", [])
|
|
115
|
+
num_directions = 2 if self.bidirectional else 1
|
|
116
|
+
# for projection layer if exists
|
|
117
|
+
self._register_temp_attribute("_proj_input_quantizers", [])
|
|
118
|
+
|
|
119
|
+
# the input quantizer is per cell (or per layer) based
|
|
120
|
+
for layer in range(self.num_layers * num_directions):
|
|
121
|
+
for direction in range(num_directions):
|
|
122
|
+
suffix = "_reverse" if direction == 1 else ""
|
|
123
|
+
name = f"layer_{layer}{suffix}_input_quantizer"
|
|
124
|
+
quantizer = TensorQuantizer(self.default_quant_desc_input)
|
|
125
|
+
self._register_temp_attribute(name, quantizer)
|
|
126
|
+
self._input_quantizers.append(quantizer)
|
|
127
|
+
if self.proj_size > 0:
|
|
128
|
+
name = f"proj_{layer}{suffix}_input_quantizer"
|
|
129
|
+
quantizer = TensorQuantizer(self.default_quant_desc_input)
|
|
130
|
+
self._register_temp_attribute(name, quantizer)
|
|
131
|
+
self._proj_input_quantizers.append(quantizer)
|
|
132
|
+
self._register_temp_attribute("_enable_weight_quantization", False)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class QuantRNNFullBase(QuantRNNBase):
|
|
136
|
+
"""Quantized RNN with input quantizer."""
|
|
137
|
+
|
|
138
|
+
def _disable_input_quantizers(self):
|
|
139
|
+
for iq in self._input_quantizers + self._proj_input_quantizers:
|
|
140
|
+
iq.disable()
|
|
141
|
+
|
|
142
|
+
def _enable_input_quantizers(self):
|
|
143
|
+
for iq in self._input_quantizers + self._proj_input_quantizers:
|
|
144
|
+
iq.enable()
|
|
145
|
+
|
|
146
|
+
def _disable_weight_quantizers(self):
|
|
147
|
+
for name, module in self.named_modules():
|
|
148
|
+
if name.endswith("weight_quantizer"):
|
|
149
|
+
module.disable()
|
|
150
|
+
|
|
151
|
+
def _enable_weight_quantizer(self):
|
|
152
|
+
for name, module in self.named_modules():
|
|
153
|
+
if name.endswith("weight_quantizer"):
|
|
154
|
+
module.enable()
|
|
155
|
+
|
|
156
|
+
def _setup(self):
|
|
157
|
+
super()._setup()
|
|
158
|
+
vf_rnn = VFRNNForward(
|
|
159
|
+
self.mode,
|
|
160
|
+
self.bidirectional,
|
|
161
|
+
self.num_layers,
|
|
162
|
+
self.proj_size > 0,
|
|
163
|
+
self.bias,
|
|
164
|
+
self._input_quantizers,
|
|
165
|
+
self._proj_input_quantizers if self.proj_size > 0 else None,
|
|
166
|
+
self.batch_first,
|
|
167
|
+
)
|
|
168
|
+
self._functionals_to_replace = [(_VF, _layer_call_name_map[self.mode], vf_rnn)]
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class VFRNNForward:
|
|
172
|
+
"""Reimplement the _VF rnn calls with python to enable input quantizers.
|
|
173
|
+
|
|
174
|
+
It's less efficient compared to original calls.
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
def __init__(
|
|
178
|
+
self,
|
|
179
|
+
mode: str,
|
|
180
|
+
bidirectional: bool,
|
|
181
|
+
num_layers: int,
|
|
182
|
+
has_proj: bool,
|
|
183
|
+
has_bias: bool,
|
|
184
|
+
input_quantizers: list[TensorQuantizer],
|
|
185
|
+
proj_input_quantizers: list[TensorQuantizer] | None = None,
|
|
186
|
+
batch_first: bool | None = False,
|
|
187
|
+
):
|
|
188
|
+
"""Pre-construct necessary parameters for vf calls to reduce overhead.
|
|
189
|
+
|
|
190
|
+
Refer to torch RNN modules for parameter information.
|
|
191
|
+
"""
|
|
192
|
+
cell = _cell_call_map[mode]
|
|
193
|
+
if has_proj:
|
|
194
|
+
cell = lstm_cell_with_proj
|
|
195
|
+
self.layer_forwards_const = (RNNLayerForward(cell, variable_len=False),)
|
|
196
|
+
self.layer_forwards_variable = (RNNLayerForward(cell, variable_len=True),)
|
|
197
|
+
if bidirectional:
|
|
198
|
+
self.layer_forwards_const += (RNNLayerForward(cell, reverse=True, variable_len=False),)
|
|
199
|
+
self.layer_forwards_variable += (
|
|
200
|
+
RNNLayerForward(cell, reverse=True, variable_len=True),
|
|
201
|
+
)
|
|
202
|
+
self.num_directions = 2 if bidirectional else 1
|
|
203
|
+
self.total_layers = num_layers * self.num_directions
|
|
204
|
+
self.num_layers = num_layers
|
|
205
|
+
self.is_lstm = mode == "LSTM"
|
|
206
|
+
self.has_proj = has_proj
|
|
207
|
+
|
|
208
|
+
self.num_weights_per_layer = self.num_cell_weights_per_layer = 4 if has_bias else 2
|
|
209
|
+
if has_proj:
|
|
210
|
+
self.num_weights_per_layer += 1
|
|
211
|
+
|
|
212
|
+
self.input_quantizers = input_quantizers
|
|
213
|
+
|
|
214
|
+
self.proj_input_quantizers = proj_input_quantizers
|
|
215
|
+
self.batch_first = batch_first
|
|
216
|
+
|
|
217
|
+
def forward(
|
|
218
|
+
self,
|
|
219
|
+
layer_forwards: tuple[Callable],
|
|
220
|
+
input: torch.Tensor,
|
|
221
|
+
flat_weights: list[torch.Tensor],
|
|
222
|
+
hidden: torch.Tensor | tuple[torch.Tensor],
|
|
223
|
+
dropout: float | None = 0,
|
|
224
|
+
training: bool | None = True,
|
|
225
|
+
batch_sizes: torch.Tensor | None = None,
|
|
226
|
+
):
|
|
227
|
+
"""This this the core implementation of vf rnn calls."""
|
|
228
|
+
all_hiddens = []
|
|
229
|
+
|
|
230
|
+
if self.is_lstm:
|
|
231
|
+
hidden = list(zip(*hidden))
|
|
232
|
+
if self.batch_first and batch_sizes is None:
|
|
233
|
+
input = input.transpose(0, 1)
|
|
234
|
+
|
|
235
|
+
for i in range(self.num_layers):
|
|
236
|
+
all_output = []
|
|
237
|
+
for j, layer_forward in enumerate(layer_forwards):
|
|
238
|
+
l_i = i * self.num_directions + j
|
|
239
|
+
# the flat_weights is a list of tensors, we need extract weights of each layer
|
|
240
|
+
w_start = l_i * self.num_weights_per_layer
|
|
241
|
+
w_end = w_start + self.num_weights_per_layer
|
|
242
|
+
proj_input_quantizer = (
|
|
243
|
+
self.proj_input_quantizers[l_i] if self.proj_input_quantizers else None
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
hx, output = layer_forward(
|
|
247
|
+
input,
|
|
248
|
+
hidden[l_i],
|
|
249
|
+
flat_weights[w_start:w_end],
|
|
250
|
+
self.input_quantizers[l_i],
|
|
251
|
+
batch_sizes,
|
|
252
|
+
proj_input_quantizer=proj_input_quantizer,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
all_hiddens.append(hx)
|
|
256
|
+
all_output.append(output)
|
|
257
|
+
|
|
258
|
+
input = torch.cat(all_output, -1)
|
|
259
|
+
|
|
260
|
+
if dropout != 0 and i < self.num_layers - 1:
|
|
261
|
+
input = F.dropout(input, p=dropout, training=training, inplace=False)
|
|
262
|
+
|
|
263
|
+
if self.batch_first and batch_sizes is None:
|
|
264
|
+
input = input.transpose(0, 1)
|
|
265
|
+
|
|
266
|
+
if self.is_lstm:
|
|
267
|
+
hn, cn = zip(*all_hiddens)
|
|
268
|
+
all_hiddens = (torch.stack(hn, 0), torch.stack(cn, 0))
|
|
269
|
+
output_tuple = (input, *all_hiddens)
|
|
270
|
+
else:
|
|
271
|
+
all_hiddens = torch.stack(all_hiddens, 0)
|
|
272
|
+
output_tuple = (input, all_hiddens)
|
|
273
|
+
|
|
274
|
+
return output_tuple
|
|
275
|
+
|
|
276
|
+
def __call__(self, *args) -> tuple[torch.Tensor, torch.Tensor]:
|
|
277
|
+
"""Entry of vf calls.
|
|
278
|
+
|
|
279
|
+
Original vf funcs are overloaded cpp funcs. Each has two different signatures,
|
|
280
|
+
one accepts inputs with variable length (packed sequence), the other accepts constant length.
|
|
281
|
+
The difference is that the fourth arg is a bool for constant length.
|
|
282
|
+
"""
|
|
283
|
+
if isinstance(args[3], bool):
|
|
284
|
+
# constant
|
|
285
|
+
(
|
|
286
|
+
input,
|
|
287
|
+
hidden,
|
|
288
|
+
flat_weights,
|
|
289
|
+
bias,
|
|
290
|
+
num_layers,
|
|
291
|
+
dropout,
|
|
292
|
+
training,
|
|
293
|
+
bidirectional,
|
|
294
|
+
batch_first,
|
|
295
|
+
) = args
|
|
296
|
+
batch_sizes = None
|
|
297
|
+
layer_forwards = self.layer_forwards_const
|
|
298
|
+
else:
|
|
299
|
+
# variable
|
|
300
|
+
(
|
|
301
|
+
input,
|
|
302
|
+
batch_sizes,
|
|
303
|
+
hidden,
|
|
304
|
+
flat_weights,
|
|
305
|
+
bias,
|
|
306
|
+
num_layers,
|
|
307
|
+
dropout,
|
|
308
|
+
training,
|
|
309
|
+
bidirectional,
|
|
310
|
+
) = args
|
|
311
|
+
layer_forwards = self.layer_forwards_variable
|
|
312
|
+
|
|
313
|
+
return self.forward(
|
|
314
|
+
layer_forwards,
|
|
315
|
+
input,
|
|
316
|
+
flat_weights,
|
|
317
|
+
hidden,
|
|
318
|
+
dropout,
|
|
319
|
+
training,
|
|
320
|
+
batch_sizes,
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
class RNNLayerForward:
|
|
325
|
+
"""A single layer of rnn modules."""
|
|
326
|
+
|
|
327
|
+
def __init__(self, cell, reverse=False, variable_len=False):
|
|
328
|
+
"""Init the layer forward for different cells, directions, and inputs."""
|
|
329
|
+
self.cell = cell
|
|
330
|
+
self.reverse = reverse
|
|
331
|
+
self.variable_len = variable_len
|
|
332
|
+
if variable_len:
|
|
333
|
+
if reverse:
|
|
334
|
+
self.forward = get_quantized_rnn_layer_variable_len_reverse_forward(cell)
|
|
335
|
+
else:
|
|
336
|
+
self.forward = get_quantized_rnn_layer_variable_len_forward(cell)
|
|
337
|
+
else:
|
|
338
|
+
self.forward = get_quantized_rnn_layer_forward(cell, reverse=reverse)
|
|
339
|
+
|
|
340
|
+
def __call__(
|
|
341
|
+
self, input, hidden, weights, input_quantizer, batch_sizes=None, proj_input_quantizer=None
|
|
342
|
+
) -> Any:
|
|
343
|
+
"""Layer forward."""
|
|
344
|
+
return self.forward(
|
|
345
|
+
input,
|
|
346
|
+
hidden,
|
|
347
|
+
weights,
|
|
348
|
+
input_quantizer,
|
|
349
|
+
batch_sizes=batch_sizes,
|
|
350
|
+
proj_input_quantizer=proj_input_quantizer,
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def lstm_cell_with_proj(input, hidden, *weights, proj_input_quantizer=None):
|
|
355
|
+
"""Currently the _VF.lstm_cell doesn't accept projected inputs. i.e. h_n and c_n must be same shape.
|
|
356
|
+
|
|
357
|
+
This implementation is not optimized for cuda compared to _VF.lstm_cell, so we only use it when projection exists.
|
|
358
|
+
"""
|
|
359
|
+
if len(weights) == 3:
|
|
360
|
+
weight_ih, weight_hh, weight_hr = weights
|
|
361
|
+
bias_ih = bias_hh = None
|
|
362
|
+
else:
|
|
363
|
+
weight_ih, weight_hh, bias_ih, bias_hh, weight_hr = weights
|
|
364
|
+
hn, cn = hidden
|
|
365
|
+
|
|
366
|
+
gates = F.linear(input, weight_ih, bias_ih) + F.linear(hn, weight_hh, bias_hh)
|
|
367
|
+
|
|
368
|
+
ingate, forgetgate, cellgate, outgate = gates.chunk(4, 1)
|
|
369
|
+
|
|
370
|
+
ingate = torch.sigmoid(ingate)
|
|
371
|
+
forgetgate = torch.sigmoid(forgetgate)
|
|
372
|
+
cellgate = torch.tanh(cellgate)
|
|
373
|
+
outgate = torch.sigmoid(outgate)
|
|
374
|
+
|
|
375
|
+
cy = (forgetgate * cn) + (ingate * cellgate)
|
|
376
|
+
hy = outgate * torch.tanh(cy)
|
|
377
|
+
if proj_input_quantizer is not None:
|
|
378
|
+
hy = proj_input_quantizer(hy)
|
|
379
|
+
hy = F.linear(hy, weight_hr)
|
|
380
|
+
return hy, cy
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def quantized_cell_forward(
|
|
384
|
+
cell, input, hidden, weights, input_quantizer, proj_input_quantizer=None
|
|
385
|
+
):
|
|
386
|
+
"""Call input quantizer before calling cell."""
|
|
387
|
+
quant_input = input_quantizer(input)
|
|
388
|
+
quant_hidden = (
|
|
389
|
+
(input_quantizer(hidden[0]), input_quantizer(hidden[1]))
|
|
390
|
+
if isinstance(hidden, tuple)
|
|
391
|
+
else input_quantizer(hidden)
|
|
392
|
+
)
|
|
393
|
+
kwargs = {} if proj_input_quantizer is None else {"proj_input_quantizer": proj_input_quantizer}
|
|
394
|
+
hidden = cell(quant_input, quant_hidden, *weights, **kwargs)
|
|
395
|
+
return hidden
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def get_quantized_rnn_layer_forward(cell, reverse=False):
|
|
399
|
+
"""Construct the forward call for different rnn cells.
|
|
400
|
+
|
|
401
|
+
Note that batch_sizes is here for keeping a consistent signature with the forward of variable length.
|
|
402
|
+
"""
|
|
403
|
+
|
|
404
|
+
def forward(
|
|
405
|
+
input, hidden, weights, input_quantizer, batch_sizes=None, proj_input_quantizer=None
|
|
406
|
+
):
|
|
407
|
+
seq_len = input.shape[0]
|
|
408
|
+
steps = reversed(range(seq_len)) if reverse else range(seq_len)
|
|
409
|
+
|
|
410
|
+
output = []
|
|
411
|
+
for i in steps:
|
|
412
|
+
hidden = quantized_cell_forward(
|
|
413
|
+
cell,
|
|
414
|
+
input[i],
|
|
415
|
+
hidden,
|
|
416
|
+
weights,
|
|
417
|
+
input_quantizer,
|
|
418
|
+
proj_input_quantizer=proj_input_quantizer,
|
|
419
|
+
)
|
|
420
|
+
output.append(hidden[0] if isinstance(hidden, tuple) else hidden)
|
|
421
|
+
|
|
422
|
+
if reverse:
|
|
423
|
+
output.reverse()
|
|
424
|
+
output = torch.stack(output, 0)
|
|
425
|
+
|
|
426
|
+
return hidden, output
|
|
427
|
+
|
|
428
|
+
return forward
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def get_quantized_rnn_layer_variable_len_forward(cell):
|
|
432
|
+
"""Construct the forward call for packed sequence."""
|
|
433
|
+
|
|
434
|
+
def forward(input, hidden, weights, input_quantizer, batch_sizes, proj_input_quantizer=None):
|
|
435
|
+
output = []
|
|
436
|
+
input_offset = 0
|
|
437
|
+
last_batch_size = batch_sizes[0]
|
|
438
|
+
hiddens = []
|
|
439
|
+
flat_hidden = not isinstance(hidden, tuple)
|
|
440
|
+
if flat_hidden:
|
|
441
|
+
hidden = (hidden,)
|
|
442
|
+
for batch_size in batch_sizes:
|
|
443
|
+
step_input = input[input_offset : input_offset + batch_size]
|
|
444
|
+
input_offset += batch_size
|
|
445
|
+
|
|
446
|
+
dec = last_batch_size - batch_size
|
|
447
|
+
if dec > 0:
|
|
448
|
+
hiddens.append(tuple(h[-dec:] for h in hidden))
|
|
449
|
+
hidden = tuple(h[:-dec] for h in hidden)
|
|
450
|
+
last_batch_size = batch_size
|
|
451
|
+
hx = hidden[0] if flat_hidden else hidden
|
|
452
|
+
hidden = quantized_cell_forward(
|
|
453
|
+
cell,
|
|
454
|
+
step_input,
|
|
455
|
+
hx,
|
|
456
|
+
weights,
|
|
457
|
+
input_quantizer,
|
|
458
|
+
proj_input_quantizer=proj_input_quantizer,
|
|
459
|
+
)
|
|
460
|
+
if flat_hidden:
|
|
461
|
+
hidden = (hidden,)
|
|
462
|
+
|
|
463
|
+
output.append(hidden[0])
|
|
464
|
+
hiddens.append(hidden)
|
|
465
|
+
hiddens.reverse()
|
|
466
|
+
|
|
467
|
+
hidden = tuple(torch.cat(h, 0) for h in zip(*hiddens))
|
|
468
|
+
assert hidden[0].shape[0] == batch_sizes[0]
|
|
469
|
+
if flat_hidden:
|
|
470
|
+
hidden = hidden[0]
|
|
471
|
+
output = torch.cat(output, 0)
|
|
472
|
+
|
|
473
|
+
return hidden, output
|
|
474
|
+
|
|
475
|
+
return forward
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
def get_quantized_rnn_layer_variable_len_reverse_forward(cell):
|
|
479
|
+
"""Construct the forward call for packed sequence in the reversed direction."""
|
|
480
|
+
|
|
481
|
+
def forward(input, hidden, weights, input_quantizer, batch_sizes, proj_input_quantizer=None):
|
|
482
|
+
output = []
|
|
483
|
+
input_offset = input.shape[0]
|
|
484
|
+
last_batch_size = batch_sizes[-1]
|
|
485
|
+
initial_hidden = hidden
|
|
486
|
+
flat_hidden = not isinstance(hidden, tuple)
|
|
487
|
+
if flat_hidden:
|
|
488
|
+
hidden = (hidden,)
|
|
489
|
+
initial_hidden = (initial_hidden,)
|
|
490
|
+
hidden = tuple(h[: batch_sizes[-1]] for h in hidden)
|
|
491
|
+
for i in reversed(range(len(batch_sizes))):
|
|
492
|
+
batch_size = batch_sizes[i]
|
|
493
|
+
inc = batch_size - last_batch_size
|
|
494
|
+
if inc > 0:
|
|
495
|
+
hidden = tuple(
|
|
496
|
+
torch.cat((h, ih[last_batch_size:batch_size]), 0)
|
|
497
|
+
for h, ih in zip(hidden, initial_hidden)
|
|
498
|
+
)
|
|
499
|
+
last_batch_size = batch_size
|
|
500
|
+
step_input = input[input_offset - batch_size : input_offset]
|
|
501
|
+
input_offset -= batch_size
|
|
502
|
+
|
|
503
|
+
hx = hidden[0] if flat_hidden else hidden
|
|
504
|
+
hidden = quantized_cell_forward(
|
|
505
|
+
cell,
|
|
506
|
+
step_input,
|
|
507
|
+
hx,
|
|
508
|
+
weights,
|
|
509
|
+
input_quantizer,
|
|
510
|
+
proj_input_quantizer=proj_input_quantizer,
|
|
511
|
+
)
|
|
512
|
+
if flat_hidden:
|
|
513
|
+
hidden = (hidden,)
|
|
514
|
+
output.append(hidden[0])
|
|
515
|
+
|
|
516
|
+
output.reverse()
|
|
517
|
+
output = torch.cat(output, 0)
|
|
518
|
+
if flat_hidden:
|
|
519
|
+
hidden = hidden[0]
|
|
520
|
+
return hidden, output
|
|
521
|
+
|
|
522
|
+
return forward
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
QuantModuleRegistry.register({nn.RNN: "nn.RNN"})(QuantRNNFullBase)
|
|
526
|
+
QuantModuleRegistry.register({nn.LSTM: "nn.LSTM"})(QuantRNNFullBase)
|
|
527
|
+
QuantModuleRegistry.register({nn.GRU: "nn.GRU"})(QuantRNNFullBase)
|