Skip to content

Commit 72d3efe

Browse files
authored
[microNPU][2a] Add CascaderGraph for cascading analysis (#9469)
A CascaderGraph augments a TE graph with additional information needed by the cascading algorithms. This includes defining a strict ordering on the operators as well as including all the Propagators needed to do the affine analysis of cascades. The CascaderGraph consists of two object types, Parts and Tensors. A Part is an augmented operator which includes the Propagators and a Tensor is similar to a TE tensor but stores additional information like compression ratio.
1 parent 92eeef6 commit 72d3efe

File tree

11 files changed

+1101
-5
lines changed

11 files changed

+1101
-5
lines changed

cmake/modules/contrib/EthosU.cmake

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818
if(USE_ETHOSU)
1919
tvm_file_glob(GLOB COMPILER_ETHOSU_SRCS
2020
src/relay/backend/contrib/ethosu/*
21-
src/contrib/ethosu/cascader/*)
21+
src/contrib/ethosu/cascader/*
22+
src/contrib/ethosu/cascader/parts/*)
2223
list(APPEND COMPILER_SRCS ${COMPILER_ETHOSU_SRCS})
2324
else()
2425
# Keeping just utils.cc because it has Object definitions
2526
# used by python side
2627
tvm_file_glob(GLOB COMPILER_ETHOSU_SRCS
27-
src/relay/backend/contrib/ethosu/utils.cc)
28+
src/relay/backend/contrib/ethosu/utils.cc
29+
src/contrib/ethosu/cascader/*
30+
src/contrib/ethosu/cascader/parts/*)
2831
list(APPEND COMPILER_SRCS ${COMPILER_ETHOSU_SRCS})
2932
endif(USE_ETHOSU)

python/tvm/contrib/ethosu/cascader/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17-
"""The NPU cascading planner.
17+
"""The NPU cascader.
1818
1919
This component performs inter-operator scheduling to optimize
2020
for both performance and memory usage on Arm(R) Ethos(TM)-U NPUs.
2121
"""
2222
from .stripe_config import StripeConfig
2323
from .propagator import Propagator
24+
from .graph import PerformanceInfo, Tensor, Part, TESubgraph, CascaderGraph
25+
from .parts import InlinePart
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
"""Graph objects to define compute graphs for the NPU cascader."""
18+
from typing import List
19+
from collections import namedtuple
20+
import tvm._ffi
21+
22+
from tvm.runtime import Object
23+
24+
from .stripe_config import StripeConfig
25+
from . import _ffi_api
26+
27+
28+
TESubgraph = namedtuple("TESubgraph", ["input_tensors", "output_tensor"])
29+
30+
31+
@tvm._ffi.register_object("contrib.ethosu.cascader.PerformanceInfo")
32+
class PerformanceInfo(Object):
33+
"""PerformanceInfo class"""
34+
35+
@property
36+
def compute_cycles(self):
37+
return self._compute_cycles
38+
39+
@property
40+
def read_bytes(self):
41+
return list(self._read_bytes)
42+
43+
@property
44+
def write_bytes(self):
45+
return self._write_bytes
46+
47+
48+
@tvm._ffi.register_object("contrib.ethosu.cascader.Tensor")
49+
class Tensor(Object):
50+
"""Tensor class"""
51+
52+
def __init__(self, shape, dtype, is_constant=False, compression_ratio=1):
53+
self.__init_handle_by_constructor__(
54+
_ffi_api.Tensor, shape, dtype, is_constant, compression_ratio
55+
)
56+
57+
def add_producer(self, part):
58+
_ffi_api.TensorAddProducer(self, part)
59+
60+
def add_consumer(self, part):
61+
_ffi_api.TensorAddConsumer(self, part)
62+
63+
@property
64+
def producers(self):
65+
return list(self._producers)
66+
67+
@property
68+
def consumers(self):
69+
return list(self._consumers)
70+
71+
@property
72+
def shape(self):
73+
return list(self._shape)
74+
75+
@property
76+
def dtype(self):
77+
return self._dtype
78+
79+
@property
80+
def is_constant(self):
81+
return self._is_constant
82+
83+
@property
84+
def compression_ratio(self):
85+
return self._compression_ratio
86+
87+
@property
88+
def size(self):
89+
return self._size
90+
91+
92+
class Part(Object):
93+
"""Part base class"""
94+
95+
def set_input(self, index: int, tensor: Tensor):
96+
_ffi_api.PartSetInput(self, index, tensor)
97+
98+
def set_output(self, tensor: Tensor):
99+
_ffi_api.PartSetOutput(self, tensor)
100+
101+
def calculate_input_stripe_configs(
102+
self, output_stripe_config: StripeConfig
103+
) -> List[StripeConfig]:
104+
return list(_ffi_api.PartCalculateInputStripeConfigs(self, output_stripe_config))
105+
106+
def get_stripe_align_hint(self) -> List[int]:
107+
return list(_ffi_api.PartGetStripeAlignHint(self))
108+
109+
def get_performance_info(
110+
self, stripe_config: StripeConfig, is_rolling: bool
111+
) -> PerformanceInfo:
112+
return _ffi_api.PartGetPerformanceInfo(self, stripe_config, is_rolling)
113+
114+
@property
115+
def input_tensors(self):
116+
return list(self._input_tensors)
117+
118+
@property
119+
def output_tensor(self):
120+
return self._output_tensor
121+
122+
@property
123+
def propagators(self):
124+
return list(self._propagators)
125+
126+
@property
127+
def in_line(self):
128+
return self._in_line
129+
130+
@property
131+
def subgraph(self):
132+
return TESubgraph(list(self._te_input_tensors), self._te_output_tensor)
133+
134+
135+
@tvm._ffi.register_object("contrib.ethosu.cascader.CascaderGraph")
136+
class CascaderGraph(Object):
137+
"""A class to describe a graph of Parts and Tensors used by the cascader.
138+
139+
This class describes a graph consisting of two object types: Tensors and Parts.
140+
It defines a topological ordering on the graph such that each Part and Tensor has a
141+
position in the ordering. This ordering is used by the Plan and Proposal generation
142+
algorithms. It is also the ordering the Parts are expected to be executed in.
143+
144+
In addition to defining an ordering, the Parts and Tensors are also all given unique
145+
IDs which they can be referred to by."""
146+
147+
def __init__(self, input_tensors: List[Tensor], output_tensors: List[Tensor]):
148+
self.__init_handle_by_constructor__(_ffi_api.CascaderGraph, input_tensors, output_tensors)
149+
150+
def get_part_id(self, part: Part) -> int:
151+
return _ffi_api.CascaderGraphGetPartID(self, part)
152+
153+
def get_tensor_id(self, tensor: Tensor) -> int:
154+
return _ffi_api.CascaderGraphGetTensorID(self, tensor)
155+
156+
@property
157+
def input_tensors(self):
158+
return list(self._input_tensors)
159+
160+
@property
161+
def output_tensors(self):
162+
return list(self._output_tensors)
163+
164+
@property
165+
def tensor_order(self):
166+
return list(self._tensor_order)
167+
168+
@property
169+
def part_order(self):
170+
return list(self._part_order)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
"""Parts used by the NPU cascader."""
18+
from typing import List
19+
import tvm._ffi
20+
21+
from .propagator import Propagator
22+
from .graph import Part, TESubgraph
23+
from . import _ffi_api
24+
25+
26+
@tvm._ffi.register_object("contrib.ethosu.cascader.InlinePart")
27+
class InlinePart(Part):
28+
"""InlinePart class"""
29+
30+
def __init__(
31+
self,
32+
te_subgraph: TESubgraph,
33+
propagators: List[Propagator],
34+
):
35+
self.__init_handle_by_constructor__(
36+
_ffi_api.InlinePart,
37+
te_subgraph.input_tensors,
38+
te_subgraph.output_tensor,
39+
propagators,
40+
)

src/contrib/ethosu/cascader/common.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include <tvm/ir/expr.h>
2828
#include <tvm/runtime/container/array.h>
2929

30+
#include <functional>
31+
#include <numeric>
3032
#include <vector>
3133

3234
namespace tvm {
@@ -50,6 +52,22 @@ inline Array<Integer> make_array(const std::vector<int>& vec) {
5052
return arr;
5153
}
5254

55+
/*!
56+
* \brief Make a tvm::Array<Integer> from a size_t vector.
57+
* \param vec The size_t vector.
58+
* \return The Integer Array.
59+
* \note Array<Integer>(std::vector<size_t>) doesn't work as this implicit
60+
* type conversion fails. This is why this helper is required.
61+
*/
62+
inline Array<Integer> make_array(const std::vector<size_t>& vec) {
63+
Array<Integer> arr;
64+
arr.resize(vec.size());
65+
for (unsigned int i = 0; i < vec.size(); ++i) {
66+
arr.Set(i, Integer(vec[i]));
67+
}
68+
return arr;
69+
}
70+
5371
/*!
5472
* \brief Make a tvm::Array<FloatImm> from an float vector.
5573
* \param vec The float vector.
@@ -69,7 +87,7 @@ inline Array<FloatImm> make_array(const std::vector<float>& vec) {
6987
* \param arr The Array.
7088
* \return The vector.
7189
*/
72-
template <class T, class tvm_T>
90+
template <typename T, typename tvm_T>
7391
inline std::vector<T> make_vector(const Array<tvm_T>& arr) {
7492
std::vector<T> vec(arr.size());
7593
for (unsigned int i = 0; i < arr.size(); ++i) {
@@ -103,6 +121,11 @@ inline std::size_t hash_vector(const std::vector<T>& vec) {
103121
return seed;
104122
}
105123

124+
template <class T>
125+
inline T mul_reduce(const std::vector<T>& vec) {
126+
return std::accumulate(vec.begin(), vec.end(), 1, std::multiplies<T>());
127+
}
128+
106129
} // namespace cascader
107130
} // namespace ethosu
108131
} // namespace contrib

0 commit comments

Comments
 (0)