tico 0.1.0.dev250617__py3-none-any.whl → 0.1.0.dev250619__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tico/__init__.py +1 -1
- tico/experimental/quantization/passes/quantize_bias.py +123 -0
- tico/experimental/quantization/passes/remove_weight_dequant_op.py +3 -0
- tico/serialize/operators/op_leaky_relu.py +60 -0
- tico/serialize/operators/op_max_pool2d_with_indices.py +2 -1
- tico/utils/convert.py +2 -0
- tico/utils/validate_args_kwargs.py +11 -0
- {tico-0.1.0.dev250617.dist-info → tico-0.1.0.dev250619.dist-info}/METADATA +1 -1
- {tico-0.1.0.dev250617.dist-info → tico-0.1.0.dev250619.dist-info}/RECORD +13 -11
- {tico-0.1.0.dev250617.dist-info → tico-0.1.0.dev250619.dist-info}/LICENSE +0 -0
- {tico-0.1.0.dev250617.dist-info → tico-0.1.0.dev250619.dist-info}/WHEEL +0 -0
- {tico-0.1.0.dev250617.dist-info → tico-0.1.0.dev250619.dist-info}/entry_points.txt +0 -0
- {tico-0.1.0.dev250617.dist-info → tico-0.1.0.dev250619.dist-info}/top_level.txt +0 -0
tico/__init__.py
CHANGED
@@ -21,7 +21,7 @@ from tico.config import CompileConfigV1, get_default_config
|
|
21
21
|
from tico.utils.convert import convert, convert_from_exported_program, convert_from_pt2
|
22
22
|
|
23
23
|
# THIS LINE IS AUTOMATICALLY GENERATED BY setup.py
|
24
|
-
__version__ = "0.1.0.
|
24
|
+
__version__ = "0.1.0.dev250619"
|
25
25
|
|
26
26
|
MINIMUM_SUPPORTED_VERSION = "2.5.0"
|
27
27
|
SECURE_TORCH_VERSION = "2.6.0"
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# Copyright (c) 2025 Samsung Electronics Co., Ltd. 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, software
|
10
|
+
# 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 TYPE_CHECKING
|
16
|
+
|
17
|
+
if TYPE_CHECKING:
|
18
|
+
import torch.fx
|
19
|
+
import copy
|
20
|
+
|
21
|
+
import torch
|
22
|
+
from torch.export import ExportedProgram
|
23
|
+
|
24
|
+
from tico.serialize.quant_param import QPARAM_KEY, QuantParam, to_qparam_dtype
|
25
|
+
from tico.utils import logging
|
26
|
+
from tico.utils.graph import add_placeholder, get_torch_param_value, is_torch_param
|
27
|
+
from tico.utils.passes import PassBase, PassResult
|
28
|
+
from tico.utils.trace_decorators import trace_graph_diff_on_pass
|
29
|
+
from tico.utils.validate_args_kwargs import LinearArgs
|
30
|
+
|
31
|
+
|
32
|
+
@trace_graph_diff_on_pass
|
33
|
+
class QuantizeBias(PassBase):
|
34
|
+
"""
|
35
|
+
Quantize bias.
|
36
|
+
|
37
|
+
This pass identifies fp32 biases, quantizes them using scales of input and weights.
|
38
|
+
|
39
|
+
This pass assumes that if bias is fp32, input and weights must have been quantized.
|
40
|
+
"""
|
41
|
+
|
42
|
+
def __init__(self):
|
43
|
+
super().__init__()
|
44
|
+
|
45
|
+
def call(self, exported_program: ExportedProgram) -> PassResult:
|
46
|
+
logger = logging.getLogger(__name__)
|
47
|
+
|
48
|
+
graph_module = exported_program.graph_module
|
49
|
+
graph: torch.fx.Graph = graph_module.graph
|
50
|
+
for node in graph.nodes:
|
51
|
+
if node.op != "call_function":
|
52
|
+
continue
|
53
|
+
if node.target == torch.ops.aten.linear.default:
|
54
|
+
lin_args = LinearArgs(*node.args, **node.kwargs)
|
55
|
+
inp = lin_args.input
|
56
|
+
weights = lin_args.weight
|
57
|
+
bias = lin_args.bias
|
58
|
+
|
59
|
+
if bias is None:
|
60
|
+
continue
|
61
|
+
|
62
|
+
# Only support bias is Parameter
|
63
|
+
# TODO Is it possible that bias is not Parameter?
|
64
|
+
if not is_torch_param(bias, exported_program):
|
65
|
+
continue
|
66
|
+
|
67
|
+
bias_val: torch.Tensor = get_torch_param_value(bias, exported_program)
|
68
|
+
if bias_val.dtype != torch.float32:
|
69
|
+
continue
|
70
|
+
|
71
|
+
if QPARAM_KEY not in inp.meta:
|
72
|
+
continue
|
73
|
+
|
74
|
+
if QPARAM_KEY not in weights.meta:
|
75
|
+
continue
|
76
|
+
|
77
|
+
quant_dtype = None
|
78
|
+
if inp.meta[QPARAM_KEY].dtype == "int16":
|
79
|
+
quant_dtype = torch.int64
|
80
|
+
elif inp.meta[QPARAM_KEY].dtype == "uint8":
|
81
|
+
quant_dtype = torch.int32
|
82
|
+
else:
|
83
|
+
continue
|
84
|
+
|
85
|
+
type_info = torch.iinfo(quant_dtype)
|
86
|
+
|
87
|
+
assert quant_dtype is not None
|
88
|
+
|
89
|
+
i_scale = inp.meta[QPARAM_KEY].scale
|
90
|
+
w_scale = weights.meta[QPARAM_KEY].scale
|
91
|
+
|
92
|
+
assert i_scale is not None
|
93
|
+
assert w_scale is not None
|
94
|
+
assert len(i_scale) == 1
|
95
|
+
assert len(w_scale) == bias_val.shape[0]
|
96
|
+
|
97
|
+
bias_scale = torch.tensor(i_scale) * torch.tensor(w_scale)
|
98
|
+
q_bias = torch.round(bias_val / bias_scale)
|
99
|
+
q_bias = torch.clamp(q_bias, min=type_info.min, max=type_info.max)
|
100
|
+
q_bias = q_bias.to(quant_dtype)
|
101
|
+
|
102
|
+
q_bias_node = add_placeholder(exported_program, q_bias, bias.name)
|
103
|
+
|
104
|
+
qparam = QuantParam()
|
105
|
+
qparam.scale = bias_scale.tolist()
|
106
|
+
assert qparam.scale is not None
|
107
|
+
qparam.zero_point = [0] * len(qparam.scale)
|
108
|
+
qparam.dtype = to_qparam_dtype(quant_dtype)
|
109
|
+
qparam.quantized_dimension = 0
|
110
|
+
q_bias_node.meta[QPARAM_KEY] = qparam
|
111
|
+
|
112
|
+
node.update_arg(2, q_bias_node)
|
113
|
+
|
114
|
+
logger.debug(f"Bias ({bias.name}) is quantized to {q_bias_node.name}.")
|
115
|
+
|
116
|
+
# TODO Support more ops.
|
117
|
+
|
118
|
+
graph.eliminate_dead_code()
|
119
|
+
graph.lint()
|
120
|
+
graph_module.recompile()
|
121
|
+
|
122
|
+
# Run only once.
|
123
|
+
return PassResult(False)
|
@@ -145,6 +145,9 @@ class RemoveWeightDequantOp(PassBase):
|
|
145
145
|
if isinstance(dq_args, DequantizePerChannelArgs):
|
146
146
|
scales = get_constant(exported_program, dq_args.scales)
|
147
147
|
zero_ps = get_constant(exported_program, dq_args.zero_points)
|
148
|
+
|
149
|
+
# Sometimes users can give fp32 zero point. Let's update dtype here.
|
150
|
+
zero_ps = zero_ps.to(torch.int64)
|
148
151
|
quant_param.scale = scales.tolist()
|
149
152
|
quant_param.zero_point = zero_ps.tolist()
|
150
153
|
assert quant_param.zero_point is not None # To avoid mypy error
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Copyright (c) 2025 Samsung Electronics Co., Ltd. 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, software
|
10
|
+
# 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, TYPE_CHECKING
|
16
|
+
|
17
|
+
if TYPE_CHECKING:
|
18
|
+
import torch._ops
|
19
|
+
import torch.fx
|
20
|
+
import torch
|
21
|
+
from circle_schema import circle
|
22
|
+
|
23
|
+
from tico.serialize.circle_graph import CircleSubgraph
|
24
|
+
from tico.serialize.operators.hashable_opcode import OpCode
|
25
|
+
from tico.serialize.operators.node_visitor import NodeVisitor, register_node_visitor
|
26
|
+
from tico.serialize.operators.utils import create_builtin_operator, get_op_index
|
27
|
+
from tico.utils.validate_args_kwargs import LeakyReluArgs
|
28
|
+
|
29
|
+
|
30
|
+
@register_node_visitor
|
31
|
+
class LeakyReluVisitor(NodeVisitor):
|
32
|
+
target: List[torch._ops.OpOverload] = [torch.ops.aten.leaky_relu.default]
|
33
|
+
|
34
|
+
def __init__(self, op_codes: Dict[OpCode, int], graph: CircleSubgraph):
|
35
|
+
super().__init__(op_codes, graph)
|
36
|
+
|
37
|
+
def define_node(
|
38
|
+
self,
|
39
|
+
node: torch.fx.Node,
|
40
|
+
) -> circle.Operator.OperatorT:
|
41
|
+
op_index = get_op_index(
|
42
|
+
circle.BuiltinOperator.BuiltinOperator.LEAKY_RELU, self._op_codes
|
43
|
+
)
|
44
|
+
|
45
|
+
args = LeakyReluArgs(*node.args, **node.kwargs) # type: ignore[arg-type]
|
46
|
+
input = args.input
|
47
|
+
negative_slope = args.negative_slope
|
48
|
+
|
49
|
+
inputs = [input]
|
50
|
+
outputs = [node]
|
51
|
+
|
52
|
+
operator = create_builtin_operator(self.graph, op_index, inputs, outputs)
|
53
|
+
operator.builtinOptionsType = (
|
54
|
+
circle.BuiltinOptions.BuiltinOptions.LeakyReluOptions
|
55
|
+
)
|
56
|
+
option = circle.LeakyReluOptions.LeakyReluOptionsT()
|
57
|
+
option.alpha = negative_slope
|
58
|
+
operator.builtinOptions = option
|
59
|
+
|
60
|
+
return operator
|
@@ -124,7 +124,8 @@ class MaxPool2DWithIndicesVisitor(NodeVisitor):
|
|
124
124
|
padding_type = PaddingType.SAME
|
125
125
|
else:
|
126
126
|
padding_type = PaddingType.VALID
|
127
|
-
|
127
|
+
if padding[0] != 0 or padding[1] != 0:
|
128
|
+
maxpool_input = define_padding_node()
|
128
129
|
|
129
130
|
inputs = [maxpool_input]
|
130
131
|
outputs = [node]
|
tico/utils/convert.py
CHANGED
@@ -30,6 +30,7 @@ from tico.experimental.quantization.passes.propagate_qparam_backward import (
|
|
30
30
|
from tico.experimental.quantization.passes.propagate_qparam_forward import (
|
31
31
|
PropagateQParamForward,
|
32
32
|
)
|
33
|
+
from tico.experimental.quantization.passes.quantize_bias import QuantizeBias
|
33
34
|
from tico.experimental.quantization.passes.remove_weight_dequant_op import (
|
34
35
|
RemoveWeightDequantOp,
|
35
36
|
)
|
@@ -250,6 +251,7 @@ def convert_exported_module_to_circle(
|
|
250
251
|
RemoveWeightDequantOp(),
|
251
252
|
PropagateQParamForward(),
|
252
253
|
PropagateQParamBackward(),
|
254
|
+
QuantizeBias(),
|
253
255
|
InsertQuantizeOnDtypeMismatch(),
|
254
256
|
]
|
255
257
|
)
|
@@ -513,6 +513,17 @@ class InstanceNormArgs:
|
|
513
513
|
cudnn_enabled: bool
|
514
514
|
|
515
515
|
|
516
|
+
@enforce_type
|
517
|
+
@dataclass
|
518
|
+
class LeakyReluArgs:
|
519
|
+
"""
|
520
|
+
leaky_relu(Tensor self, Scalar negative_slope=0.01) -> Tensor
|
521
|
+
"""
|
522
|
+
|
523
|
+
input: torch.fx.Node
|
524
|
+
negative_slope: float = 0.01
|
525
|
+
|
526
|
+
|
516
527
|
@enforce_type
|
517
528
|
@dataclass
|
518
529
|
class LinearArgs:
|
@@ -1,4 +1,4 @@
|
|
1
|
-
tico/__init__.py,sha256=
|
1
|
+
tico/__init__.py,sha256=tvZ8ebod0VB1gCI6Pf4kkiUWrmA31DGVE_9E2MAjYXo,1743
|
2
2
|
tico/pt2_to_circle.py,sha256=PPmFNw20jw2Z2VyM3ln9pX__jTzBOAZiv0gT5a-p-Y8,2666
|
3
3
|
tico/config/__init__.py,sha256=xZzCXjZ84qE-CsBi-dfaL05bqpQ3stKKfTXhnrJRyVs,142
|
4
4
|
tico/config/base.py,sha256=anwOiJFkUxUi7Cef573JgQcjk6S-FSi6O_TLjYASW-g,1244
|
@@ -54,7 +54,8 @@ tico/experimental/quantization/passes/fold_quant_ops.py,sha256=OYUndHaSL3GiL8koI
|
|
54
54
|
tico/experimental/quantization/passes/insert_quantize_on_dtype_mismatch.py,sha256=AbNcI7rfIwHsQna_rFuwqFdOzFAU2lIB3sMK-vns8Dc,13072
|
55
55
|
tico/experimental/quantization/passes/propagate_qparam_backward.py,sha256=TGtyW0Z2qOTgVIasBdGRgbwH31YYd6ek7OvLTmCV614,3118
|
56
56
|
tico/experimental/quantization/passes/propagate_qparam_forward.py,sha256=RhUHGCR2RpBO5KYkQ7Z8U5u7HEwDq2wdKHLKAJCi-5c,5138
|
57
|
-
tico/experimental/quantization/passes/
|
57
|
+
tico/experimental/quantization/passes/quantize_bias.py,sha256=ZQ3rETYStpW28JUbODRixbq5sDEOiIOB_qWA-Jzuu-Y,4337
|
58
|
+
tico/experimental/quantization/passes/remove_weight_dequant_op.py,sha256=Klc_9-94tl0_AuAToKOjsWED_YPk5RB67eum0ddPX7o,6588
|
58
59
|
tico/interpreter/__init__.py,sha256=IO6FP_xYbGy0dW0HL26GXD3ouxARaxCK7bz9dn4blPQ,26
|
59
60
|
tico/interpreter/infer.py,sha256=vJ3b69ce9HrxNT0gFwbEhHpAyvVyuiunTgAeiqn5t64,4350
|
60
61
|
tico/interpreter/interpreter.py,sha256=tGbluCbrehTCqBu8mtGDNzby_ieJ2ry8_RH_eC0CQxk,3828
|
@@ -134,6 +135,7 @@ tico/serialize/operators/op_gt.py,sha256=JAVbtuAUNLYhtJycJJCEkYo9QAvmiK4lTMdw5yH
|
|
134
135
|
tico/serialize/operators/op_index.py,sha256=iDW2YSeUS_kLiWEaQ_MjrYpxZAFBbm7_GU_2B4SRe6c,3033
|
135
136
|
tico/serialize/operators/op_index_select.py,sha256=cw7IbvixooikGxzbpUmI9tHS4kjl4lXLtO9D-GO8qLQ,2277
|
136
137
|
tico/serialize/operators/op_instance_norm.py,sha256=AhcVm71ChB16BlPNwqBh5tMHCqMShOXHPkE8Ag9jBfQ,3144
|
138
|
+
tico/serialize/operators/op_leaky_relu.py,sha256=UJPoL7kAIp6nAjyDdda_afdOcMLHme7NE77b2y76exc,2160
|
137
139
|
tico/serialize/operators/op_linear.py,sha256=bw_mn2CiJy8CbpPevOV0PMPh0ZMWKAybLZ9cnIKJSsk,2527
|
138
140
|
tico/serialize/operators/op_log.py,sha256=1TKvH2lttdAHE0P84vcxmOvGBBRUs6D71Jrei7SdZHE,1827
|
139
141
|
tico/serialize/operators/op_log1p.py,sha256=gG7Fs4UDj_Nnp7U60UtPyz0fLv1lBpJVOGGCMm-42pY,3121
|
@@ -141,7 +143,7 @@ tico/serialize/operators/op_logical_and.py,sha256=WhQ8knuq32BO-WhAqkOgpcUStPkjoP
|
|
141
143
|
tico/serialize/operators/op_logical_not.py,sha256=ugrVcRqR3IvUUaiRVW5cArCYJbzmkcXp88QM846jCww,2129
|
142
144
|
tico/serialize/operators/op_lt.py,sha256=_vA7dWpV9wVBxB7JL9pLQT9BsV91NGQBq_0auAtHK5Y,2080
|
143
145
|
tico/serialize/operators/op_max_dim.py,sha256=nS_TZl5uq4uv1LwgBD9Wddyac4atKqBiIWKIyeXse2s,2519
|
144
|
-
tico/serialize/operators/op_max_pool2d_with_indices.py,sha256=
|
146
|
+
tico/serialize/operators/op_max_pool2d_with_indices.py,sha256=Gd16ebLyo1x_gSXCvq-cBJEQ9jLTRLTd2zBXO7p3DvY,5724
|
145
147
|
tico/serialize/operators/op_maximum.py,sha256=JjBr6gWEnuakLuk1_feotTHfIIm3s5YqWmqhUMpSPI0,1873
|
146
148
|
tico/serialize/operators/op_mean.py,sha256=rVQZOxCJkHFY4kQBAS1HVK0HkcqxgkSy6zvEDLX_WYQ,2267
|
147
149
|
tico/serialize/operators/op_minimum.py,sha256=fASjQVcTPCin02umQwFPdq2ss-Ve7S5A33J3QmmQ_wQ,1873
|
@@ -178,7 +180,7 @@ tico/serialize/operators/op_view.py,sha256=5EMww-ve17Vm9XPuV03Tn7vJsjpU2J8U4d_FO
|
|
178
180
|
tico/serialize/operators/op_where.py,sha256=doE81GSwygrPBm3JIfN9w7kKXxeIYKxgk0eoY22QIcg,2845
|
179
181
|
tico/serialize/operators/utils.py,sha256=lXGpEJW1h8U_-gfc6EWjvvSiq3yJ9P-v1v3EMRT_pSk,2954
|
180
182
|
tico/utils/__init__.py,sha256=IO6FP_xYbGy0dW0HL26GXD3ouxARaxCK7bz9dn4blPQ,26
|
181
|
-
tico/utils/convert.py,sha256=
|
183
|
+
tico/utils/convert.py,sha256=gh_EcWwjZZ5IyQKtazfiZ1_FvAMXe0leu5nPN-0OcHg,11919
|
182
184
|
tico/utils/define.py,sha256=Ypgp7YffM4pgPl4Zh6TmogSn1OxGBMRw_e09qYGflZk,1467
|
183
185
|
tico/utils/diff_graph.py,sha256=_eDGGPDPYQD4b--MXX0DLoVgSt_wLfNPt47UlolLLR4,5272
|
184
186
|
tico/utils/errors.py,sha256=f3csJjgbXG9W1aHhqEcou008Aor19W57X8oT5Hx8w1M,954
|
@@ -191,14 +193,14 @@ tico/utils/register_custom_op.py,sha256=iRQvdqlBqrJxq_pNkvJyDIJD_SYtCUl88wwbbuvS
|
|
191
193
|
tico/utils/serialize.py,sha256=AQXMBOLu-Kg2Rn-qbqsAtHndjZAZIavlKA0QFgJREHM,1420
|
192
194
|
tico/utils/trace_decorators.py,sha256=ddLIiKQfSaQrxgF1kNpwjFTQnXENzeSfcr1kuAW4jGI,3221
|
193
195
|
tico/utils/utils.py,sha256=fnbZ2RLH6-J-wqb32O4qsR1ce4BJU0wYNrk84QXa6_E,13158
|
194
|
-
tico/utils/validate_args_kwargs.py,sha256=
|
196
|
+
tico/utils/validate_args_kwargs.py,sha256=vp1GaGhOWqQBD4axMPaULy0tWxoIDTwEqEYoR5S7ph0,25244
|
195
197
|
tico/utils/mx/__init__.py,sha256=IO6FP_xYbGy0dW0HL26GXD3ouxARaxCK7bz9dn4blPQ,26
|
196
198
|
tico/utils/mx/elemwise_ops.py,sha256=V6glyAHsVR1joqpsgnNytatCD_ew92xNWZ19UFDoMTA,10281
|
197
199
|
tico/utils/mx/formats.py,sha256=uzNWyu-1onUlwQfX5cZ6fZSUfHMRqorper7_T1k3jfk,3404
|
198
200
|
tico/utils/mx/mx_ops.py,sha256=RcfUTYVi-wilGB2sC35OeARdwDqnixv7dG5iyZ-fQT8,8555
|
199
|
-
tico-0.1.0.
|
200
|
-
tico-0.1.0.
|
201
|
-
tico-0.1.0.
|
202
|
-
tico-0.1.0.
|
203
|
-
tico-0.1.0.
|
204
|
-
tico-0.1.0.
|
201
|
+
tico-0.1.0.dev250619.dist-info/LICENSE,sha256=kp4JLII7bzRhPb0CPD5XTDZMh22BQ7h3k3B7t8TiSbw,12644
|
202
|
+
tico-0.1.0.dev250619.dist-info/METADATA,sha256=Ms7oDZDD9txOcAycr9TUsJIGoC_B5FmXyF-q2AfJu58,8846
|
203
|
+
tico-0.1.0.dev250619.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
204
|
+
tico-0.1.0.dev250619.dist-info/entry_points.txt,sha256=kBKYSS_IYrSXmUYevmmepqIVPScq5vF8ulQRu3I_Zf0,59
|
205
|
+
tico-0.1.0.dev250619.dist-info/top_level.txt,sha256=oqs7UPoNSKZEwqsX8B-KAWdQwfAa7i60pbxW_Jk7P3w,5
|
206
|
+
tico-0.1.0.dev250619.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|