Skip to content

Commit 34d2561

Browse files
mbaretylc
authored andcommitted
[microNPU][1] Add affine analysis structures for the cascader (apache#9458)
* [ETHOSU][1] Add affine analysis structures for the cascader The cascader relies heavily on being able to determine data dependencies between operators. This is so that it can calculate how stripes should be propagated through a cascade. To do this, two data structures are defined: StripeConfig and Propagator. StripeConfig stores information for how a tensor should be broken up into stripes and executed. Propagator transforms a StripeConfig using an affine transform matrix, allowing an input StripeConfig for an operator to be determined by 'propagating' the output StripeConfig. By chaining together Propagators, we can analyse how data dependencies vary throughout a cascade and therefore calculate the memory requirements (and approximate the performance). Change-Id: If7176fea961c631be4a6c195303da536030d957b * Add test guards Change-Id: I1d7633e20daab33642fa5c4a12e474a4def4d8b8 * Address review comments Change-Id: Iff5f1effa08e0628de91f5577487d0cecebec824 * Improve docs Change-Id: I508809d8c1a08d231e3a9b0fd9b3f2639cc2f0e3
1 parent 8763e3a commit 34d2561

File tree

14 files changed

+1364
-2
lines changed

14 files changed

+1364
-2
lines changed

cmake/modules/contrib/EthosU.cmake

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
# under the License.
1717

1818
if(USE_ETHOSU)
19-
file(GLOB ETHOSU_RELAY_CONTRIB_SRC src/relay/backend/contrib/ethosu/*)
20-
list(APPEND COMPILER_SRCS ${ETHOSU_RELAY_CONTRIB_SRC})
19+
file(GLOB COMPILER_ETHOSU_SRCS
20+
CONFIGURE_DEPENDS src/relay/backend/contrib/ethosu/*
21+
CONFIGURE_DEPENDS src/contrib/ethosu/cascader/*)
22+
list(APPEND COMPILER_SRCS ${COMPILER_ETHOSU_SRCS})
2123
endif(USE_ETHOSU)

python/tvm/contrib/ethosu/__init__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
"""Namespace for Arm(R) Ethos(TM)-U NPU contrib functionality"""
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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+
"""The NPU cascading planner.
18+
19+
This component performs inter-operator scheduling to optimize
20+
for both performance and memory usage on Arm(R) Ethos(TM)-U NPUs.
21+
"""
22+
from .stripe_config import StripeConfig
23+
from .propagator import Propagator
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
"""FFI APIs for the NPU cascader."""
18+
import tvm._ffi
19+
20+
21+
tvm._ffi._init_api("contrib.ethosu.cascader", __name__)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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+
"""Propagator class."""
18+
# pylint: disable=invalid-name
19+
import tvm._ffi
20+
21+
from tvm.runtime import Object
22+
23+
from . import _ffi_api
24+
25+
26+
@tvm._ffi.register_object("contrib.ethosu.cascader.Propagator")
27+
class Propagator(Object):
28+
"""Propagator class"""
29+
30+
def __init__(self, transform, offset):
31+
float_transform = list([list(float(v) for v in row) for row in transform])
32+
self.__init_handle_by_constructor__(_ffi_api.Propagator, float_transform, offset)
33+
34+
def propagate(self, stripe_config):
35+
return _ffi_api.PropagatorPropagate(self, stripe_config)
36+
37+
@property
38+
def transform(self):
39+
"""Get the transform matrix"""
40+
new_matrix = []
41+
for row in self._transform:
42+
new_row = []
43+
for v in row:
44+
new_row.append(v.value)
45+
46+
new_matrix.append(new_row)
47+
48+
return new_matrix
49+
50+
@property
51+
def offset(self):
52+
"""Get the offset matrix"""
53+
new_vec = []
54+
for v in self._offset:
55+
new_vec.append(v.value)
56+
57+
return new_vec
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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+
"""Stripe config class to hold tensor striping information."""
18+
# pylint: disable=invalid-name
19+
import tvm._ffi
20+
21+
from tvm.runtime import Object
22+
23+
from . import _ffi_api
24+
25+
26+
@tvm._ffi.register_object("contrib.ethosu.cascader.StripeConfig")
27+
class StripeConfig(Object):
28+
"""StripeConfig class"""
29+
30+
def __init__(self, shape, extent, strides, order, stripes, offset):
31+
strides = list([float(v) for v in strides])
32+
self.__init_handle_by_constructor__(
33+
_ffi_api.StripeConfig, shape, extent, strides, order, stripes, offset
34+
)
35+
36+
@property
37+
def shape(self):
38+
return list(self._shape)
39+
40+
@property
41+
def extent(self):
42+
return list(self._extent)
43+
44+
@property
45+
def strides(self):
46+
return list([float(v.value) for v in self._strides])
47+
48+
@property
49+
def order(self):
50+
return list(self._order)
51+
52+
@property
53+
def stripes(self):
54+
return list(self._stripes)
55+
56+
@property
57+
def offset(self):
58+
return list(self._offset)
59+
60+
def __hash__(self):
61+
return self._hash
62+
63+
def __eq__(self, other):
64+
return _ffi_api.StripeConfigEqual(self, other)
65+
66+
def __repr__(self):
67+
return (
68+
f"StripeConfig(shape={self.shape}, "
69+
f"extent={self.extent}, "
70+
f"strides={self.strides}, "
71+
f"order={self.order}, "
72+
f"stripes={self.stripes}, "
73+
f"offset={self.offset}"
74+
)
75+
76+
77+
def count_stripes(stripe_config: StripeConfig, enable_sliding_window: bool = False):
78+
stripe_counts = dict(_ffi_api.CountStripes(stripe_config, enable_sliding_window))
79+
# Some code to 'de-TVM' the data types and make them pure Python
80+
clean_stripe_counts = dict()
81+
for stripe, count in stripe_counts.items():
82+
clean_stripe = tuple([int(v) for v in stripe])
83+
clean_count = int(count)
84+
clean_stripe_counts[clean_stripe] = clean_count
85+
86+
return clean_stripe_counts

src/contrib/ethosu/cascader/common.h

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
/*!
21+
* \file src/contrib/ethosu/cascader/common.h
22+
* \brief Common functions used in the NPU cascader
23+
*/
24+
#ifndef TVM_CONTRIB_ETHOSU_CASCADER_COMMON_H_
25+
#define TVM_CONTRIB_ETHOSU_CASCADER_COMMON_H_
26+
27+
#include <tvm/ir/expr.h>
28+
#include <tvm/runtime/container/array.h>
29+
30+
#include <vector>
31+
32+
namespace tvm {
33+
namespace contrib {
34+
namespace ethosu {
35+
namespace cascader {
36+
37+
/*!
38+
* \brief Make a tvm::Array<Integer> from an int vector.
39+
* \param vec The int vector.
40+
* \return The Integer Array.
41+
* \note Array<Integer>(std::vector<int>) doesn't work as this implicit
42+
* type conversion fails. This is why this helper is required.
43+
*/
44+
inline Array<Integer> make_array(const std::vector<int>& vec) {
45+
Array<Integer> arr;
46+
arr.resize(vec.size());
47+
for (unsigned int i = 0; i < vec.size(); ++i) {
48+
arr.Set(i, Integer(vec[i]));
49+
}
50+
return arr;
51+
}
52+
53+
/*!
54+
* \brief Make a tvm::Array<FloatImm> from an float vector.
55+
* \param vec The float vector.
56+
* \return The FloatImm Array.
57+
*/
58+
inline Array<FloatImm> make_array(const std::vector<float>& vec) {
59+
Array<FloatImm> arr;
60+
arr.resize(vec.size());
61+
for (unsigned int i = 0; i < vec.size(); ++i) {
62+
arr.Set(i, FloatImm(DataType::Float(32), static_cast<double>(vec[i])));
63+
}
64+
return arr;
65+
}
66+
67+
/*!
68+
* \brief Make a vector from a tvm::Array.
69+
* \param arr The Array.
70+
* \return The vector.
71+
*/
72+
template <class T, class tvm_T>
73+
inline std::vector<T> make_vector(const Array<tvm_T>& arr) {
74+
std::vector<T> vec(arr.size());
75+
for (unsigned int i = 0; i < arr.size(); ++i) {
76+
vec[i] = arr[i]->value;
77+
}
78+
return vec;
79+
}
80+
81+
/*!
82+
* \brief Create a combined hash.
83+
* \param seed The current hash value.
84+
* \param v The value to combine into the hash.
85+
* \return The combined hash.
86+
*/
87+
template <class T>
88+
inline void hash_combine(std::size_t* seed, T const& v) {
89+
*seed ^= std::hash<T>()(v) + 0x9e3779b9 + (*seed << 6) + (*seed >> 2);
90+
}
91+
92+
/*!
93+
* \brief Hash a vector.
94+
* \param vec The vector to hash.
95+
* \return The hash.
96+
*/
97+
template <class T>
98+
inline std::size_t hash_vector(const std::vector<T>& vec) {
99+
std::size_t seed = vec.size();
100+
for (const auto& elem : vec) {
101+
hash_combine(&seed, elem);
102+
}
103+
return seed;
104+
}
105+
106+
} // namespace cascader
107+
} // namespace ethosu
108+
} // namespace contrib
109+
} // namespace tvm
110+
111+
#endif // TVM_CONTRIB_ETHOSU_CASCADER_COMMON_H_

0 commit comments

Comments
 (0)