ZhengyangZhang commited on
Commit
13a5289
·
verified ·
1 Parent(s): cafebc0

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. lib/python3.12/site-packages/compressed_tensors/__init__.py +22 -0
  2. lib/python3.12/site-packages/compressed_tensors/__pycache__/__init__.cpython-312.pyc +0 -0
  3. lib/python3.12/site-packages/compressed_tensors/__pycache__/base.cpython-312.pyc +0 -0
  4. lib/python3.12/site-packages/compressed_tensors/__pycache__/version.cpython-312.pyc +0 -0
  5. lib/python3.12/site-packages/compressed_tensors/base.py +20 -0
  6. lib/python3.12/site-packages/compressed_tensors/compressors/__init__.py +22 -0
  7. lib/python3.12/site-packages/compressed_tensors/compressors/__pycache__/__init__.cpython-312.pyc +0 -0
  8. lib/python3.12/site-packages/compressed_tensors/compressors/__pycache__/base.cpython-312.pyc +0 -0
  9. lib/python3.12/site-packages/compressed_tensors/compressors/__pycache__/helpers.cpython-312.pyc +0 -0
  10. lib/python3.12/site-packages/compressed_tensors/compressors/base.py +197 -0
  11. lib/python3.12/site-packages/compressed_tensors/compressors/helpers.py +137 -0
  12. lib/python3.12/site-packages/compressed_tensors/compressors/model_compressors/__init__.py +17 -0
  13. lib/python3.12/site-packages/compressed_tensors/compressors/model_compressors/__pycache__/__init__.cpython-312.pyc +0 -0
  14. lib/python3.12/site-packages/compressed_tensors/compressors/model_compressors/__pycache__/model_compressor.cpython-312.pyc +0 -0
  15. lib/python3.12/site-packages/compressed_tensors/compressors/model_compressors/model_compressor.py +580 -0
  16. lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/__init__.py +18 -0
  17. lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/__pycache__/__init__.cpython-312.pyc +0 -0
  18. lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/__pycache__/base.cpython-312.pyc +0 -0
  19. lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/__pycache__/naive_quantized.cpython-312.pyc +0 -0
  20. lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/__pycache__/pack_quantized.cpython-312.pyc +0 -0
  21. lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/base.py +205 -0
  22. lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/naive_quantized.py +148 -0
  23. lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/pack_quantized.py +236 -0
  24. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/__init__.py +19 -0
  25. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/__pycache__/__init__.cpython-312.pyc +0 -0
  26. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/__pycache__/base.cpython-312.pyc +0 -0
  27. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/__pycache__/dense.cpython-312.pyc +0 -0
  28. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/__pycache__/sparse_24_bitmask.cpython-312.pyc +0 -0
  29. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/__pycache__/sparse_bitmask.cpython-312.pyc +0 -0
  30. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/base.py +147 -0
  31. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/dense.py +42 -0
  32. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/sparse_24_bitmask.py +246 -0
  33. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/sparse_bitmask.py +169 -0
  34. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_quantized_compressors/__init__.py +16 -0
  35. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_quantized_compressors/__pycache__/__init__.cpython-312.pyc +0 -0
  36. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_quantized_compressors/__pycache__/marlin_24.cpython-312.pyc +0 -0
  37. lib/python3.12/site-packages/compressed_tensors/compressors/sparse_quantized_compressors/marlin_24.py +257 -0
  38. lib/python3.12/site-packages/compressed_tensors/config/__init__.py +19 -0
  39. lib/python3.12/site-packages/compressed_tensors/config/__pycache__/__init__.cpython-312.pyc +0 -0
  40. lib/python3.12/site-packages/compressed_tensors/config/__pycache__/base.cpython-312.pyc +0 -0
  41. lib/python3.12/site-packages/compressed_tensors/config/__pycache__/dense.cpython-312.pyc +0 -0
  42. lib/python3.12/site-packages/compressed_tensors/config/__pycache__/sparse_24_bitmask.cpython-312.pyc +0 -0
  43. lib/python3.12/site-packages/compressed_tensors/config/__pycache__/sparse_bitmask.cpython-312.pyc +0 -0
  44. lib/python3.12/site-packages/compressed_tensors/config/base.py +111 -0
  45. lib/python3.12/site-packages/compressed_tensors/config/dense.py +36 -0
  46. lib/python3.12/site-packages/compressed_tensors/config/sparse_24_bitmask.py +40 -0
  47. lib/python3.12/site-packages/compressed_tensors/config/sparse_bitmask.py +36 -0
  48. lib/python3.12/site-packages/compressed_tensors/linear/__init__.py +13 -0
  49. lib/python3.12/site-packages/compressed_tensors/linear/__pycache__/__init__.cpython-312.pyc +0 -0
  50. lib/python3.12/site-packages/compressed_tensors/linear/__pycache__/compressed_linear.cpython-312.pyc +0 -0
lib/python3.12/site-packages/compressed_tensors/__init__.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from .base import *
16
+
17
+ # flake8: noqa
18
+ from .compressors import *
19
+ from .config import *
20
+ from .quantization import QuantizationConfig, QuantizationStatus
21
+ from .utils import *
22
+ from .version import *
lib/python3.12/site-packages/compressed_tensors/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (401 Bytes). View file
 
lib/python3.12/site-packages/compressed_tensors/__pycache__/base.cpython-312.pyc ADDED
Binary file (497 Bytes). View file
 
lib/python3.12/site-packages/compressed_tensors/__pycache__/version.cpython-312.pyc ADDED
Binary file (1.14 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/base.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ SPARSITY_CONFIG_NAME = "sparsity_config"
16
+ QUANTIZATION_CONFIG_NAME = "quantization_config"
17
+ COMPRESSION_CONFIG_NAME = "compression_config"
18
+ KV_CACHE_SCHEME_NAME = "kv_cache_scheme"
19
+ COMPRESSION_VERSION_NAME = "version"
20
+ QUANTIZATION_METHOD_NAME = "quant_method"
lib/python3.12/site-packages/compressed_tensors/compressors/__init__.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # flake8: noqa
16
+
17
+ from .base import *
18
+ from .helpers import *
19
+ from .model_compressors import *
20
+ from .quantized_compressors import *
21
+ from .sparse_compressors import *
22
+ from .sparse_quantized_compressors import *
lib/python3.12/site-packages/compressed_tensors/compressors/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (403 Bytes). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/__pycache__/base.cpython-312.pyc ADDED
Binary file (7.56 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/__pycache__/helpers.cpython-312.pyc ADDED
Binary file (5.69 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/base.py ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from abc import ABC, abstractmethod
16
+ from typing import Dict, Generator, Optional, Tuple, Union
17
+
18
+ import torch
19
+ from compressed_tensors.config import SparsityCompressionConfig
20
+ from compressed_tensors.quantization import QuantizationArgs, QuantizationConfig
21
+ from compressed_tensors.registry import RegistryMixin
22
+ from torch import Tensor
23
+ from torch.nn import Module
24
+
25
+
26
+ __all__ = ["BaseCompressor"]
27
+
28
+
29
+ class BaseCompressor(RegistryMixin, ABC):
30
+ """
31
+ Base class representing a model compression algorithm. Each child class should
32
+ implement compression_param_info, compress_weight and decompress_weight.
33
+
34
+ Compressors support compressing/decompressing a full module state dict or a single
35
+ quantized PyTorch leaf module.
36
+
37
+ Model Load Lifecycle (run_compressed=False):
38
+ - ModelCompressor.decompress()
39
+ - apply_quantization_config()
40
+ - BaseCompressor.decompress()
41
+
42
+ Model Save Lifecycle:
43
+ - ModelCompressor.compress()
44
+ - BaseCompressor.compress()
45
+
46
+
47
+ Module Lifecycle (run_compressed=True):
48
+ - apply_quantization_config()
49
+ - compressed_module = CompressedLinear(module)
50
+ - initialize_module_for_quantization()
51
+ - BaseCompressor.compression_param_info()
52
+ - register_parameters()
53
+ - compressed_module.forward()
54
+ -compressed_module.decompress()
55
+
56
+
57
+ :param config: config specifying compression parameters
58
+ """
59
+
60
+ def __init__(
61
+ self, config: Union[SparsityCompressionConfig, QuantizationConfig, None] = None
62
+ ):
63
+ self.config = config
64
+
65
+ def compression_param_info(
66
+ self,
67
+ weight_shape: torch.Size,
68
+ quantization_args: Optional[QuantizationArgs] = None,
69
+ ) -> Dict[str, Tuple[torch.Size, torch.dtype]]:
70
+ """
71
+ Creates a dictionary of expected shapes and dtypes for each compression
72
+ parameter used by the compressor
73
+
74
+ :param weight_shape: uncompressed weight shape
75
+ :param quantization_args: quantization parameters for the weight
76
+ :return: dictionary mapping compressed parameter names to shape and dtype
77
+ """
78
+ raise NotImplementedError()
79
+
80
+ @property
81
+ @abstractmethod
82
+ def compression_param_names(self) -> Tuple[str]:
83
+ """
84
+ Returns a tuple of compression parameter names introduced by
85
+ the compressor during compression
86
+ """
87
+ raise NotImplementedError()
88
+
89
+ @abstractmethod
90
+ def compress(
91
+ self,
92
+ model_state: Dict[str, Tensor],
93
+ **kwargs,
94
+ ) -> Dict[str, Tensor]:
95
+ """
96
+ Compresses a dense state dict
97
+
98
+ :param model_state: state dict of uncompressed model
99
+ :param kwargs: additional arguments for compression
100
+ :return: compressed state dict
101
+ """
102
+ raise NotImplementedError()
103
+
104
+ @abstractmethod
105
+ def decompress(
106
+ self,
107
+ path_to_model_or_tensors: str,
108
+ device: str = "cpu",
109
+ **kwargs,
110
+ ) -> Generator[Tuple[str, Tensor], None, None]:
111
+ """
112
+ Reads a compressed state dict located at path_to_model_or_tensors
113
+ and returns a generator for sequentially decompressing back to a
114
+ dense state dict
115
+
116
+ :param path_to_model_or_tensors: path to compressed safetensors model (directory
117
+ with one or more safetensors files) or compressed tensors file
118
+ :param names_to_scheme: quantization args for each quantized weight
119
+ :param device: optional device to load intermediate weights into
120
+ :return: compressed state dict
121
+ """
122
+ raise NotImplementedError()
123
+
124
+ def compress_module(self, module: Module) -> Optional[Dict[str, torch.Tensor]]:
125
+ """
126
+ Compresses a single quantized leaf PyTorch module. If the module is not
127
+ quantized, this function has no effect.
128
+
129
+ :param module: PyTorch module to compress
130
+ :return: dictionary of compressed weight data, or None if module is not
131
+ quantized
132
+ """
133
+ if not hasattr(module, "quantization_scheme"):
134
+ return None # module is not quantized
135
+ quantization_scheme = module.quantization_scheme
136
+ if not hasattr(quantization_scheme, "weights"):
137
+ return None # weights are not quantized
138
+
139
+ quantization_args = quantization_scheme.weights
140
+ weight = getattr(module, "weight", None)
141
+ weight_scale = getattr(module, "weight_scale", None)
142
+ weight_zero_point = getattr(module, "weight_zero_point", None)
143
+
144
+ return self.compress_weight(
145
+ weight=weight,
146
+ scale=weight_scale,
147
+ zero_point=weight_zero_point,
148
+ quantization_args=quantization_args,
149
+ )
150
+
151
+ def compress_weight(
152
+ self,
153
+ weight: Tensor,
154
+ **kwargs,
155
+ ) -> Dict[str, torch.Tensor]:
156
+ """
157
+ Compresses a single uncompressed weight
158
+
159
+ :param weight: uncompressed weight tensor
160
+ :param kwargs: additional arguments for compression
161
+ """
162
+ raise NotImplementedError()
163
+
164
+ def decompress_module(self, module: Module):
165
+ """
166
+ Decompresses a single compressed leaf PyTorch module. If the module is not
167
+ quantized, this function has no effect.
168
+
169
+ :param module: PyTorch module to decompress
170
+ :return: tensor of the decompressed weight, or None if module is not quantized
171
+ """
172
+ if not hasattr(module, "quantization_scheme"):
173
+ return None # module is not quantized
174
+ quantization_scheme = module.quantization_scheme
175
+ if not hasattr(quantization_scheme, "weights"):
176
+ return None # weights are not quantized
177
+
178
+ quantization_args = quantization_scheme.weights
179
+ compressed_data = {}
180
+ for name, parameter in module.named_parameters():
181
+ compressed_data[name] = parameter
182
+
183
+ return self.decompress_weight(
184
+ compressed_data=compressed_data, quantization_args=quantization_args
185
+ )
186
+
187
+ def decompress_weight(
188
+ self, compressed_data: Dict[str, Tensor], **kwargs
189
+ ) -> torch.Tensor:
190
+ """
191
+ Decompresses a single compressed weight
192
+
193
+ :param compressed_data: dictionary of data needed for decompression
194
+ :param kwargs: additional arguments for decompression
195
+ :return: tensor of the decompressed weight
196
+ """
197
+ raise NotImplementedError()
lib/python3.12/site-packages/compressed_tensors/compressors/helpers.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from pathlib import Path
16
+ from typing import Dict, Generator, Optional, Tuple, Union
17
+
18
+ import torch
19
+ from compressed_tensors.compressors import BaseCompressor
20
+ from compressed_tensors.config import CompressionFormat, SparsityCompressionConfig
21
+ from compressed_tensors.utils.safetensors_load import get_weight_mappings
22
+ from safetensors import safe_open
23
+ from safetensors.torch import save_file
24
+ from torch import Tensor
25
+
26
+
27
+ __all__ = [
28
+ "load_compressed",
29
+ "save_compressed",
30
+ "save_compressed_model",
31
+ ]
32
+
33
+
34
+ def save_compressed(
35
+ tensors: Dict[str, Tensor],
36
+ save_path: Union[str, Path],
37
+ compression_format: Optional[CompressionFormat] = None,
38
+ ):
39
+ """
40
+ Save compressed tensors to disk. If tensors are not compressed,
41
+ save them as is.
42
+
43
+ :param tensors: dictionary of tensors to compress
44
+ :param save_path: path to save compressed tensors
45
+ :param compression_format: compression format used for the tensors
46
+ :return: compression config, if tensors were compressed - None otherwise
47
+ """
48
+ if tensors is None or len(tensors) == 0:
49
+ raise ValueError("No tensors or empty tensors provided to compress")
50
+
51
+ # if no compression_format specified, default to `dense`
52
+ compression_format = compression_format or CompressionFormat.dense.value
53
+
54
+ if not (
55
+ compression_format in BaseCompressor.registered_names()
56
+ or compression_format in BaseCompressor.registered_aliases()
57
+ ):
58
+ raise ValueError(
59
+ f"Unknown compression format: {compression_format}. "
60
+ f"Must be one of {set(BaseCompressor.registered_names() + BaseCompressor.registered_aliases())}" # noqa E501
61
+ )
62
+
63
+ # compress
64
+ compressor = BaseCompressor.load_from_registry(compression_format)
65
+ # save compressed tensors
66
+ compressed_tensors = compressor.compress(tensors)
67
+ save_file(compressed_tensors, save_path)
68
+
69
+
70
+ def load_compressed(
71
+ compressed_tensors: Union[str, Path],
72
+ compression_config: SparsityCompressionConfig = None,
73
+ device: Optional[str] = "cpu",
74
+ ) -> Generator[Tuple[str, Tensor], None, None]:
75
+ """
76
+ Load compressed tensors from disk.
77
+ If tensors are not compressed, load them as is.
78
+
79
+ :param compressed_tensors: path to compressed tensors.
80
+ This can be a path to a file or a directory containing
81
+ one or multiple safetensor files (if multiple - in the format
82
+ assumed by huggingface)
83
+ :param compression_config: compression config to use for decompressing tensors.
84
+ :param device: device to move tensors to. If None, tensors are loaded on CPU.
85
+ :param return_dict: if True, return a dictionary of decompressed tensors
86
+ :return a generator that yields the name and tensor of the decompressed tensor
87
+ """
88
+ if compressed_tensors is None or not Path(compressed_tensors).exists():
89
+ raise ValueError("No compressed tensors provided to load")
90
+
91
+ if (
92
+ compression_config is None
93
+ or compression_config.format == CompressionFormat.dense.value
94
+ ):
95
+ # if no compression_config specified, or `dense` format specified,
96
+ # assume tensors are not compressed on disk
97
+ weight_mappings = get_weight_mappings(compressed_tensors)
98
+ for weight_name, file_with_weight_name in weight_mappings.items():
99
+ with safe_open(file_with_weight_name, framework="pt", device=device) as f:
100
+ weight = f.get_tensor(weight_name)
101
+ yield weight_name, weight
102
+ else:
103
+ # decompress tensors
104
+ compression_format = compression_config.format
105
+ compressor = BaseCompressor.load_from_registry(
106
+ compression_format, config=compression_config
107
+ )
108
+ yield from compressor.decompress(compressed_tensors, device=device)
109
+
110
+
111
+ def save_compressed_model(
112
+ model: torch.nn.Module,
113
+ filename: str,
114
+ compression_format: Optional[CompressionFormat] = None,
115
+ force_contiguous: bool = True,
116
+ ):
117
+ """
118
+ Wrapper around safetensors `save_model` helper function, which allows for
119
+ saving compressed model to disk.
120
+
121
+ Note: The model is assumed to have a
122
+ state_dict with unique entries
123
+
124
+ :param model: model to save on disk
125
+ :param filename: filename location to save the file
126
+ :param compression_format: compression format used for the model
127
+ :param force_contiguous: forcing the state_dict to be saved as contiguous tensors
128
+ """
129
+ state_dict = model.state_dict()
130
+ if force_contiguous:
131
+ state_dict = {k: v.contiguous() for k, v in state_dict.items()}
132
+ try:
133
+ save_compressed(state_dict, filename, compression_format=compression_format)
134
+ except ValueError as e:
135
+ msg = str(e)
136
+ msg += " Or use save_compressed_model(..., force_contiguous=True), read the docs for potential caveats." # noqa E501
137
+ raise ValueError(msg)
lib/python3.12/site-packages/compressed_tensors/compressors/model_compressors/__init__.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # flake8: noqa
15
+
16
+
17
+ from .model_compressor import *
lib/python3.12/site-packages/compressed_tensors/compressors/model_compressors/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (267 Bytes). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/model_compressors/__pycache__/model_compressor.cpython-312.pyc ADDED
Binary file (23.4 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/model_compressors/model_compressor.py ADDED
@@ -0,0 +1,580 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import json
16
+ import logging
17
+ import operator
18
+ import os
19
+ import re
20
+ from contextlib import contextmanager
21
+ from copy import deepcopy
22
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple, TypeVar, Union
23
+
24
+ import compressed_tensors
25
+ import torch
26
+ import transformers
27
+ from compressed_tensors.base import (
28
+ COMPRESSION_VERSION_NAME,
29
+ QUANTIZATION_CONFIG_NAME,
30
+ QUANTIZATION_METHOD_NAME,
31
+ SPARSITY_CONFIG_NAME,
32
+ )
33
+ from compressed_tensors.compressors.base import BaseCompressor
34
+ from compressed_tensors.config import CompressionFormat, SparsityCompressionConfig
35
+ from compressed_tensors.quantization import (
36
+ DEFAULT_QUANTIZATION_METHOD,
37
+ QuantizationConfig,
38
+ QuantizationStatus,
39
+ apply_quantization_config,
40
+ load_pretrained_quantization,
41
+ )
42
+ from compressed_tensors.quantization.lifecycle import expand_target_names
43
+ from compressed_tensors.quantization.quant_args import QuantizationArgs
44
+ from compressed_tensors.quantization.utils import (
45
+ is_module_quantized,
46
+ iter_named_leaf_modules,
47
+ )
48
+ from compressed_tensors.utils import (
49
+ get_safetensors_folder,
50
+ merge_names,
51
+ update_parameter_data,
52
+ )
53
+ from compressed_tensors.utils.helpers import (
54
+ fix_fsdp_module_name,
55
+ is_compressed_tensors_config,
56
+ )
57
+ from torch import Tensor
58
+ from torch.nn import Module
59
+ from tqdm import tqdm
60
+ from transformers import AutoConfig
61
+ from transformers.file_utils import CONFIG_NAME
62
+
63
+
64
+ __all__ = ["ModelCompressor", "map_modules_to_quant_args"]
65
+
66
+ _LOGGER: logging.Logger = logging.getLogger(__name__)
67
+
68
+
69
+ if TYPE_CHECKING:
70
+ # dummy type if not available from transformers
71
+ CompressedTensorsConfig = TypeVar("CompressedTensorsConfig")
72
+
73
+
74
+ class ModelCompressor:
75
+ """
76
+ Handles compression and decompression of a model with a sparsity config and/or
77
+ quantization config.
78
+
79
+ Compression LifeCycle
80
+ - compressor = ModelCompressor.from_pretrained_model(model)
81
+ - compressed_state_dict = compressor.compress(model, state_dict)
82
+ - compressor.quantization_compressor.compress(model, state_dict)
83
+ - compressor.sparsity_compressor.compress(model, state_dict)
84
+ - model.save_pretrained(output_dir, state_dict=compressed_state_dict)
85
+ - compressor.update_config(output_dir)
86
+
87
+ Decompression LifeCycle
88
+ - compressor = ModelCompressor.from_pretrained(comp_model_path)
89
+ - model = AutoModel.from_pretrained(comp_model_path)
90
+ - compressor.decompress(comp_model_path, model)
91
+ - compressor.sparsity_compressor.decompress(comp_model_path, model)
92
+ - compressor.quantization_compressor.decompress(comp_model_path, model)
93
+
94
+ :param sparsity_config: config specifying sparsity compression parameters
95
+ :param quantization_config: config specifying quantization compression parameters
96
+ """
97
+
98
+ @classmethod
99
+ def from_pretrained(
100
+ cls,
101
+ pretrained_model_name_or_path: str,
102
+ **kwargs,
103
+ ) -> Optional["ModelCompressor"]:
104
+ """
105
+ Given a path to a model config, extract the sparsity and/or quantization
106
+ configs and load a ModelCompressor
107
+
108
+ :param pretrained_model_name_or_path: path to model config on disk or HF hub
109
+ :return: compressor for the configs, or None if model is not compressed
110
+ """
111
+ config = AutoConfig.from_pretrained(pretrained_model_name_or_path, **kwargs)
112
+ compression_config = getattr(config, QUANTIZATION_CONFIG_NAME, None)
113
+ return cls.from_compression_config(compression_config)
114
+
115
+ @classmethod
116
+ def from_compression_config(
117
+ cls,
118
+ compression_config: Union[Dict[str, Any], "CompressedTensorsConfig"],
119
+ ):
120
+ """
121
+ :param compression_config:
122
+ A compression or quantization config
123
+
124
+ The type is one of the following:
125
+ 1. A Dict found under either "quantization_config" or "compression_config"
126
+ keys in the config.json
127
+ 2. A CompressedTensorsConfig found under key "quantization_config" in HF
128
+ model config
129
+ :return: compressor for the configs, or None if model is not compressed
130
+ """
131
+ if compression_config is None:
132
+ return None
133
+
134
+ sparsity_config = cls.parse_sparsity_config(compression_config)
135
+ quantization_config = cls.parse_quantization_config(compression_config)
136
+ if sparsity_config is None and quantization_config is None:
137
+ return None
138
+
139
+ if sparsity_config is not None:
140
+ format = sparsity_config.get("format")
141
+ sparsity_config = SparsityCompressionConfig.load_from_registry(
142
+ format, **sparsity_config
143
+ )
144
+ if quantization_config is not None:
145
+ quantization_config = QuantizationConfig.model_validate(quantization_config)
146
+
147
+ return cls(
148
+ sparsity_config=sparsity_config, quantization_config=quantization_config
149
+ )
150
+
151
+ @classmethod
152
+ def from_pretrained_model(
153
+ cls,
154
+ model: Module,
155
+ sparsity_config: Union[SparsityCompressionConfig, str, None] = None,
156
+ quantization_format: Optional[str] = None,
157
+ ) -> Optional["ModelCompressor"]:
158
+ """
159
+ Given a pytorch model and optional sparsity and/or quantization configs,
160
+ load the appropriate compressors
161
+
162
+ :param model: pytorch model to target for compression
163
+ :param sparsity_config: a filled in sparsity config or string corresponding
164
+ to a sparsity compression algorithm
165
+ :param quantization_format: string corresponding to a quantization compression
166
+ algorithm
167
+ :return: compressor for the configs, or None if model is not compressed
168
+ """
169
+ quantization_config = QuantizationConfig.from_pretrained(
170
+ model, format=quantization_format
171
+ )
172
+
173
+ if isinstance(sparsity_config, str): # we passed in a sparsity format
174
+ sparsity_config = SparsityCompressionConfig.load_from_registry(
175
+ sparsity_config
176
+ )
177
+
178
+ if sparsity_config is None and quantization_config is None:
179
+ return None
180
+
181
+ return cls(
182
+ sparsity_config=sparsity_config, quantization_config=quantization_config
183
+ )
184
+
185
+ @staticmethod
186
+ def parse_sparsity_config(
187
+ compression_config: Union[Dict[str, Any], "CompressedTensorsConfig"]
188
+ ) -> Union[Dict[str, Any], None]:
189
+ """
190
+ Parse sparsity config from quantization/compression config. Sparsity
191
+ config is nested inside q/c config
192
+
193
+ :param compression_config: quantization/compression config
194
+ :return: sparsity config
195
+ """
196
+ if compression_config is None:
197
+ return None
198
+
199
+ if is_compressed_tensors_config(compression_config):
200
+ s_config = compression_config.sparsity_config
201
+ return s_config.model_dump() if s_config is not None else None
202
+
203
+ return compression_config.get(SPARSITY_CONFIG_NAME, None)
204
+
205
+ @staticmethod
206
+ def parse_quantization_config(
207
+ compression_config: Union[Dict[str, Any], "CompressedTensorsConfig"]
208
+ ) -> Union[Dict[str, Any], None]:
209
+ """
210
+ Parse quantization config from quantization/compression config. The
211
+ quantization are all the fields that are not the sparsity config or
212
+ metadata fields
213
+
214
+ :param compression_config: quantization/compression config
215
+ :return: quantization config without sparsity config or metadata fields
216
+ """
217
+ if compression_config is None:
218
+ return None
219
+
220
+ if is_compressed_tensors_config(compression_config):
221
+ q_config = compression_config.quantization_config
222
+ return q_config.model_dump() if q_config is not None else None
223
+
224
+ quantization_config = deepcopy(compression_config)
225
+ quantization_config.pop(SPARSITY_CONFIG_NAME, None)
226
+
227
+ # some fields are required, even if a qconfig is not present
228
+ # pop them off and if nothing remains, then there is no qconfig
229
+ quant_method = quantization_config.pop(QUANTIZATION_METHOD_NAME, None)
230
+ _ = quantization_config.pop(COMPRESSION_VERSION_NAME, None)
231
+
232
+ if len(quantization_config) == 0:
233
+ return None
234
+
235
+ # replace popped off values
236
+ # note that version is discarded for now
237
+ if quant_method is not None:
238
+ quantization_config[QUANTIZATION_METHOD_NAME] = quant_method
239
+
240
+ return quantization_config
241
+
242
+ def __init__(
243
+ self,
244
+ sparsity_config: Optional[SparsityCompressionConfig] = None,
245
+ quantization_config: Optional[QuantizationConfig] = None,
246
+ ):
247
+ self.sparsity_config = sparsity_config
248
+ self.quantization_config = quantization_config
249
+ self.sparsity_compressor = None
250
+ self.quantization_compressor = None
251
+
252
+ if sparsity_config is not None:
253
+ self.sparsity_compressor = BaseCompressor.load_from_registry(
254
+ sparsity_config.format, config=sparsity_config
255
+ )
256
+ if quantization_config is not None:
257
+ self.quantization_compressor = BaseCompressor.load_from_registry(
258
+ quantization_config.format, config=quantization_config
259
+ )
260
+
261
+ def get_missing_module_keys(self, model: Module) -> List[str]:
262
+ """
263
+ Identifies the expected missing weight keys in the compressed state_dict.
264
+
265
+ When a model undergoes sparsity or quantization compression, certain
266
+ weight tensors may be absent from the checkpoint by virtue of compression.
267
+ This function determines which weight keys are missing based on the
268
+ applied compression techniques.
269
+
270
+
271
+ :param model: The PyTorch model to check for missing keys.
272
+ :return: A list of missing keys expected in the compressed state_dict.
273
+ """
274
+ missing_keys = set()
275
+
276
+ # Determine missing keys due to sparsity compression
277
+ if (
278
+ self.sparsity_compressor
279
+ and self.sparsity_config.format != CompressionFormat.dense.value
280
+ ):
281
+ sparse_targets = expand_target_names(
282
+ model=model,
283
+ targets=self.sparsity_config.targets,
284
+ ignore=self.sparsity_config.ignore,
285
+ )
286
+ missing_keys.update(
287
+ merge_names(target, "weight") for target in sparse_targets
288
+ )
289
+
290
+ # Determine missing keys due to pack quantization
291
+ if (
292
+ self.quantization_compressor
293
+ and self.quantization_config.format
294
+ == CompressionFormat.pack_quantized.value
295
+ ):
296
+ for scheme in self.quantization_config.config_groups.values():
297
+ quant_targets = expand_target_names(
298
+ model=model,
299
+ targets=scheme.targets,
300
+ ignore=self.quantization_config.ignore,
301
+ )
302
+ missing_keys.update(
303
+ merge_names(target, "weight") for target in quant_targets
304
+ )
305
+
306
+ return list(missing_keys)
307
+
308
+ def get_unexpected_file_keys(self, model: Module) -> List[str]:
309
+ """
310
+ Identifies extra keys introduced by the compression process in the
311
+ compressed state_dict that are not expected by the model graph.
312
+
313
+ During sparsity or quantization compression, additional metadata or
314
+ auxiliary parameters may be stored in the checkpoint, which do not
315
+ correspond to any parameter in the original model. These keys are
316
+ typically introduced to support the reconstruction of compressed weights.
317
+
318
+ For example, Sparse24Bitmask compression may introduce keys such as
319
+ 'compressed', 'bitmask', and 'shape' in the checkpoint, which are
320
+ not part of the original model parameters.
321
+
322
+ :param model: The PyTorch model to check for unexpected keys.
323
+ :return: A list of extra keys introduced by the compression process
324
+ that are not expected by the model.
325
+ """
326
+
327
+ unexpected_keys = set()
328
+
329
+ # Identify unexpected keys from sparsity compression
330
+ if (
331
+ self.sparsity_compressor
332
+ and self.sparsity_config.format != CompressionFormat.dense.value
333
+ ):
334
+ sparse_targets: Set[str] = expand_target_names(
335
+ model=model,
336
+ targets=self.sparsity_config.targets,
337
+ ignore=self.sparsity_config.ignore,
338
+ )
339
+ unexpected_keys.update(
340
+ merge_names(target, param)
341
+ for target in sparse_targets
342
+ for param in self.sparsity_compressor.compression_param_names
343
+ )
344
+
345
+ # Identify unexpected keys from quantization compression
346
+ if self.quantization_compressor:
347
+ for scheme in self.quantization_config.config_groups.values():
348
+ quant_targets: Set[str] = expand_target_names(
349
+ model=model,
350
+ targets=scheme.targets,
351
+ ignore=self.quantization_config.ignore,
352
+ )
353
+ unexpected_keys.update(
354
+ merge_names(target, param)
355
+ for target in quant_targets
356
+ for param in self.quantization_compressor.compression_param_names
357
+ if param != "weight"
358
+ )
359
+
360
+ return list(unexpected_keys)
361
+
362
+ def compress(
363
+ self, model: Module, state_dict: Optional[Dict[str, Tensor]] = None
364
+ ) -> Dict[str, Tensor]:
365
+ """
366
+ Compresses a dense state dict or model with sparsity and/or quantization
367
+
368
+ :param model: uncompressed model to compress
369
+ :param state_dict: optional uncompressed state_dict to insert into model
370
+ :return: compressed state dict
371
+ """
372
+ if state_dict is None:
373
+ state_dict = model.state_dict()
374
+
375
+ compressed_state_dict = state_dict
376
+
377
+ quantized_modules_to_args: Dict[
378
+ str, QuantizationArgs
379
+ ] = map_modules_to_quant_args(model)
380
+
381
+ if self.quantization_compressor is not None:
382
+ compressed_state_dict = self.quantization_compressor.compress(
383
+ state_dict, names_to_scheme=quantized_modules_to_args
384
+ )
385
+ if self.quantization_config.format != CompressionFormat.dense.value:
386
+ self.quantization_config.quantization_status = (
387
+ QuantizationStatus.COMPRESSED
388
+ )
389
+
390
+ if self.sparsity_compressor is not None:
391
+ sparse_compression_targets: Set[str] = expand_target_names(
392
+ model=model,
393
+ targets=self.sparsity_config.targets,
394
+ ignore=self.sparsity_config.ignore,
395
+ )
396
+ compressed_state_dict = self.sparsity_compressor.compress(
397
+ compressed_state_dict,
398
+ compression_targets=sparse_compression_targets,
399
+ )
400
+
401
+ # HACK: Override the dtype_byte_size function in transformers to
402
+ # support float8 types. Fix is posted upstream
403
+ # https://github.com/huggingface/transformers/pull/30488
404
+ transformers.modeling_utils.dtype_byte_size = new_dtype_byte_size
405
+
406
+ return compressed_state_dict
407
+
408
+ def decompress(self, model_path: str, model: Module):
409
+ """
410
+ Overwrites the weights in model with weights decompressed from model_path
411
+
412
+ :param model_path: path to compressed weights
413
+ :param model: pytorch model to load decompressed weights into
414
+ """
415
+ model_path = get_safetensors_folder(model_path)
416
+ sparse_decompressed = False
417
+
418
+ if (
419
+ self.sparsity_compressor is not None
420
+ and self.sparsity_config.format != CompressionFormat.dense.value
421
+ ):
422
+ # Sparse decompression is applied on the model_path
423
+ dense_gen = self.sparsity_compressor.decompress(model_path)
424
+ self._replace_weights(dense_gen, model)
425
+ setattr(model, SPARSITY_CONFIG_NAME, self.sparsity_compressor.config)
426
+ sparse_decompressed = True
427
+
428
+ if self.quantization_compressor is not None:
429
+ # Temporarily set quantization status to FROZEN to prevent
430
+ # quantization during apply_quantization_config. This ensures
431
+ # that the dtypes of the weights are not unintentionally updated.
432
+ # The status is restored after quantization params are loaded.
433
+ with override_quantization_status(
434
+ self.quantization_config, QuantizationStatus.FROZEN
435
+ ):
436
+ names_to_scheme = apply_quantization_config(
437
+ model, self.quantization_config
438
+ )
439
+ load_pretrained_quantization(model, model_path)
440
+
441
+ model_path_or_state_dict = (
442
+ model.state_dict() if sparse_decompressed else model_path
443
+ )
444
+
445
+ dense_gen = self.quantization_compressor.decompress(
446
+ model_path_or_state_dict, names_to_scheme=names_to_scheme
447
+ )
448
+ self._replace_weights(dense_gen, model)
449
+
450
+ def freeze_quantization_status(module):
451
+ module.quantization_status = QuantizationStatus.FROZEN
452
+
453
+ model.apply(freeze_quantization_status)
454
+ setattr(model, QUANTIZATION_CONFIG_NAME, self.quantization_config)
455
+
456
+ def update_config(self, save_directory: str):
457
+ """
458
+ Update the model config located at save_directory with compression configs
459
+ for sparsity and/or quantization
460
+
461
+ :param save_directory: path to a folder containing a HF model config
462
+ """
463
+ if self.quantization_config is None and self.sparsity_config is None:
464
+ return
465
+
466
+ config_file_path = os.path.join(save_directory, CONFIG_NAME)
467
+ if not os.path.exists(config_file_path):
468
+ _LOGGER.warning(
469
+ f"Could not find a valid model config file in "
470
+ f"{save_directory}. Compression config will not be saved."
471
+ )
472
+ return
473
+
474
+ with open(config_file_path, "r") as config_file:
475
+ config_data = json.load(config_file)
476
+
477
+ # required metadata whenever a quantization or sparsity config is present
478
+ # overwrite previous config and version if already existing
479
+ config_data[QUANTIZATION_CONFIG_NAME] = {}
480
+ config_data[QUANTIZATION_CONFIG_NAME][
481
+ COMPRESSION_VERSION_NAME
482
+ ] = compressed_tensors.__version__
483
+ if self.quantization_config is not None:
484
+ self.quantization_config.quant_method = DEFAULT_QUANTIZATION_METHOD
485
+ else:
486
+ config_data[QUANTIZATION_CONFIG_NAME][
487
+ QUANTIZATION_METHOD_NAME
488
+ ] = DEFAULT_QUANTIZATION_METHOD
489
+
490
+ # quantization and sparsity configs
491
+ if self.quantization_config is not None:
492
+ quant_config_data = self.quantization_config.model_dump()
493
+ config_data[QUANTIZATION_CONFIG_NAME] = quant_config_data
494
+ if self.sparsity_config is not None:
495
+ sparsity_config_data = self.sparsity_config.model_dump()
496
+ config_data[QUANTIZATION_CONFIG_NAME][
497
+ SPARSITY_CONFIG_NAME
498
+ ] = sparsity_config_data
499
+
500
+ with open(config_file_path, "w") as config_file:
501
+ json.dump(config_data, config_file, indent=2, sort_keys=True)
502
+
503
+ def _replace_weights(self, dense_weight_generator, model: Module):
504
+ """
505
+ Replace the weights of the model with the
506
+ provided dense weights.
507
+
508
+ This method iterates over the dense_weight_generator and
509
+ updates the corresponding weights in the model. If a parameter
510
+ name does not exist in the model, it will be skipped.
511
+
512
+ :param dense_weight_generator (generator): A generator that yields
513
+ tuples of (name, data), where 'name' is the parameter name and
514
+ 'data' is the updated param data
515
+ :param model: The model whose weights are to be updated.
516
+ """
517
+ for name, data in tqdm(dense_weight_generator, desc="Decompressing model"):
518
+ split_name = name.split(".")
519
+ prefix, param_name = ".".join(split_name[:-1]), split_name[-1]
520
+ module = operator.attrgetter(prefix)(model)
521
+ if hasattr(module, param_name):
522
+ update_parameter_data(module, data, param_name)
523
+
524
+
525
+ def map_modules_to_quant_args(
526
+ model: Module,
527
+ ) -> Dict[str, Union[QuantizationArgs, Tuple[QuantizationArgs, QuantizationArgs]]]:
528
+ """
529
+ Given a pytorch model, map out the submodule name (usually linear layers)
530
+ to the weight QuantizationArgs. If running input activation quantization, will also
531
+ map to the input QuantizationArgs in a tuple.
532
+
533
+ :param model: pytorch model
534
+ """
535
+ quantized_modules_to_args = {}
536
+ for name, submodule in iter_named_leaf_modules(model):
537
+ if is_module_quantized(submodule):
538
+ if submodule.quantization_scheme.weights is not None:
539
+ name = fix_fsdp_module_name(name)
540
+ quantized_modules_to_args[name] = submodule.quantization_scheme.weights
541
+ if submodule.quantization_scheme.input_activations is not None:
542
+ weight_args = quantized_modules_to_args.get(name)
543
+ quantized_modules_to_args[name] = (
544
+ weight_args,
545
+ submodule.quantization_scheme.input_activations,
546
+ )
547
+
548
+ return quantized_modules_to_args
549
+
550
+
551
+ # HACK: Override the dtype_byte_size function in transformers to support float8 types
552
+ # Fix is posted upstream https://github.com/huggingface/transformers/pull/30488
553
+ def new_dtype_byte_size(dtype):
554
+ if dtype == torch.bool:
555
+ return 1 / 8
556
+ bit_search = re.search(r"[^\d](\d+)_?", str(dtype))
557
+ if bit_search is None:
558
+ raise ValueError(f"`dtype` is not a valid dtype: {dtype}.")
559
+ bit_size = int(bit_search.groups()[0])
560
+ return bit_size // 8
561
+
562
+
563
+ @contextmanager
564
+ def override_quantization_status(
565
+ config: QuantizationConfig, status: QuantizationStatus
566
+ ):
567
+ """
568
+ Within this context, the quantization status will be set to the
569
+ supplied status. After the context exits, the original status
570
+ will be restored.
571
+
572
+ :param config: the quantization config to override
573
+ :param status: the status to temporarily set
574
+ """
575
+ original_status = config.quantization_status
576
+ config.quantization_status = status
577
+ try:
578
+ yield
579
+ finally:
580
+ config.quantization_status = original_status
lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/__init__.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # flake8: noqa
15
+
16
+ from .base import *
17
+ from .naive_quantized import *
18
+ from .pack_quantized import *
lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (318 Bytes). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/__pycache__/base.cpython-312.pyc ADDED
Binary file (8.23 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/__pycache__/naive_quantized.cpython-312.pyc ADDED
Binary file (5.67 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/__pycache__/pack_quantized.cpython-312.pyc ADDED
Binary file (9.94 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/base.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import logging
16
+ from pathlib import Path
17
+ from typing import Any, Dict, Generator, Tuple, Union
18
+
19
+ import torch
20
+ from compressed_tensors.compressors.base import BaseCompressor
21
+ from compressed_tensors.quantization import QuantizationArgs
22
+ from compressed_tensors.utils import (
23
+ get_nested_mappings_from_state_dict,
24
+ get_nested_weight_mappings,
25
+ merge_names,
26
+ )
27
+ from safetensors import safe_open
28
+ from torch import Tensor
29
+ from tqdm import tqdm
30
+
31
+
32
+ _LOGGER: logging.Logger = logging.getLogger(__name__)
33
+
34
+ __all__ = ["BaseQuantizationCompressor"]
35
+
36
+
37
+ class BaseQuantizationCompressor(BaseCompressor):
38
+ """
39
+ Base class representing a quant compression algorithm. Each child class should
40
+ implement compression_param_info, compress_weight and decompress_weight.
41
+
42
+ Compressors support compressing/decompressing a full module state dict or a single
43
+ quantized PyTorch leaf module.
44
+
45
+ Model Load Lifecycle (run_compressed=False):
46
+ - ModelCompressor.decompress()
47
+ - apply_quantization_config()
48
+ - BaseQuantizationCompressor.decompress()
49
+ - BaseQuantizationCompressor.decompress_weight()
50
+
51
+ Model Save Lifecycle:
52
+ - ModelCompressor.compress()
53
+ - BaseQuantizationCompressor.compress()
54
+ - BaseQuantizationCompressor.compress_weight()
55
+
56
+ Module Lifecycle (run_compressed=True):
57
+ - apply_quantization_config()
58
+ - compressed_module = CompressedLinear(module)
59
+ - initialize_module_for_quantization()
60
+ - BaseQuantizationCompressor.compression_param_info()
61
+ - register_parameters()
62
+ - compressed_module.forward()
63
+ - compressed_module.decompress()
64
+
65
+
66
+ :param config: config specifying compression parameters
67
+ """
68
+
69
+ def compress(
70
+ self,
71
+ model_state: Dict[str, Tensor],
72
+ names_to_scheme: Dict[str, QuantizationArgs],
73
+ **kwargs,
74
+ ) -> Dict[str, Tensor]:
75
+ """
76
+ Compresses a dense state dict
77
+
78
+ :param model_state: state dict of uncompressed model
79
+ :param names_to_scheme: quantization args for each quantized weight, needed for
80
+ quantize function to calculate bit depth
81
+ :return: compressed state dict
82
+ """
83
+ compressed_dict = {}
84
+ weight_suffix = ".weight"
85
+ input_zp_suffix = ".input_zero_point"
86
+ weight_zp_suffix = ".weight_zero_point"
87
+ _LOGGER.debug(
88
+ f"Compressing model with {len(model_state)} parameterized layers..."
89
+ )
90
+
91
+ for name, value in tqdm(model_state.items(), desc="Quantized Compression"):
92
+ # check if the parameter we're compressing is the weight zp
93
+ # or the input zp
94
+ is_weight_zp = name.endswith(weight_zp_suffix)
95
+ is_input_zp = name.endswith(input_zp_suffix)
96
+
97
+ # if we're saving the weight zp, fetch weight quant args
98
+ if is_weight_zp:
99
+ quant_args_zp = names_to_scheme.get(name[: -(len(weight_zp_suffix))])
100
+ if isinstance(quant_args_zp, tuple):
101
+ # If tuple, first value is weight args, second is input args
102
+ quant_args_zp = quant_args_zp[0]
103
+
104
+ # if we're saving the input zp, fetch input quant args
105
+ if is_input_zp:
106
+ input_args_zp = names_to_scheme.get(name[: -(len(input_zp_suffix))])
107
+ if isinstance(input_args_zp, tuple):
108
+ # If tuple, first value is weight args, second is input args
109
+ input_args_zp = input_args_zp[-1]
110
+
111
+ if name.endswith(weight_suffix):
112
+ prefix = name[: -(len(weight_suffix))]
113
+ scale = model_state.get(merge_names(prefix, "weight_scale"), None)
114
+ zp = model_state.get(merge_names(prefix, "weight_zero_point"), None)
115
+ g_idx = model_state.get(merge_names(prefix, "weight_g_idx"), None)
116
+ if scale is not None:
117
+ # weight is quantized, compress it
118
+ if isinstance(names_to_scheme[prefix], tuple):
119
+ quant_args = names_to_scheme[prefix][0]
120
+ else:
121
+ quant_args = names_to_scheme[prefix]
122
+
123
+ compressed_data = self.compress_weight(
124
+ weight=value,
125
+ scale=scale,
126
+ zero_point=zp,
127
+ g_idx=g_idx,
128
+ quantization_args=quant_args,
129
+ device="cpu",
130
+ )
131
+ for key, value in compressed_data.items():
132
+ compressed_dict[merge_names(prefix, key)] = value
133
+ else:
134
+ compressed_dict[name] = value.to("cpu")
135
+ # only save if asym
136
+ elif is_weight_zp and quant_args_zp.symmetric:
137
+ continue
138
+ # only save if asym
139
+ elif is_input_zp and input_args_zp.symmetric:
140
+ continue
141
+ elif name.endswith("g_idx") and torch.any(value <= -1):
142
+ continue
143
+ else:
144
+ compressed_dict[name] = value.to("cpu")
145
+
146
+ return compressed_dict
147
+
148
+ def decompress(
149
+ self,
150
+ path_to_model_or_tensors: Union[str, Path, Dict[str, Any]],
151
+ names_to_scheme: Dict[str, QuantizationArgs],
152
+ device: str = "cpu",
153
+ ) -> Generator[Tuple[str, Tensor], None, None]:
154
+ """
155
+ Reads a compressed state dict located at path_to_model_or_tensors
156
+ and returns a generator for sequentially decompressing back to a
157
+ dense state dict
158
+ :param path_to_model_or_tensors: path to compressed safetensors model (directory
159
+ with one or more safetensors files) or compressed tensors file
160
+ :param names_to_scheme: quantization args for each quantized weight
161
+ :param device: optional device to load intermediate weights into
162
+ :return: compressed state dict
163
+ """
164
+ if isinstance(path_to_model_or_tensors, (str, Path)):
165
+ yield from self._decompress_from_path(
166
+ path_to_model_or_tensors, names_to_scheme, device
167
+ )
168
+
169
+ else:
170
+ yield from self._decompress_from_state_dict(
171
+ path_to_model_or_tensors, names_to_scheme
172
+ )
173
+
174
+ def _decompress_from_path(self, path_to_model, names_to_scheme, device):
175
+ weight_mappings = get_nested_weight_mappings(
176
+ path_to_model, self.compression_param_names
177
+ )
178
+ for weight_name in weight_mappings.keys():
179
+ weight_data = {}
180
+ for param_name, safe_path in weight_mappings[weight_name].items():
181
+ full_name = merge_names(weight_name, param_name)
182
+ with safe_open(safe_path, framework="pt", device=device) as f:
183
+ weight_data[param_name] = f.get_tensor(full_name)
184
+ if "weight_scale" in weight_data:
185
+ quant_args = names_to_scheme[weight_name]
186
+ decompressed = self.decompress_weight(
187
+ compressed_data=weight_data, quantization_args=quant_args
188
+ )
189
+ yield merge_names(weight_name, "weight"), decompressed
190
+
191
+ def _decompress_from_state_dict(self, state_dict, names_to_scheme):
192
+ weight_mappings = get_nested_mappings_from_state_dict(
193
+ state_dict, self.compression_param_names
194
+ )
195
+ for weight_name in weight_mappings.keys():
196
+ weight_data = {}
197
+ for param_name, param_value in weight_mappings[weight_name].items():
198
+ weight_data[param_name] = param_value
199
+
200
+ if "weight_scale" in weight_data:
201
+ quant_args = names_to_scheme[weight_name]
202
+ decompressed = self.decompress_weight(
203
+ compressed_data=weight_data, quantization_args=quant_args
204
+ )
205
+ yield merge_names(weight_name, "weight"), decompressed
lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/naive_quantized.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Dict, Optional, Tuple
16
+
17
+ import torch
18
+ from compressed_tensors.compressors.base import BaseCompressor
19
+ from compressed_tensors.compressors.quantized_compressors.base import (
20
+ BaseQuantizationCompressor,
21
+ )
22
+ from compressed_tensors.config import CompressionFormat
23
+ from compressed_tensors.quantization import QuantizationArgs
24
+ from compressed_tensors.quantization.lifecycle.forward import dequantize, quantize
25
+ from compressed_tensors.quantization.utils import can_quantize
26
+ from torch import Tensor
27
+
28
+
29
+ __all__ = [
30
+ "NaiveQuantizationCompressor",
31
+ "IntQuantizationCompressor",
32
+ "FloatQuantizationCompressor",
33
+ ]
34
+
35
+
36
+ @BaseCompressor.register(name=CompressionFormat.naive_quantized.value)
37
+ class NaiveQuantizationCompressor(BaseQuantizationCompressor):
38
+ """
39
+ Implements naive compression for quantized models. Weight of each
40
+ quantized layer is converted from its original float type to the closest Pytorch
41
+ type to the type specified by the layer's QuantizationArgs.
42
+ """
43
+
44
+ @property
45
+ def compression_param_names(self) -> Tuple[str]:
46
+ """
47
+ Returns a tuple of compression parameter names introduced by
48
+ the compressor during compression
49
+ """
50
+ return (
51
+ "weight",
52
+ "weight_scale",
53
+ "weight_zero_point",
54
+ "weight_g_idx",
55
+ )
56
+
57
+ def compression_param_info(
58
+ self,
59
+ weight_shape: torch.Size,
60
+ quantization_args: Optional[QuantizationArgs] = None,
61
+ ) -> Dict[str, Tuple[torch.Size, torch.dtype]]:
62
+ """
63
+ Creates a dictionary of expected shapes and dtypes for each compression
64
+ parameter used by the compressor
65
+
66
+ :param weight_shape: uncompressed weight shape
67
+ :param quantization_args: quantization parameters for the weight
68
+ :return: dictionary mapping compressed parameter names to shape and dtype
69
+ """
70
+ dtype = quantization_args.pytorch_dtype()
71
+ return {"weight": (weight_shape, dtype)}
72
+
73
+ def compress_weight(
74
+ self,
75
+ weight: Tensor,
76
+ scale: Tensor,
77
+ quantization_args: QuantizationArgs,
78
+ zero_point: Optional[Tensor] = None,
79
+ g_idx: Optional[torch.Tensor] = None,
80
+ device: Optional[torch.device] = None,
81
+ ) -> Dict[str, torch.Tensor]:
82
+ """
83
+ Compresses a single uncompressed weight
84
+
85
+ :param weight: uncompressed weight tensor
86
+ :param scale: quantization scale for weight
87
+ :param quantization_args: quantization parameters for weight
88
+ :param zero_point: quantization zero point for weight
89
+ :param g_idx: optional mapping from column index to group index
90
+ :param device: optional device to move compressed output to
91
+ :return: dictionary of compressed weight data
92
+ """
93
+ if can_quantize(weight, quantization_args):
94
+ quantized_weight = quantize(
95
+ x=weight,
96
+ scale=scale,
97
+ zero_point=zero_point,
98
+ g_idx=g_idx,
99
+ args=quantization_args,
100
+ dtype=quantization_args.pytorch_dtype(),
101
+ )
102
+ else:
103
+ quantized_weight = weight
104
+
105
+ if device is not None:
106
+ quantized_weight = quantized_weight.to(device)
107
+
108
+ return {"weight": quantized_weight}
109
+
110
+ def decompress_weight(
111
+ self,
112
+ compressed_data: Dict[str, Tensor],
113
+ quantization_args: Optional[QuantizationArgs] = None,
114
+ ) -> torch.Tensor:
115
+ """
116
+ Decompresses a single compressed weight
117
+
118
+ :param compressed_data: dictionary of data needed for decompression
119
+ :param quantization_args: quantization parameters for the weight
120
+ :return: tensor of the decompressed weight
121
+ """
122
+ weight = compressed_data["weight"]
123
+ scale = compressed_data["weight_scale"]
124
+ zero_point = compressed_data.get("weight_zero_point", None)
125
+ g_idx = compressed_data.get("weight_g_idx", None)
126
+ decompressed_weight = dequantize(
127
+ x_q=weight, scale=scale, zero_point=zero_point, g_idx=g_idx
128
+ )
129
+
130
+ return decompressed_weight
131
+
132
+
133
+ @BaseCompressor.register(name=CompressionFormat.int_quantized.value)
134
+ class IntQuantizationCompressor(NaiveQuantizationCompressor):
135
+ """
136
+ Alias for integer quantized models
137
+ """
138
+
139
+ pass
140
+
141
+
142
+ @BaseCompressor.register(name=CompressionFormat.float_quantized.value)
143
+ class FloatQuantizationCompressor(NaiveQuantizationCompressor):
144
+ """
145
+ Alias for fp quantized models
146
+ """
147
+
148
+ pass
lib/python3.12/site-packages/compressed_tensors/compressors/quantized_compressors/pack_quantized.py ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ import math
15
+ from typing import Dict, Optional, Tuple
16
+
17
+ import numpy as np
18
+ import torch
19
+ from compressed_tensors.compressors.base import BaseCompressor
20
+ from compressed_tensors.compressors.quantized_compressors.base import (
21
+ BaseQuantizationCompressor,
22
+ )
23
+ from compressed_tensors.config import CompressionFormat
24
+ from compressed_tensors.quantization import QuantizationArgs
25
+ from compressed_tensors.quantization.lifecycle.forward import dequantize, quantize
26
+ from compressed_tensors.quantization.utils import can_quantize
27
+ from torch import Tensor
28
+
29
+
30
+ __all__ = ["PackedQuantizationCompressor", "pack_to_int32", "unpack_from_int32"]
31
+
32
+
33
+ @BaseCompressor.register(name=CompressionFormat.pack_quantized.value)
34
+ class PackedQuantizationCompressor(BaseQuantizationCompressor):
35
+ """
36
+ Compresses a quantized model by packing every eight 4-bit weights into an int32
37
+ """
38
+
39
+ @property
40
+ def compression_param_names(self) -> Tuple[str]:
41
+ """
42
+ Returns a tuple of compression parameter names introduced by
43
+ the compressor during compression
44
+ """
45
+ return (
46
+ "weight_packed",
47
+ "weight_scale",
48
+ "weight_zero_point",
49
+ "weight_g_idx",
50
+ "weight_shape",
51
+ )
52
+
53
+ def compression_param_info(
54
+ self,
55
+ weight_shape: torch.Size,
56
+ quantization_args: Optional[QuantizationArgs] = None,
57
+ ) -> Dict[str, Tuple[torch.Size, torch.dtype]]:
58
+ """
59
+ Creates a dictionary of expected shapes and dtypes for each compression
60
+ parameter used by the compressor
61
+
62
+ :param weight_shape: uncompressed weight shape
63
+ :param quantization_args: quantization parameters for the weight
64
+ :return: dictionary mapping compressed parameter names to shape and dtype
65
+ """
66
+ pack_factor = 32 // quantization_args.num_bits
67
+ packed_size = math.ceil(weight_shape[1] / pack_factor)
68
+ return {
69
+ "weight_packed": (torch.Size((weight_shape[0], packed_size)), torch.int32),
70
+ "weight_shape": (torch.Size((2,)), torch.int32),
71
+ }
72
+
73
+ def compress_weight(
74
+ self,
75
+ weight: Tensor,
76
+ scale: Tensor,
77
+ quantization_args: QuantizationArgs,
78
+ zero_point: Optional[Tensor] = None,
79
+ g_idx: Optional[torch.Tensor] = None,
80
+ device: Optional[torch.device] = None,
81
+ ) -> Dict[str, torch.Tensor]:
82
+ """
83
+ Compresses a single uncompressed weight
84
+
85
+ :param weight: uncompressed weight tensor
86
+ :param scale: quantization scale for weight
87
+ :param quantization_args: quantization parameters for weight
88
+ :param zero_point: quantization zero point for weight
89
+ :param g_idx: optional mapping from column index to group index
90
+ :param device: optional device to move compressed output to
91
+ :return: dictionary of compressed weight data
92
+ """
93
+ compressed_dict = {}
94
+ if can_quantize(weight, quantization_args):
95
+ quantized_weight = quantize(
96
+ x=weight,
97
+ scale=scale,
98
+ zero_point=zero_point,
99
+ g_idx=g_idx,
100
+ args=quantization_args,
101
+ dtype=torch.int8,
102
+ )
103
+ else:
104
+ quantized_weight = weight
105
+
106
+ packed_weight = pack_to_int32(quantized_weight, quantization_args.num_bits)
107
+ weight_shape = torch.tensor(weight.shape)
108
+ if device is not None:
109
+ packed_weight = packed_weight.to(device)
110
+ weight_shape = weight_shape.to(device)
111
+
112
+ compressed_dict["weight_shape"] = weight_shape
113
+ compressed_dict["weight_packed"] = packed_weight
114
+
115
+ return compressed_dict
116
+
117
+ def decompress_weight(
118
+ self,
119
+ compressed_data: Dict[str, Tensor],
120
+ quantization_args: Optional[QuantizationArgs] = None,
121
+ ) -> torch.Tensor:
122
+ """
123
+ Decompresses a single compressed weight
124
+
125
+ :param compressed_data: dictionary of data needed for decompression
126
+ :param quantization_args: quantization parameters for the weight
127
+ :return: tensor of the decompressed weight
128
+ """
129
+ weight = compressed_data["weight_packed"]
130
+ scale = compressed_data["weight_scale"]
131
+ zero_point = compressed_data.get("weight_zero_point", None)
132
+ g_idx = compressed_data.get("weight_g_idx", None)
133
+ original_shape = torch.Size(compressed_data["weight_shape"])
134
+ num_bits = quantization_args.num_bits
135
+ unpacked = unpack_from_int32(weight, num_bits, original_shape)
136
+ decompressed_weight = dequantize(
137
+ x_q=unpacked, scale=scale, zero_point=zero_point, g_idx=g_idx
138
+ )
139
+
140
+ return decompressed_weight
141
+
142
+
143
+ def pack_to_int32(value: torch.Tensor, num_bits: int) -> torch.Tensor:
144
+ """
145
+ Packs a tensor of quantized weights stored in int8 into int32s with padding
146
+
147
+ Pseudocode:
148
+ 1. Shift wrt num_bits to convert to unsigned. num_bits=8
149
+ [1,2] -> [129, 130]
150
+ 2. Pad to fill in 32 bits
151
+ [129, 130] -> [129, 130, 0, 0]
152
+ 3. convert to binary align in order
153
+ [129, 130, 0, 0] -> 00000000 00000000 10000010 10000001
154
+ 4. convert aligned binary to number
155
+ 00000000000000001000001010000001 -> 33409
156
+ 5. covert back to uint32
157
+ 33409 -> 33409
158
+
159
+ :param value: tensor to pack
160
+ :param num_bits: number of bits used to store underlying data, must be at least 1
161
+ :returns: packed int32 tensor
162
+ """
163
+ if value.dtype is not torch.int8:
164
+ raise ValueError("Tensor must be quantized to torch.int8 before packing")
165
+
166
+ if num_bits > 8:
167
+ raise ValueError("Packing is only supported for less than 8 bits")
168
+
169
+ if num_bits < 1:
170
+ raise ValueError(f"num_bits must be at least 1, got {num_bits}")
171
+
172
+ # convert to unsigned for packing
173
+ offset = 1 << (num_bits - 1)
174
+ value = (value + offset).to(torch.uint8)
175
+ value = value.cpu().numpy().astype(np.uint32)
176
+ pack_factor = 32 // num_bits
177
+
178
+ # pad input tensor and initialize packed output
179
+ packed_size = math.ceil(value.shape[1] / pack_factor)
180
+ padding = packed_size * pack_factor - value.shape[1]
181
+ value = np.pad(value, pad_width=[(0, 0), (0, padding)], constant_values=0)
182
+
183
+ # pack values
184
+ packed = np.zeros((value.shape[0], packed_size), dtype=np.uint32)
185
+ for i in range(pack_factor):
186
+ packed |= value[:, i::pack_factor] << num_bits * i
187
+
188
+ # convert back to signed and torch
189
+ packed = np.ascontiguousarray(packed).view(np.int32)
190
+ return torch.from_numpy(packed)
191
+
192
+
193
+ def unpack_from_int32(
194
+ value: torch.Tensor, num_bits: int, shape: torch.Size
195
+ ) -> torch.Tensor:
196
+ """
197
+ Unpacks a tensor of packed int32 weights into individual int8s, maintaining the
198
+ original bit range.
199
+
200
+ Return tensors in int8
201
+
202
+ :param value: tensor to upack
203
+ :param num_bits: number of bits to unpack each data point into
204
+ :param shape: shape to unpack into, used to remove padding
205
+ :returns: unpacked int8 tensor
206
+ """
207
+ if value.dtype is not torch.int32:
208
+ raise ValueError(
209
+ f"Expected {torch.int32} but got {value.dtype}, Aborting unpack."
210
+ )
211
+
212
+ if num_bits > 8:
213
+ raise ValueError("Unpacking is only supported for less than 8 bits")
214
+
215
+ pack_factor = 32 // num_bits
216
+
217
+ # unpack
218
+ mask = (1 << num_bits) - 1
219
+ unpacked = torch.zeros(
220
+ (value.shape[0], value.shape[1] * pack_factor),
221
+ device=value.device,
222
+ dtype=torch.int32,
223
+ )
224
+ for i in range(pack_factor):
225
+ unpacked[:, i::pack_factor] = (value >> (num_bits * i)) & mask
226
+
227
+ # remove padding
228
+ original_row_size = int(shape[1])
229
+ unpacked = unpacked[:, :original_row_size]
230
+
231
+ # bits are packed in unsigned format, reformat to signed
232
+ # update the value range from unsigned to signed
233
+ offset = pow(2, num_bits) // 2
234
+ unpacked = (unpacked - offset).to(torch.int8)
235
+
236
+ return unpacked
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/__init__.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # flake8: noqa
15
+
16
+ from .base import *
17
+ from .dense import *
18
+ from .sparse_24_bitmask import *
19
+ from .sparse_bitmask import *
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (337 Bytes). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/__pycache__/base.cpython-312.pyc ADDED
Binary file (6.52 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/__pycache__/dense.cpython-312.pyc ADDED
Binary file (1.83 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/__pycache__/sparse_24_bitmask.cpython-312.pyc ADDED
Binary file (11.3 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/__pycache__/sparse_bitmask.cpython-312.pyc ADDED
Binary file (7.63 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/base.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import logging
16
+ from typing import Dict, Generator, Optional, Set, Tuple
17
+
18
+ from compressed_tensors.compressors.base import BaseCompressor
19
+ from compressed_tensors.utils import get_nested_weight_mappings, merge_names
20
+ from safetensors import safe_open
21
+ from torch import Tensor
22
+ from tqdm import tqdm
23
+
24
+
25
+ __all__ = ["BaseSparseCompressor"]
26
+
27
+ _LOGGER: logging.Logger = logging.getLogger(__name__)
28
+
29
+
30
+ class BaseSparseCompressor(BaseCompressor):
31
+ """
32
+ Base class representing a sparse compression algorithm. Each child class should
33
+ implement compression_param_names, compress_weight and decompress_weight;
34
+
35
+ Compressors support compressing/decompressing a full module state dict or a single
36
+ quantized PyTorch leaf module.
37
+
38
+ Model Load Lifecycle (run_compressed=False):
39
+ - ModelCompressor.decompress()
40
+ - apply_quantization_config()
41
+ - BaseSparseCompressor.decompress()
42
+ - BaseSparseCompressor.decompress_weight()
43
+
44
+ Model Save Lifecycle:
45
+ - ModelCompressor.compress()
46
+ - BaseSparseCompressor.compress()
47
+ - BaseSparseCompressor.compress_weight()
48
+
49
+ Module Lifecycle (run_compressed=True):
50
+ - apply_quantization_config()
51
+ - compressed_module = CompressedLinear(module)
52
+ - initialize_module_for_quantization()
53
+ - BaseSparseCompressor.compression_param_info()
54
+ - register_parameters()
55
+ - compressed_module.forward()
56
+ - compressed_module.decompress()
57
+
58
+
59
+ :param config: config specifying compression parameters
60
+ """
61
+
62
+ def compress(
63
+ self,
64
+ model_state: Dict[str, Tensor],
65
+ compression_targets: Optional[Set[str]] = None,
66
+ ) -> Dict[str, Tensor]:
67
+ """
68
+ Compresses a dense state dict using bitmask compression
69
+
70
+ :param model_state: state dict of uncompressed model
71
+ :param compression_targets: optional set of layer prefixes to compress,
72
+ otherwise compress all layers (for backwards compatibility)
73
+ :return: compressed state dict
74
+ """
75
+ compressed_dict = {}
76
+ _LOGGER.debug(
77
+ f"Compressing model with {len(model_state)} parameterized layers..."
78
+ )
79
+ for name, value in tqdm(model_state.items(), desc="Compressing model"):
80
+ if not self.should_compress(name, compression_targets):
81
+ compressed_dict[name] = value
82
+ continue
83
+ prefix = name
84
+ if prefix.endswith(".weight"):
85
+ prefix = prefix[: -(len(".weight"))]
86
+
87
+ compression_data = self.compress_weight(prefix, value)
88
+ for key in compression_data.keys():
89
+ if key in compressed_dict:
90
+ _LOGGER.warn(
91
+ f"Expected all compressed state_dict keys to be unique, but "
92
+ f"found an existing entry for {key}. The existing entry will "
93
+ "be replaced."
94
+ )
95
+
96
+ compressed_dict.update(compression_data)
97
+
98
+ return compressed_dict
99
+
100
+ def decompress(
101
+ self, path_to_model_or_tensors: str, device: str = "cpu", **kwargs
102
+ ) -> Generator[Tuple[str, Tensor], None, None]:
103
+ """
104
+ Reads a bitmask compressed state dict located
105
+ at path_to_model_or_tensors and returns a generator
106
+ for sequentially decompressing back to a dense state dict
107
+
108
+ :param model_path: path to compressed safetensors model (directory with
109
+ one or more safetensors files) or compressed tensors file
110
+ :param device: device to load decompressed weights onto
111
+ :return: iterator for generating decompressed weights
112
+ """
113
+ weight_mappings, ignored_params = get_nested_weight_mappings(
114
+ path_to_model_or_tensors,
115
+ self.compression_param_names,
116
+ return_unmatched_params=True,
117
+ )
118
+ for weight_name in weight_mappings.keys():
119
+ weight_data = {}
120
+ for param_name, safe_path in weight_mappings[weight_name].items():
121
+ full_name = merge_names(weight_name, param_name)
122
+ with safe_open(safe_path, framework="pt", device=device) as f:
123
+ weight_data[param_name] = f.get_tensor(full_name)
124
+ decompressed = self.decompress_weight(weight_data)
125
+ yield merge_names(weight_name, "weight"), decompressed
126
+
127
+ for ignored_param_name, safe_path in ignored_params.items():
128
+ with safe_open(safe_path, framework="pt", device=device) as f:
129
+ value = f.get_tensor(ignored_param_name)
130
+ yield ignored_param_name, value
131
+
132
+ @staticmethod
133
+ def should_compress(name: str, expanded_targets: Optional[Set[str]] = None) -> bool:
134
+ """
135
+ Check if a parameter should be compressed.
136
+ Currently, this only returns True for weight parameters.
137
+
138
+ :param name: name of the parameter
139
+ :param expanded_targets: set of layer prefixes to compress
140
+ :return: whether or not the parameter should be compressed
141
+ """
142
+ if expanded_targets is None:
143
+ return name.endswith(".weight")
144
+
145
+ return (
146
+ name.endswith(".weight") and name[: -(len(".weight"))] in expanded_targets
147
+ )
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/dense.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Dict, Generator, Tuple
16
+
17
+ from compressed_tensors.compressors.base import BaseCompressor
18
+ from compressed_tensors.config import CompressionFormat
19
+ from torch import Tensor
20
+
21
+
22
+ @BaseCompressor.register(name=CompressionFormat.dense.value)
23
+ class DenseCompressor(BaseCompressor):
24
+ """
25
+ Identity compressor for dense models, returns the original state_dict
26
+ """
27
+
28
+ @property
29
+ def compression_param_names(self) -> Tuple[str]:
30
+ """
31
+ Returns a tuple of compression parameter names introduced by
32
+ the compressor during compression
33
+ """
34
+ return ()
35
+
36
+ def compress(self, model_state: Dict[str, Tensor], **kwargs) -> Dict[str, Tensor]:
37
+ return model_state
38
+
39
+ def decompress(
40
+ self, path_to_model_or_tensors: str, device: str = "cpu", **kwargs
41
+ ) -> Generator[Tuple[str, Tensor], None, None]:
42
+ return iter([])
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/sparse_24_bitmask.py ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from dataclasses import dataclass
16
+ from typing import Dict, List, Tuple, Union
17
+
18
+ import torch
19
+ from compressed_tensors.compressors.base import BaseCompressor
20
+ from compressed_tensors.compressors.sparse_compressors.base import BaseSparseCompressor
21
+ from compressed_tensors.config import CompressionFormat, SparsityStructure
22
+ from compressed_tensors.quantization import FP8_DTYPE
23
+ from compressed_tensors.utils import merge_names, pack_bitmasks, unpack_bitmasks
24
+ from torch import Tensor
25
+
26
+
27
+ __all__ = [
28
+ "Sparse24BitMaskCompressor",
29
+ "Sparse24BitMaskTensor",
30
+ "sparse24_bitmask_compress",
31
+ "sparse24_bitmask_decompress",
32
+ "get_24_bytemasks",
33
+ ]
34
+
35
+
36
+ @BaseCompressor.register(name=CompressionFormat.sparse_24_bitmask.value)
37
+ class Sparse24BitMaskCompressor(BaseSparseCompressor):
38
+ """
39
+ Compression for sparse models using bitmasks. Non-zero weights are stored in a 2d
40
+ values tensor, with their locations stored in a 2d bitmask
41
+ """
42
+
43
+ @property
44
+ def compression_param_names(self) -> Tuple[str]:
45
+ """
46
+ Returns a tuple of compression parameter names introduced by
47
+ the compressor during compression
48
+ """
49
+ return (
50
+ "shape",
51
+ "compressed",
52
+ "bitmask",
53
+ )
54
+
55
+ def compress_weight(self, name, value):
56
+ bitmask_tensor = Sparse24BitMaskTensor.from_dense(
57
+ value, self.config.sparsity_structure
58
+ )
59
+ bitmask_dict = bitmask_tensor.dict(name_prefix=name, device="cpu")
60
+ return bitmask_dict
61
+
62
+ def decompress_weight(self, weight_data):
63
+ data = Sparse24BitMaskTensor.from_compressed_data(**weight_data)
64
+ decompressed = data.decompress()
65
+ return decompressed
66
+
67
+
68
+ @dataclass
69
+ class Sparse24BitMaskTensor:
70
+ """
71
+ Owns compressions and decompression for a single 2:4 sparse
72
+ bitmask compressed tensor.
73
+
74
+ :param shape: shape of dense tensor
75
+ :param compressed: 2d tensor of non-zero values
76
+ :param bitmask: 2d bitmask of non-zero values
77
+ """
78
+
79
+ shape: List[int]
80
+ compressed: Tensor
81
+ bitmask: Tensor
82
+
83
+ @staticmethod
84
+ def from_dense(
85
+ tensor: Tensor,
86
+ sparsity_structure: Union[SparsityStructure, str] = SparsityStructure.TWO_FOUR,
87
+ ) -> "Sparse24BitMaskTensor":
88
+ """
89
+ :param tensor: dense tensor to compress
90
+ :return: instantiated compressed tensor
91
+ """
92
+ shape = list(tensor.shape)
93
+ compressed, bitmask = sparse24_bitmask_compress(
94
+ tensor.cpu(), sparsity_structure=sparsity_structure
95
+ )
96
+ return Sparse24BitMaskTensor(
97
+ shape=shape,
98
+ compressed=compressed,
99
+ bitmask=bitmask,
100
+ )
101
+
102
+ @staticmethod
103
+ def from_compressed_data(
104
+ shape: Union[List[int], Tensor], compressed: Tensor, bitmask: Tensor
105
+ ) -> "Sparse24BitMaskTensor":
106
+ """
107
+ :param shape: shape of the dense tensor (can be a list or a tensor)
108
+ :param compressed: 2d tensor of non-zero values
109
+ :param bitmask: 2d bitmask of non-zero values
110
+ :return: instantiated Sparse24BitMaskTensor
111
+ """
112
+ if isinstance(shape, list):
113
+ shape = torch.tensor(shape)
114
+ if isinstance(shape, torch.Tensor):
115
+ shape = shape.flatten().tolist()
116
+ return Sparse24BitMaskTensor(
117
+ shape=shape, compressed=compressed, bitmask=bitmask
118
+ )
119
+
120
+ def decompress(self) -> Tensor:
121
+ """
122
+ :return: reconstructed dense tensor
123
+ """
124
+ return sparse24_bitmask_decompress(self.compressed, self.bitmask, self.shape)
125
+
126
+ def curr_memory_size_bytes(self) -> int:
127
+ """
128
+ :return: size in bytes required to store compressed tensor on disk
129
+ """
130
+
131
+ def sizeof_tensor(a: Tensor) -> int:
132
+ return a.element_size() * a.nelement()
133
+
134
+ return sizeof_tensor(self.compressed) + sizeof_tensor(self.bitmask)
135
+
136
+ def dict(self, name_prefix: str, device: str = "cpu") -> Dict[str, Tensor]:
137
+ """
138
+ :param name_prefix: name of original tensor to store compressed weight as
139
+ :return: dict of compressed data for the stored weight
140
+ """
141
+ if name_prefix.endswith(".weight"):
142
+ name_prefix = name_prefix[: -len(".weight")]
143
+ return {
144
+ merge_names(name_prefix, "shape"): torch.tensor(
145
+ self.shape, device=device
146
+ ).reshape(-1, 1),
147
+ merge_names(name_prefix, "compressed"): self.compressed.to(device),
148
+ merge_names(name_prefix, "bitmask"): self.bitmask.to(device),
149
+ }
150
+
151
+ def __repr__(self) -> str:
152
+ return f"BitMaskTensor(shape={self.shape}, compressed=True)"
153
+
154
+
155
+ def sparse24_bitmask_compress(
156
+ tensor: Tensor,
157
+ sparsity_structure: Union[SparsityStructure, str] = SparsityStructure.TWO_FOUR,
158
+ ) -> Tuple[Tensor, Tensor, Tensor]:
159
+ """
160
+ Compresses a dense tensor using bitmask compression
161
+
162
+ :param tensor: dense 2D tensor to compress
163
+ :param sparsity_structure: structure of sparsity in the tensor, defaults
164
+ to unstructured, can also be set to `2:4`
165
+ :return: tuple of compressed data representing tensor
166
+ """
167
+ assert len(tensor.shape) == 2, "Only 2D tensors are supported"
168
+ assert (
169
+ SparsityStructure(sparsity_structure) == SparsityStructure.TWO_FOUR
170
+ ), "Only 2:4 sparsity is supported"
171
+
172
+ bytemasks = get_24_bytemasks(tensor=tensor)
173
+
174
+ if tensor.dtype == FP8_DTYPE:
175
+ # acces raw bytes of the tensor
176
+ tensor_view = tensor.view(torch.int8)
177
+ values = tensor_view[bytemasks]
178
+ values = values.view(FP8_DTYPE)
179
+ else:
180
+ values = tensor[bytemasks]
181
+
182
+ num_rows, num_cols = tensor.shape
183
+ compressed_values = values.reshape(num_rows, num_cols // 2)
184
+ bitmasks_packed = pack_bitmasks(bytemasks)
185
+ return compressed_values, bitmasks_packed
186
+
187
+
188
+ def sparse24_bitmask_decompress(
189
+ values: Tensor, bitmasks: Tensor, original_shape: torch.Size
190
+ ) -> Tensor:
191
+ """
192
+ Reconstructs a dense tensor from a compressed one
193
+
194
+ :param values: 1d tensor of non-zero values
195
+ :param bitmasks: 2d int8 tensor flagging locations of non-zero values in the
196
+ tensors original shape
197
+ :param original_shape: shape of the dense tensor
198
+ :return: decompressed dense tensor
199
+ """
200
+ bytemasks_unpacked = unpack_bitmasks(bitmasks, original_shape)
201
+
202
+ decompressed_tensor = torch.zeros(original_shape, dtype=values.dtype)
203
+ decompressed_tensor = decompressed_tensor.to(values.device)
204
+ values = values.flatten()
205
+ if decompressed_tensor.dtype == FP8_DTYPE:
206
+ decompressed_tensor[bytemasks_unpacked] = values
207
+ decompressed_tensor = decompressed_tensor.cuda()
208
+ else:
209
+ decompressed_tensor[bytemasks_unpacked] = values
210
+ return decompressed_tensor
211
+
212
+
213
+ def get_24_bytemasks(tensor):
214
+ """
215
+ Generate a 2:4 sparsity mask for the given tensor.
216
+
217
+ This function creates a mask where exactly 2 out of every 4 elements are
218
+ preserved based on their magnitudes. The preserved elements are the ones
219
+ with the highest absolute values in each group of 4 elements.
220
+
221
+ :param tensor: The input tensor for which the 2:4 sparsity mask is to be created.
222
+ The tensor can be of any shape but its total number of elements
223
+ must be a multiple of 4.
224
+ :return: A boolean tensor of the same shape as the input tensor, where `True`
225
+ indicates the preserved elements and `False` indicates the pruned elements.
226
+ :raises ValueError: If the total number of elements in the tensor is not a
227
+ multiple of 4.
228
+ """
229
+ original_dtype = tensor.dtype
230
+ if tensor.dtype == FP8_DTYPE:
231
+ tensor = tensor.view(torch.int8)
232
+ original_shape = tensor.shape
233
+ num_elements = tensor.numel()
234
+
235
+ if num_elements % 4 != 0:
236
+ raise ValueError("Tensor size must be a multiple of 4 for TWO_FOUR sparsity")
237
+
238
+ reshaped_tensor = tensor.view(-1, 4)
239
+ abs_tensor = reshaped_tensor.abs()
240
+ topk_indices = abs_tensor.topk(2, dim=1).indices
241
+ mask = torch.zeros_like(reshaped_tensor, dtype=torch.bool)
242
+ mask.scatter_(1, topk_indices, True)
243
+ mask = mask.view(original_shape)
244
+ tensor = tensor.view(original_dtype)
245
+
246
+ return mask
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_compressors/sparse_bitmask.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Dict, List, Tuple, Union
16
+
17
+ import torch
18
+ from compressed_tensors.compressors.base import BaseCompressor
19
+ from compressed_tensors.compressors.sparse_compressors.base import BaseSparseCompressor
20
+ from compressed_tensors.config import CompressionFormat
21
+ from compressed_tensors.quantization import FP8_DTYPE
22
+ from compressed_tensors.utils import merge_names, pack_bitmasks, unpack_bitmasks
23
+ from torch import Tensor
24
+
25
+
26
+ __all__ = [
27
+ "BitmaskCompressor",
28
+ "BitmaskTensor",
29
+ "bitmask_compress",
30
+ "bitmask_decompress",
31
+ ]
32
+
33
+
34
+ @BaseCompressor.register(name=CompressionFormat.sparse_bitmask.value)
35
+ class BitmaskCompressor(BaseSparseCompressor):
36
+ """
37
+ Compression for sparse models using bitmasks. Non-zero weights are stored in a 1d
38
+ values tensor, with their locations stored in a 2d bitmask
39
+ """
40
+
41
+ @property
42
+ def compression_param_names(self) -> Tuple[str]:
43
+ """
44
+ Returns a tuple of compression parameter names introduced by
45
+ the compressor during compression
46
+ """
47
+ return ("shape", "compressed", "bitmask", "row_offsets")
48
+
49
+ def compress_weight(self, name, value):
50
+ bitmask_tensor = BitmaskTensor.from_dense(value)
51
+ bitmask_dict = bitmask_tensor.dict(name_prefix=name, device="cpu")
52
+ return bitmask_dict
53
+
54
+ def decompress_weight(self, weight_data):
55
+ data = BitmaskTensor(**weight_data)
56
+ decompressed = data.decompress()
57
+ return decompressed
58
+
59
+
60
+ class BitmaskTensor:
61
+ """
62
+ Owns compressions and decompression for a single bitmask compressed tensor.
63
+ Adapted from: https://github.com/mgoin/torch_bitmask/tree/main
64
+
65
+ :param shape: shape of dense tensor
66
+ :compressed: flat tensor of non-zero values
67
+ :bitmask: 2d bitmask of non-zero values
68
+ :row_offsets: flat tensor indicating what index in values each dense row starts at
69
+ """
70
+
71
+ def __init__(
72
+ self,
73
+ shape: Union[torch.Size, List],
74
+ compressed: Tensor,
75
+ bitmask: Tensor,
76
+ row_offsets: Tensor,
77
+ ):
78
+ self.shape = list(shape)
79
+ self.compressed = compressed
80
+ self.bitmask = bitmask
81
+ self.row_offsets = row_offsets
82
+
83
+ @staticmethod
84
+ def from_dense(tensor: Tensor) -> "BitmaskTensor":
85
+ """
86
+ :param tensor: dense tensor to compress
87
+ :return: instantiated compressed tensor
88
+ """
89
+ shape = tensor.shape
90
+ compressed, bitmask, row_offsets = bitmask_compress(tensor.cpu())
91
+ return BitmaskTensor(
92
+ shape=shape, compressed=compressed, bitmask=bitmask, row_offsets=row_offsets
93
+ )
94
+
95
+ def decompress(self) -> Tensor:
96
+ """
97
+ :return: reconstructed dense tensor
98
+ """
99
+ return bitmask_decompress(self.compressed, self.bitmask, self.shape)
100
+
101
+ def curr_memory_size_bytes(self):
102
+ """
103
+ :return: size in bytes required to store compressed tensor on disk
104
+ """
105
+
106
+ def sizeof_tensor(a):
107
+ return a.element_size() * a.nelement()
108
+
109
+ return (
110
+ sizeof_tensor(self.compressed)
111
+ + sizeof_tensor(self.bitmask)
112
+ + sizeof_tensor(self.row_offsets)
113
+ )
114
+
115
+ def dict(self, name_prefix: str, device: str = "cpu") -> Dict[str, Tensor]:
116
+ """
117
+ :name_prefix: name of original tensor to store compressed weight as
118
+ :return: dict of compressed data for the stored weight
119
+ """
120
+ return {
121
+ merge_names(name_prefix, "shape"): torch.tensor(self.shape, device=device),
122
+ merge_names(name_prefix, "compressed"): self.compressed.to(device),
123
+ merge_names(name_prefix, "bitmask"): self.bitmask.to(device),
124
+ merge_names(name_prefix, "row_offsets"): self.row_offsets.to(device),
125
+ }
126
+
127
+ def __repr__(self):
128
+ return f"BitmaskTensor(shape={self.shape}, compressed=True)"
129
+
130
+
131
+ def bitmask_compress(tensor: Tensor) -> Tuple[Tensor, Tensor, Tensor]:
132
+ """
133
+ Compresses a dense tensor using bitmask compression
134
+
135
+ :param tensor: dense tensor to compress
136
+ :return: tuple of compressed data representing tensor
137
+ """
138
+ bytemasks = tensor != 0
139
+ row_counts = bytemasks.sum(dim=-1)
140
+ row_offsets = torch.cumsum(row_counts, 0) - row_counts
141
+ if tensor.dtype == FP8_DTYPE:
142
+ # acces raw bytes of the tensor
143
+ tensor_view = tensor.view(torch.int8)
144
+ values = tensor_view[bytemasks]
145
+ values = values.view(FP8_DTYPE)
146
+ else:
147
+ values = tensor[bytemasks]
148
+ bitmasks_packed = pack_bitmasks(bytemasks)
149
+ return values, bitmasks_packed, row_offsets
150
+
151
+
152
+ def bitmask_decompress(
153
+ values: Tensor, bitmasks: Tensor, original_shape: torch.Size
154
+ ) -> Tensor:
155
+ """
156
+ Reconstructs a dense tensor from a compressed one
157
+
158
+ :param values: 1d tensor of non-zero values
159
+ :param bitmasks: 2d int8 tensor flagging locations of non-zero values in the
160
+ tensors original shape
161
+ :param original_shape: shape of the dense tensor
162
+ :return: decompressed dense tensor
163
+ """
164
+ bytemasks_unpacked = unpack_bitmasks(bitmasks, original_shape)
165
+
166
+ decompressed_tensor = torch.zeros(original_shape, dtype=values.dtype)
167
+ decompressed_tensor[bytemasks_unpacked] = values
168
+
169
+ return decompressed_tensor
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_quantized_compressors/__init__.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # flake8: noqa
15
+
16
+ from .marlin_24 import Marlin24Compressor
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_quantized_compressors/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (295 Bytes). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_quantized_compressors/__pycache__/marlin_24.cpython-312.pyc ADDED
Binary file (11 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/compressors/sparse_quantized_compressors/marlin_24.py ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import logging
16
+ from typing import Dict, Generator, Tuple
17
+
18
+ import numpy as np
19
+ import torch
20
+ from compressed_tensors.compressors.base import BaseCompressor
21
+ from compressed_tensors.config import CompressionFormat
22
+ from compressed_tensors.quantization import QuantizationArgs, QuantizationStrategy
23
+ from compressed_tensors.quantization.lifecycle.forward import quantize
24
+ from compressed_tensors.utils import (
25
+ get_permutations_24,
26
+ is_quantization_param,
27
+ merge_names,
28
+ sparse_semi_structured_from_dense_cutlass,
29
+ tensor_follows_mask_structure,
30
+ )
31
+ from torch import Tensor
32
+ from tqdm import tqdm
33
+
34
+
35
+ _LOGGER: logging.Logger = logging.getLogger(__name__)
36
+
37
+
38
+ @BaseCompressor.register(name=CompressionFormat.marlin_24.value)
39
+ class Marlin24Compressor(BaseCompressor):
40
+ """
41
+ Compresses a quantized model with 2:4 sparsity structure for inference with the
42
+ Marlin24 kernel. Decompression is not implemented for this compressor.
43
+ """
44
+
45
+ @staticmethod
46
+ def validate_quant_compatability(
47
+ model_quant_args: Dict[str, QuantizationArgs]
48
+ ) -> bool:
49
+ """
50
+ Checks if every quantized module in the model is compatible with Marlin24
51
+ compression. Quantization must be channel or group strategy with group_size
52
+ of 128. Only symmetric quantization is supported
53
+
54
+ :param model_quant_args: dictionary of mapping module names to their
55
+ quantization configuration
56
+ :return: True if all modules are compatible with Marlin24 compression, raises
57
+ a ValueError otherwise
58
+ """
59
+ for name, quant_args in model_quant_args.items():
60
+ strategy = quant_args.strategy
61
+ group_size = quant_args.group_size
62
+ symmetric = quant_args.symmetric
63
+ if (
64
+ strategy is not QuantizationStrategy.GROUP.value
65
+ and strategy is not QuantizationStrategy.CHANNEL.value
66
+ ):
67
+ raise ValueError(
68
+ f"Marlin24 Compressor is only valid for group and channel "
69
+ f"quantization strategies, got {strategy} in {name}"
70
+ )
71
+
72
+ if group_size is not None and group_size != 128:
73
+ raise ValueError(
74
+ f"Marlin24 Compressor is only valid for group size 128, "
75
+ f"got {group_size} in {name}"
76
+ )
77
+
78
+ if not symmetric:
79
+ raise ValueError(
80
+ f"Marlin24 Compressor is only valid for symmetric quantzation, "
81
+ f"got symmetric={symmetric} in {name}"
82
+ )
83
+
84
+ return True
85
+
86
+ @staticmethod
87
+ def validate_sparsity_structure(name: str, weight: Tensor) -> bool:
88
+ """
89
+ Checks if a tensor fits the required 2:4 sparsity structure
90
+
91
+ :param name: name of the tensor to check
92
+ :param weight: tensor to check for sparsity structure
93
+ :return: True if all rows match the 2:4 sparsity structure, raises
94
+ ValueError otherwise
95
+ """
96
+
97
+ if not tensor_follows_mask_structure(weight):
98
+ raise ValueError(
99
+ "Marlin24 Compressor is only compatible with weights that have "
100
+ f"a 2:4 sparsity structure. Found segments in {name} "
101
+ "that do not match the expected structure."
102
+ )
103
+
104
+ return True
105
+
106
+ @property
107
+ def compression_param_names(self) -> Tuple[str]:
108
+ """
109
+ Returns a tuple of compression parameter names introduced by
110
+ the compressor during compression
111
+ """
112
+ return ("weight_packed", "scale_packed", "meta")
113
+
114
+ def compress(
115
+ self,
116
+ model_state: Dict[str, Tensor],
117
+ names_to_scheme: Dict[str, QuantizationArgs],
118
+ **kwargs,
119
+ ) -> Dict[str, Tensor]:
120
+ """
121
+ Compresses a quantized state_dict with 2:4 sparsity structure for inference
122
+ with the Marlin24 kernel
123
+
124
+ :param model_state: state dict of uncompressed model
125
+ :param names_to_scheme: quantization args for each quantized weight, needed for
126
+ quantize function to calculate bit depth
127
+ :return: compressed state dict
128
+ """
129
+ self.validate_quant_compatability(names_to_scheme)
130
+
131
+ compressed_dict = {}
132
+ weight_suffix = ".weight"
133
+ _LOGGER.debug(
134
+ f"Compressing model with {len(model_state)} parameterized layers..."
135
+ )
136
+
137
+ for name, value in tqdm(model_state.items(), desc="Compressing model"):
138
+ if name.endswith(weight_suffix):
139
+ prefix = name[: -(len(weight_suffix))]
140
+ scale = model_state.get(merge_names(prefix, "weight_scale"), None)
141
+ zp = model_state.get(merge_names(prefix, "weight_zero_point"), None)
142
+ if scale is not None: # weight is quantized, compress it
143
+
144
+ # Marlin24 kernel requires float16 inputs
145
+ scale = scale.to(torch.float16)
146
+ value = value.to(torch.float16)
147
+
148
+ # quantize weight, keeping it as a float16 for now
149
+ quant_args = names_to_scheme[prefix]
150
+ value = quantize(
151
+ x=value, scale=scale, zero_point=zp, args=quant_args
152
+ )
153
+
154
+ # compress based on sparsity structure
155
+ self.validate_sparsity_structure(prefix, value)
156
+ value, meta = compress_weight_24(value)
157
+ meta = meta.cpu()
158
+
159
+ # Marlin24 kernel expects input dim first
160
+ value = value.t().contiguous().cpu()
161
+ scale = scale.t().contiguous().cpu()
162
+ og_weight_shape = value.shape
163
+
164
+ # Marlin24 kernel expects unsigned values, shift zero-point
165
+ value += (1 << quant_args.num_bits) // 2
166
+
167
+ # pack quantized weight and scale
168
+ value = pack_weight_24(value, quant_args)
169
+ packed_scale = pack_scales_24(scale, quant_args, og_weight_shape)
170
+ meta = meta.resize_(meta.shape[1] // 2, meta.shape[0] * 2)
171
+
172
+ # save compressed values
173
+ compressed_dict[merge_names(prefix, "scale_packed")] = packed_scale
174
+ compressed_dict[merge_names(prefix, "weight_packed")] = value
175
+ compressed_dict[merge_names(prefix, "meta")] = meta
176
+ continue
177
+
178
+ if not is_quantization_param(name):
179
+ # export unquantized parameters without modifying
180
+ compressed_dict[name] = value.to("cpu")
181
+
182
+ return compressed_dict
183
+
184
+ def decompress(
185
+ self, path_to_model_or_tensors: str, device: str = "cpu", **kwargs
186
+ ) -> Generator[Tuple[str, Tensor], None, None]:
187
+ raise NotImplementedError(
188
+ "Decompression is not implemented for the Marlin24 Compressor."
189
+ )
190
+
191
+
192
+ def compress_weight_24(weight: Tensor):
193
+ weight = weight.contiguous()
194
+ w_comp, meta = sparse_semi_structured_from_dense_cutlass(weight)
195
+ w_comp = w_comp.contiguous()
196
+ return w_comp, meta
197
+
198
+
199
+ def marlin_permute_weights(q_w, size_k, size_n, perm, tile):
200
+ assert q_w.shape == (size_k, size_n)
201
+ assert size_k % tile == 0, f"size_k = {size_k}, tile = {tile}"
202
+ assert size_n % tile == 0, f"size_k = {size_n}, tile = {tile}"
203
+
204
+ # Permute weights to 16x64 marlin tiles
205
+ q_w = q_w.reshape((size_k // tile, tile, size_n // tile, tile))
206
+ q_w = q_w.permute((0, 2, 1, 3))
207
+ q_w = q_w.reshape((size_k // tile, size_n * tile))
208
+
209
+ q_w = q_w.reshape((-1, perm.numel()))[:, perm].reshape(q_w.shape)
210
+
211
+ return q_w
212
+
213
+
214
+ def pack_weight_24(
215
+ weight: Tensor,
216
+ quantization_args: QuantizationArgs,
217
+ tile: int = 16,
218
+ ):
219
+ size_k = weight.shape[0]
220
+ size_n = weight.shape[1]
221
+ num_bits = quantization_args.num_bits
222
+ pack_factor = 32 // num_bits
223
+
224
+ # Reshuffle to marlin_24 format
225
+ perm, _, _ = get_permutations_24(num_bits)
226
+ q_w = marlin_permute_weights(weight, size_k, size_n, perm, tile)
227
+
228
+ q_w = q_w.cpu().numpy().astype(np.uint32)
229
+
230
+ q_packed = np.zeros((q_w.shape[0], q_w.shape[1] // pack_factor), dtype=np.uint32)
231
+ for i in range(pack_factor):
232
+ q_packed |= q_w[:, i::pack_factor] << num_bits * i
233
+
234
+ q_packed = torch.from_numpy(q_packed.astype(np.int32))
235
+
236
+ return q_packed
237
+
238
+
239
+ def pack_scales_24(scales, quantization_args, w_shape):
240
+ size_k = w_shape[0]
241
+ size_n = w_shape[1]
242
+ num_bits = quantization_args.num_bits
243
+
244
+ _, scale_perm_2_4, scale_perm_single_2_4 = get_permutations_24(num_bits)
245
+
246
+ if (
247
+ quantization_args.strategy == QuantizationStrategy.GROUP
248
+ and quantization_args.group_size < size_k
249
+ ):
250
+ scales = scales.reshape((-1, len(scale_perm_2_4)))[:, scale_perm_2_4]
251
+ else: # channelwise
252
+ scales = scales.reshape((-1, len(scale_perm_single_2_4)))[
253
+ :, scale_perm_single_2_4
254
+ ]
255
+ scales = scales.reshape((-1, size_n)).contiguous()
256
+
257
+ return scales
lib/python3.12/site-packages/compressed_tensors/config/__init__.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # flake8: noqa
16
+ from .base import *
17
+ from .dense import *
18
+ from .sparse_24_bitmask import *
19
+ from .sparse_bitmask import *
lib/python3.12/site-packages/compressed_tensors/config/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (313 Bytes). View file
 
lib/python3.12/site-packages/compressed_tensors/config/__pycache__/base.cpython-312.pyc ADDED
Binary file (4 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/config/__pycache__/dense.cpython-312.pyc ADDED
Binary file (1.29 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/config/__pycache__/sparse_24_bitmask.cpython-312.pyc ADDED
Binary file (1.41 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/config/__pycache__/sparse_bitmask.cpython-312.pyc ADDED
Binary file (1.28 kB). View file
 
lib/python3.12/site-packages/compressed_tensors/config/base.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from enum import Enum, unique
16
+ from typing import List, Optional
17
+
18
+ from compressed_tensors.registry import RegistryMixin
19
+ from pydantic import BaseModel
20
+
21
+
22
+ __all__ = ["SparsityCompressionConfig", "CompressionFormat", "SparsityStructure"]
23
+
24
+
25
+ @unique
26
+ class CompressionFormat(Enum):
27
+ dense = "dense"
28
+ sparse_bitmask = "sparse-bitmask"
29
+ sparse_24_bitmask = "sparse-24-bitmask"
30
+ int_quantized = "int-quantized"
31
+ float_quantized = "float-quantized"
32
+ naive_quantized = "naive-quantized"
33
+ pack_quantized = "pack-quantized"
34
+ marlin_24 = "marlin-24"
35
+
36
+
37
+ @unique
38
+ class SparsityStructure(Enum):
39
+ """
40
+ An enumeration to represent different sparsity structures.
41
+
42
+ Attributes
43
+ ----------
44
+ TWO_FOUR : str
45
+ Represents a 2:4 sparsity structure.
46
+ ZERO_ZERO : str
47
+ Represents a 0:0 sparsity structure.
48
+ UNSTRUCTURED : str
49
+ Represents an unstructured sparsity structure.
50
+
51
+ Examples
52
+ --------
53
+ >>> SparsityStructure('2:4')
54
+ <SparsityStructure.TWO_FOUR: '2:4'>
55
+
56
+ >>> SparsityStructure('unstructured')
57
+ <SparsityStructure.UNSTRUCTURED: 'unstructured'>
58
+
59
+ >>> SparsityStructure('2:4') == SparsityStructure.TWO_FOUR
60
+ True
61
+
62
+ >>> SparsityStructure('UNSTRUCTURED') == SparsityStructure.UNSTRUCTURED
63
+ True
64
+
65
+ >>> SparsityStructure(None) == SparsityStructure.UNSTRUCTURED
66
+ True
67
+
68
+ >>> SparsityStructure('invalid')
69
+ Traceback (most recent call last):
70
+ ...
71
+ ValueError: invalid is not a valid SparsityStructure
72
+ """
73
+
74
+ TWO_FOUR = "2:4"
75
+ UNSTRUCTURED = "unstructured"
76
+ ZERO_ZERO = "0:0"
77
+
78
+ def __new__(cls, value):
79
+ obj = object.__new__(cls)
80
+ obj._value_ = value.lower() if value is not None else value
81
+ return obj
82
+
83
+ @classmethod
84
+ def _missing_(cls, value):
85
+ # Handle None and case-insensitive values
86
+ if value is None:
87
+ return cls.UNSTRUCTURED
88
+ for member in cls:
89
+ if member.value == value.lower():
90
+ return member
91
+ raise ValueError(f"{value} is not a valid {cls.__name__}")
92
+
93
+
94
+ class SparsityCompressionConfig(RegistryMixin, BaseModel):
95
+ """
96
+ Base data class for storing sparsity compression parameters
97
+
98
+ :param format: name of compression format
99
+ :param targets: List of layer names or layer types that aren't sparse and should
100
+ be ignored during compression. By default, assume all layers are targeted
101
+ :param ignore: List of layer names (unique) to ignore from targets. Defaults to None
102
+ :param global_sparsity: average sparsity of the entire model
103
+ :param sparsity_structure: structure of the sparsity, such as
104
+ "unstructured", "2:4", "8:16" etc
105
+ """
106
+
107
+ format: str
108
+ targets: Optional[List[str]] = None
109
+ ignore: Optional[List[str]] = None
110
+ global_sparsity: Optional[float] = 0.0
111
+ sparsity_structure: Optional[str] = "unstructured"
lib/python3.12/site-packages/compressed_tensors/config/dense.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Optional
16
+
17
+ from compressed_tensors.config import CompressionFormat, SparsityCompressionConfig
18
+
19
+
20
+ __all__ = ["DenseSparsityConfig"]
21
+
22
+
23
+ @SparsityCompressionConfig.register(name=CompressionFormat.dense.value)
24
+ class DenseSparsityConfig(SparsityCompressionConfig):
25
+ """
26
+ Identity configuration for storing a sparse model in
27
+ an uncompressed dense format
28
+
29
+ :param global_sparsity: average sparsity of the entire model
30
+ :param sparsity_structure: structure of the sparsity, such as
31
+ "unstructured", "2:4", "8:16" etc
32
+ """
33
+
34
+ format: str = CompressionFormat.dense.value
35
+ global_sparsity: Optional[float] = 0.0
36
+ sparsity_structure: Optional[str] = "unstructured"
lib/python3.12/site-packages/compressed_tensors/config/sparse_24_bitmask.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Optional
16
+
17
+ from compressed_tensors.config import (
18
+ CompressionFormat,
19
+ SparsityCompressionConfig,
20
+ SparsityStructure,
21
+ )
22
+
23
+
24
+ __all__ = ["Sparse24BitMaskConfig"]
25
+
26
+
27
+ @SparsityCompressionConfig.register(name=CompressionFormat.sparse_24_bitmask.value)
28
+ class Sparse24BitMaskConfig(SparsityCompressionConfig):
29
+ """
30
+ Configuration for storing a 24 sparse model using
31
+ bytemask compression
32
+
33
+ :param global_sparsity: average sparsity of the entire model
34
+ :param sparsity_structure: structure of the sparsity, should always be
35
+ "2:4" for this compression format
36
+ """
37
+
38
+ format: str = CompressionFormat.sparse_24_bitmask.value
39
+ global_sparsity: Optional[float] = 0.0
40
+ sparsity_structure: Optional[str] = SparsityStructure.TWO_FOUR.value
lib/python3.12/site-packages/compressed_tensors/config/sparse_bitmask.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from typing import Optional
16
+
17
+ from compressed_tensors.config import CompressionFormat, SparsityCompressionConfig
18
+
19
+
20
+ __all__ = ["BitmaskConfig"]
21
+
22
+
23
+ @SparsityCompressionConfig.register(name=CompressionFormat.sparse_bitmask.value)
24
+ class BitmaskConfig(SparsityCompressionConfig):
25
+ """
26
+ Configuration for storing a sparse model using
27
+ bitmask compression
28
+
29
+ :param global_sparsity: average sparsity of the entire model
30
+ :param sparsity_structure: structure of the sparsity, such as
31
+ "unstructured", "2:4", "8:16" etc
32
+ """
33
+
34
+ format: str = CompressionFormat.sparse_bitmask.value
35
+ global_sparsity: Optional[float] = 0.0
36
+ sparsity_structure: Optional[str] = "unstructured"
lib/python3.12/site-packages/compressed_tensors/linear/__init__.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing,
10
+ # software distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
lib/python3.12/site-packages/compressed_tensors/linear/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (204 Bytes). View file
 
lib/python3.12/site-packages/compressed_tensors/linear/__pycache__/compressed_linear.cpython-312.pyc ADDED
Binary file (4.2 kB). View file