Skip to content

Commit d1d5f40

Browse files
Jiseong-ohguochao-yangjingya-zhang
authored
Samsung Exynos AI LiteCore - Samsung Backend in test suite of ExecuTorch (pytorch#22583)
### Summary Release notes: TestSuite The Samsung Exynos backend in TestSuite of ExecuTorch can be verfied and it was passed Testsuite for E9955/E9965 SoCs. ### Test plan pytest -c /dev/nul backends/test/suite/operators/test_add.py -m backend_samsung -vs --html=./report/add_report.html pytest -c /dev/nul backends/test/suite/models/ -m backend_samsung --html=./report/samsung_models.html cc @SS-JIA @digantdesai @kimishpatel --------- Signed-off-by: Jiseong Oh <jiseong.oh@samsung.com> Signed-off-by: jiseong.oh <jiseong.oh@samsung.com> Co-authored-by: Guochao Yang <guochao.yang@samsung.com> Co-authored-by: Jingya Zhang <jingya.zhang@samsung.com>
1 parent 18c0803 commit d1d5f40

68 files changed

Lines changed: 475 additions & 121 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎backends/samsung/_passes/remove_useless_ops.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ class RemoveUselessOpPass(ExportPass):
1515
USELESS_OP_SET = {
1616
exir_ops.edge.aten._to_copy.default,
1717
exir_ops.edge.aten.clone.default,
18-
exir_ops.edge.aten.clone.default,
1918
exir_ops.edge.aten.alias.default,
2019
exir_ops.edge.aten.lift_fresh_copy.default,
2120
exir_ops.edge.dim_order_ops._to_dim_order_copy.default,

‎backends/samsung/_passes/replace_scalar_ops.py‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,16 @@ def call_operator(
3838
if op not in self._ops_with_scalar:
3939
return super().call_operator(op, args, kwargs, meta)
4040

41+
# For pow operation, convert int scalar to float32 tensor
42+
# because the PowVisitor requires both inputs to be float32
43+
if op == exir_ops.edge.aten.pow.Tensor_Scalar and isinstance(args[1], int):
44+
args1 = torch.tensor(float(args[1]), dtype=torch.float32)
45+
else:
46+
args1 = torch.tensor(args[1])
47+
4148
return super().call_operator(
4249
op=self._ops_with_scalar.get(op, op),
43-
args=(args[0], torch.tensor(args[1])),
50+
args=(args[0], args1),
4451
kwargs=kwargs,
4552
meta=meta,
4653
)

‎backends/samsung/builders/__init__.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
op_dequantize,
1919
op_div,
2020
op_embedding,
21+
op_exp,
2122
op_expand_copy,
2223
op_gelu,
2324
op_getitem,
@@ -48,6 +49,7 @@
4849
op_select,
4950
op_sigmoid,
5051
op_sin,
52+
op_skip,
5153
op_slice_copy,
5254
op_softmax,
5355
op_split_with_sizes_copy,
@@ -77,6 +79,7 @@
7779
op_dequantize,
7880
op_div,
7981
op_embedding,
82+
op_exp,
8083
op_expand_copy,
8184
op_gelu,
8285
op_getitem,
@@ -107,6 +110,7 @@
107110
op_select,
108111
op_sigmoid,
109112
op_sin,
113+
op_skip,
110114
op_slice_copy,
111115
op_softmax,
112116
op_split_with_sizes_copy,

‎backends/samsung/builders/node_visitor.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def __init__(self, exported_program: ExportedProgram) -> None:
3131
def exported_program(self) -> ExportedProgram:
3232
return self._exported_program
3333

34-
def define_node(self, node: torch.fx.Node, enn_graph: EnnGraph):
34+
def define_node(self, node: torch.fx.Node, enn_graph: EnnGraph) -> bool:
3535
raise NotImplementedError("NodeVisitor must be extended!")
3636

3737
def define_tensor(
@@ -58,7 +58,9 @@ def define_tensor(
5858
if is_param_node(self.exported_program, node):
5959
if swap_nc_for_weights:
6060
tensor = torch.swapdims(tensor, 0, 1)
61-
const_data = tensor.contiguous().detach().numpy()
61+
if not isinstance(tensor, torch._subclasses.fake_tensor.FakeTensor):
62+
# .numpy() is not supported for tensor subclasses if the tensor is a fake tensor.
63+
const_data = tensor.contiguous().detach().numpy()
6264

6365
dims = [1] if len(tensor.size()) == 0 else list(tensor.size())
6466

‎backends/samsung/builders/op_add.py‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# This source code is licensed under the BSD-style license found in the
55
# LICENSE file in the root directory of this source tree.
66

7+
import logging
78
from typing import Dict
89

910
import torch
@@ -26,16 +27,22 @@ def define_node(
2627
node: torch.fx.Node,
2728
enn_graph: EnnGraph,
2829
vals_to_ids: Dict[torch.Tensor, int],
29-
) -> None:
30+
) -> bool:
3031
input1 = node.args[0]
3132
input_id_1 = self.define_tensor(input1, enn_graph, vals_to_ids)
3233
params = {}
3334
self._update_params_qdtype(node, params)
3435
input2 = node.args[1]
3536
input_id_2 = self.define_tensor(input2, enn_graph, vals_to_ids)
37+
alpha = node.kwargs.get("alpha", 1.0)
38+
if alpha != 1.0:
39+
logging.warning("Currently, only alpha 1 for add is supported.")
40+
return False
3641

3742
output_id = self.define_tensor(node, enn_graph, vals_to_ids)
3843

3944
enn_graph.define_op(
4045
node.name, "ELTSUM", [input_id_1, input_id_2], [output_id], params
4146
)
47+
48+
return True

‎backends/samsung/builders/op_avg_pool2d.py‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def define_node(
2626
node: torch.fx.Node,
2727
enn_graph: EnnGraph,
2828
vals_to_ids: Dict[torch.Tensor, int],
29-
) -> None:
29+
) -> bool:
3030
input = node.args[0]
3131
input_id = self.define_tensor(input, enn_graph, vals_to_ids)
3232

@@ -52,10 +52,6 @@ def define_node(
5252
params["explicit_padding"] = explicit_padding
5353
self._update_params_qdtype(node, params)
5454

55-
if len(node.args) > 4:
56-
ceil_mode = cast(bool, node.args[4])
57-
assert not ceil_mode, "Not support ceil_mode = True."
58-
5955
if len(node.args) > 5:
6056
params["count_include_pad"] = cast(bool, node.args[5])
6157
else:
@@ -68,3 +64,5 @@ def define_node(
6864
), "Not supported divisor_override which is not equal to pooling region."
6965
output_id = self.define_tensor(node, enn_graph, vals_to_ids)
7066
enn_graph.define_op(node.name, "AVGPOOL2D", [input_id], [output_id], params)
67+
68+
return True

‎backends/samsung/builders/op_batch_norm.py‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,16 @@ def define_node(
2525
node: torch.fx.Node,
2626
enn_graph: EnnGraph,
2727
vals_to_ids: Dict[torch.Tensor, int],
28-
) -> None:
28+
) -> bool:
29+
index_zero_getitems = []
30+
for user in node.users.keys():
31+
if user.target.__name__ != "getitem":
32+
continue
33+
if user.args[1] == 0:
34+
index_zero_getitems.append(user)
35+
elif len(user.users) > 0:
36+
return False
37+
2938
all_input_tensors = []
3039
input = node.args[0]
3140
input_id = self.define_tensor(input, enn_graph, vals_to_ids)
@@ -51,6 +60,11 @@ def define_node(
5160

5261
output_id = self.define_tensor(node, enn_graph, vals_to_ids, output_idx=0)
5362

63+
for getitem in index_zero_getitems:
64+
vals_to_ids[getitem] = output_id
65+
5466
enn_graph.define_op(
5567
node.name, "BatchNormalization", all_input_tensors, [output_id], params
5668
)
69+
70+
return True

‎backends/samsung/builders/op_bmm.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def define_node(
2626
node: torch.fx.Node,
2727
enn_graph: EnnGraph,
2828
vals_to_ids: Dict[torch.Tensor, int],
29-
) -> None:
29+
) -> bool:
3030
input1 = node.args[0]
3131
input_id_1 = self.define_tensor(input1, enn_graph, vals_to_ids)
3232

@@ -41,3 +41,5 @@ def define_node(
4141
enn_graph.define_op(
4242
node.name, "BATCH_MATMUL", [input_id_1, input_id_2], [output_id], params
4343
)
44+
45+
return True

‎backends/samsung/builders/op_cat.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def define_node(
2828
node: torch.fx.Node,
2929
enn_graph: EnnGraph,
3030
vals_to_ids: Dict[torch.Tensor, int],
31-
) -> None:
31+
) -> bool:
3232
tensors = cast(List[torch.fx.Node], node.args[0])
3333
input_tensor_ids = []
3434
constant_idx = None
@@ -48,3 +48,5 @@ def define_node(
4848

4949
output_id = self.define_tensor(node, enn_graph, vals_to_ids)
5050
enn_graph.define_op(node.name, "CONCAT", input_tensor_ids, [output_id], params)
51+
52+
return True

‎backends/samsung/builders/op_clamp.py‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
# This source code is licensed under the BSD-style license found in the
55
# LICENSE file in the root directory of this source tree.
66

7+
import logging
78
from typing import cast, Dict
89

910
import torch
1011
from executorch.backends.samsung.builders.node_visitor import (
1112
NodeVisitor,
1213
register_node_visitor,
1314
)
15+
from executorch.backends.samsung.builders.utils import get_tensor
1416
from executorch.backends.samsung.serialization.enn_graph_schema import EnnGraph
1517

1618

@@ -26,9 +28,13 @@ def define_node(
2628
node: torch.fx.Node,
2729
enn_graph: EnnGraph,
2830
vals_to_ids: Dict[torch.Tensor, int],
29-
) -> None:
31+
) -> bool:
3032
input = node.args[0]
3133
input_id = self.define_tensor(input, enn_graph, vals_to_ids)
34+
input_tensor = get_tensor(self.exported_program, input)
35+
if input_tensor.dtype == torch.int64:
36+
logging.warning("Currently, int64 clip is unsupported!")
37+
return False
3238

3339
# The default value of lower bound and upper bound
3440
output_min = torch.finfo(torch.float32).min
@@ -45,3 +51,5 @@ def define_node(
4551
output_id = self.define_tensor(node, enn_graph, vals_to_ids)
4652

4753
enn_graph.define_op(node.name, "CLIP", [input_id], [output_id], params)
54+
55+
return True

0 commit comments

Comments
 (0)