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 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.dev250617"
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
- maxpool_input = define_padding_node()
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tico
3
- Version: 0.1.0.dev250617
3
+ Version: 0.1.0.dev250619
4
4
  Summary: Convert exported Torch module to circle
5
5
  Home-page: UNKNOWN
6
6
  License: UNKNOWN
@@ -1,4 +1,4 @@
1
- tico/__init__.py,sha256=hljp9QJt0lsZ8rIFSeiTKhdyulprC_7xMjqxxA5qJ8U,1743
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/remove_weight_dequant_op.py,sha256=ZIwzuRXyCg6xN5pEUVV1LXsZpu0NkTcTUI6gc1VTuXs,6452
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=SPXIdlrYgJfR982il_ajokNehFYJWOmccUoksS_0qos,5665
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=nbpBJue9_ezb8Dj9L9dWcNeVlZd0soGJu_fvrL6-c5c,11810
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=ZX820o05hmzg3QmmduAy-rIOrDyPHYe6Uj6Yf6Hoe_c,25055
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.dev250617.dist-info/LICENSE,sha256=kp4JLII7bzRhPb0CPD5XTDZMh22BQ7h3k3B7t8TiSbw,12644
200
- tico-0.1.0.dev250617.dist-info/METADATA,sha256=u9zQXsDpGwxI1Q2-6raMnRuzqsI0PIDGLjmq0mV3HjM,8846
201
- tico-0.1.0.dev250617.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
202
- tico-0.1.0.dev250617.dist-info/entry_points.txt,sha256=kBKYSS_IYrSXmUYevmmepqIVPScq5vF8ulQRu3I_Zf0,59
203
- tico-0.1.0.dev250617.dist-info/top_level.txt,sha256=oqs7UPoNSKZEwqsX8B-KAWdQwfAa7i60pbxW_Jk7P3w,5
204
- tico-0.1.0.dev250617.dist-info/RECORD,,
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,,