-
Notifications
You must be signed in to change notification settings - Fork 524
/
Copy pathpartitioner.py
148 lines (122 loc) · 5.24 KB
/
partitioner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# Copyright (c) Intel Corporation
#
# Licensed under the BSD License (the "License"); you may not use this file
# except in compliance with the License. See the license file found in the
# LICENSE file in the root directory of this source tree.
# mypy: disable-error-code=import-not-found
from typing import Callable, final, List, Optional, Tuple
import torch
from executorch.backends.openvino.preprocess import OpenvinoBackend
from executorch.exir.backend.backend_details import CompileSpec
from executorch.exir.backend.partitioner import (
DelegationSpec,
Partitioner,
PartitionResult,
)
from executorch.exir.backend.utils import tag_constant_data
from openvino.frontend.pytorch.torchdynamo.op_support import ( # type: ignore[import-untyped]
OperatorSupport,
)
from torch.export.exported_program import ExportedProgram
from torch.fx.passes.infra.partitioner import CapabilityBasedPartitioner
from torch.fx.passes.operator_support import OperatorSupportBase
class OpenvinoOperatorsSupport(OperatorSupportBase):
def __init__(
self,
op_types_to_skip: Optional[set] = None,
op_names_to_skip: Optional[set] = None,
) -> None:
"""
Initializes the OpenvinoOperatorsSupport class.
:param op_types_to_skip: A set of operator types to skip during support checking.
:param op_names_to_skip: A set of operator names to skip during support checking.
"""
if op_types_to_skip is None:
op_types_to_skip = set()
if op_names_to_skip is None:
op_names_to_skip = set()
self._op_types_to_skip = op_types_to_skip
self._op_names_to_skip = op_names_to_skip
def is_node_supported(self, _, node: torch.fx.Node) -> bool:
"""
Checks if a given node is supported by OpenVINO.
:param node: The FX graph node representing an operation.
:return: True if the node is supported, otherwise False.
"""
if node.op != "call_function":
return False
options: list[str] = []
if not isinstance(node.target, str):
op_type = node.target.__name__
else:
op_type = str(node.target)
supported_ops = OperatorSupport(options)._support_dict
if op_type == "getitem":
return True
if "torch.ops." + str(op_type) in supported_ops:
return True
else:
print("Op not supported: ", "torch.ops." + str(op_type))
if op_type in self._op_types_to_skip or node.name in self._op_names_to_skip:
print(
f"[OpenVINO Backend] The {op_type} operator with name '{node.name}' is skipped."
)
return False
return False
@final
class OpenvinoPartitioner(Partitioner):
def __init__(
self,
compile_spec: List[CompileSpec],
op_types_to_skip: Optional[set] = None,
op_names_to_skip: Optional[set] = None,
) -> None:
"""
Initializes the OpenvinoPartitioner class.
:param compile_spec: A list of compile specifications for OpenVINO.
:param op_types_to_skip: A set of operator types to skip during partitioning.
:param op_names_to_skip: A set of operator names to skip during partitioning.
"""
self.delegation_spec = DelegationSpec(OpenvinoBackend.__name__, compile_spec)
self._op_types_to_skip = op_types_to_skip
self._op_names_to_skip = op_names_to_skip
def ops_to_not_decompose(
self,
ep: ExportedProgram,
) -> Tuple[List[torch._ops.OpOverload], Optional[Callable[[torch.fx.Node], bool]]]:
"""
Returns a tuple containing a list of operations that should not be decomposed
and an optional function to filter nodes.
:param ep: The exported program.
:return: A tuple consisting of a list of ops to keep and an optional filtering function.
"""
ops_not_decompose = [
torch.ops.aten.pixel_shuffle.default,
torch.ops.aten.upsample_bilinear2d.default,
torch.ops.aten.upsample_bilinear2d.vec,
torch.ops.aten.upsample_nearest2d.default,
torch.ops.aten.upsample_nearest2d.vec,
]
return (ops_not_decompose, None)
def partition(self, exported_program: ExportedProgram) -> PartitionResult:
"""
Partitions an exported program into supported and unsupported segments.
:param exported_program: The exported program.
:return: A PartitionResult containing the partitioned graph and delegation tags.
"""
partitioner = CapabilityBasedPartitioner(
exported_program.graph_module,
OpenvinoOperatorsSupport(self._op_types_to_skip, self._op_names_to_skip),
allows_single_node_partition=True,
)
partition_list = partitioner.propose_partitions()
partition_tags = {}
for partition in partition_list:
for node in partition.nodes:
tag = f"tag{partition.id}"
node.meta["delegation_tag"] = tag
partition_tags[tag] = self.delegation_spec
tag_constant_data(exported_program)
return PartitionResult(
tagged_exported_program=exported_program, partition_tags=partition_tags
)