Skip to content

Commit 522764b

Browse files
mbaretjacobbohlin
authored andcommitted
[microNPU][3] Plan generation for the cascader
The cascader creates 'Plans' which describe how to schedule subgraphs. As part of the cascading algorithm, it's necessary to explore a large variety of Plans which are Pareto optimal (in terms of memory usage and performance). This is done by the Plan generation algorithm. This commit adds the TensorConfig and Plan data structures which hold information on how to schedule the tensors/operators. Additionally, it includes functions to calculate Pareto frontiers which are used to cull sub-optimal Plans. Change-Id: Ia358b2a1b29bd810df4441027752ced75812ad4e
1 parent cbc1c77 commit 522764b

File tree

22 files changed

+2810
-0
lines changed

22 files changed

+2810
-0
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@
3434
)
3535
from .parts import InlinePart, EthosuPart
3636
from .device_config import EthosuDeviceConfig
37+
from .tensor_config import TensorConfigState, MemoryRegion, TensorConfig
38+
from .plan import Plan
39+
from .cascader_options import CascaderOptions
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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+
"""Object to hold options for the NPU cascader"""
18+
import tvm._ffi
19+
20+
from tvm.runtime import Object
21+
22+
from . import _ffi_api
23+
from .tensor_config import MemoryRegion
24+
25+
26+
@tvm._ffi.register_object("contrib.ethosu.cascader.CascaderOptions")
27+
class CascaderOptions(Object):
28+
"""A class to hold configuration options for the cascader."""
29+
30+
def __init__(
31+
self,
32+
cascade_region: MemoryRegion,
33+
max_proposals: int,
34+
stripe_factors: int,
35+
max_plan_size: int,
36+
always_copy_size: int,
37+
):
38+
self.__init_handle_by_constructor__(
39+
_ffi_api.CascaderOptions,
40+
cascade_region,
41+
max_proposals,
42+
stripe_factors,
43+
max_plan_size,
44+
always_copy_size,
45+
)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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+
"""Pareto optimisation functions for the NPU cascader."""
18+
from typing import List
19+
20+
from tvm import Object
21+
22+
from . import _ffi_api
23+
from .plan import Plan
24+
25+
26+
def get_pareto_frontier(costs: List[List[float]]) -> List[bool]:
27+
for i, cost in enumerate(costs):
28+
for j, value in enumerate(cost):
29+
costs[i][j] = float(value)
30+
31+
return [bool(v) for v in _ffi_api.GetParetoFrontier(costs)]
32+
33+
34+
def thin_vector(vec: List[Object], max_size: int) -> List[Object]:
35+
return list(_ffi_api.ThinVector(vec, max_size))
36+
37+
38+
def pareto_cull_plans(plans: List[Plan], max_plans: int) -> List[Plan]:
39+
return list(_ffi_api.ParetoCullPlans(plans, max_plans))
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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+
"""Plan class to hold subgraph scheduling information."""
18+
from typing import Dict, FrozenSet
19+
import tvm._ffi
20+
21+
from tvm.runtime import Object
22+
23+
from . import _ffi_api
24+
from .graph import Tensor, Part
25+
from .tensor_config import TensorConfig, MemoryRegion
26+
27+
28+
@tvm._ffi.register_object("contrib.ethosu.cascader.Plan")
29+
class Plan(Object):
30+
"""Plan class"""
31+
32+
def __init__(
33+
self,
34+
tensor_configs: Dict[Tensor, TensorConfig],
35+
open_configs: FrozenSet[TensorConfig],
36+
output_config: TensorConfig,
37+
part_group: FrozenSet[Part],
38+
interior_region: MemoryRegion,
39+
memory_usage: int,
40+
cycles: int,
41+
):
42+
self.__init_handle_by_constructor__(
43+
_ffi_api.Plan,
44+
list(tensor_configs.values()),
45+
list(open_configs),
46+
output_config,
47+
list(part_group),
48+
interior_region,
49+
memory_usage,
50+
cycles,
51+
)
52+
53+
def merge(self, other):
54+
return _ffi_api.PlanMerge(self, other)
55+
56+
def benchmark_merge(self, other, repeats):
57+
return _ffi_api.PlanMergeBenchmark(self, other, repeats)
58+
59+
@property
60+
def tensor_configs(self):
61+
tensor_configs = {}
62+
for config in self._tensor_configs:
63+
tensor_configs[config.tensor] = config
64+
return tensor_configs
65+
66+
@property
67+
def open_configs(self):
68+
return frozenset(self._open_configs)
69+
70+
@property
71+
def output_config(self):
72+
return self._output_config
73+
74+
@property
75+
def part_group(self):
76+
return frozenset(self._part_group)
77+
78+
@property
79+
def interior_region(self):
80+
return self._interior_region
81+
82+
@property
83+
def memory_usage(self):
84+
return self._memory_usage
85+
86+
@property
87+
def cycles(self):
88+
return self._cycles
89+
90+
def __repr__(self):
91+
return (
92+
f"Plan(tensor_configs={self.tensor_configs}, "
93+
f"open_configs={self.open_configs}, "
94+
f"output_config={self.output_config}, "
95+
f"part_group={self.part_group}, "
96+
f"interior_region={self.interior_region.name}, "
97+
f"memory_usage={self.memory_usage}, "
98+
f"cycles={self.cycles}, "
99+
)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
"""Algorithms to generate Plans for a CascaderGraph."""
18+
from typing import List, Dict
19+
20+
from tvm.contrib.ethosu.cascader.tensor_config import MemoryRegion
21+
22+
from . import _ffi_api
23+
from .cascader_options import CascaderOptions
24+
from .plan import Plan
25+
from .stripe_config import StripeConfig
26+
from .graph import CascaderGraph, Part, Tensor
27+
28+
29+
def generate_output_stripe_configs(part: Part, stripe_factors: int) -> List[StripeConfig]:
30+
return list(_ffi_api.GenerateOutputStripeConfigs(part, stripe_factors))
31+
32+
33+
def generate_single_plans(
34+
part: Part,
35+
output_stripe_configs: List[StripeConfig],
36+
home_map: Dict[Tensor, List[MemoryRegion]],
37+
cascade_region: MemoryRegion,
38+
) -> List[Plan]:
39+
return list(_ffi_api.GenerateSinglePlans(part, output_stripe_configs, home_map, cascade_region))
40+
41+
42+
def generate_graph_plans(
43+
graph: CascaderGraph,
44+
home_map: Dict[Tensor, List[MemoryRegion]],
45+
options: CascaderOptions,
46+
):
47+
return _ffi_api.GenerateGraphPlans(
48+
graph,
49+
home_map,
50+
options,
51+
)
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
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+
"""Tensor config class to hold tensor scheduling information."""
18+
from typing import List, Union
19+
from enum import IntEnum
20+
import tvm._ffi
21+
from tvm.contrib.ethosu.cascader.stripe_config import StripeConfig
22+
23+
from tvm.runtime import Object
24+
25+
from . import _ffi_api
26+
from .stripe_config import StripeConfig
27+
from .graph import Tensor, BufferMode
28+
29+
30+
class TensorConfigState(IntEnum):
31+
BOUNDARY = 0
32+
INTERIOR = 1
33+
34+
35+
@tvm._ffi.register_object("contrib.ethosu.cascader.MemoryRegion")
36+
class MemoryRegion(Object):
37+
"""MemoryRegion class"""
38+
39+
def __init__(self, name: str, size: int, read_bandwidth: int, write_bandwidth: int):
40+
self.__init_handle_by_constructor__(
41+
_ffi_api.MemoryRegion, name, size, read_bandwidth, write_bandwidth
42+
)
43+
44+
45+
@tvm._ffi.register_object("contrib.ethosu.cascader.TensorConfig")
46+
class TensorConfig(Object):
47+
"""TensorConfig class"""
48+
49+
def __init__(
50+
self,
51+
tensor: Tensor,
52+
home_region: MemoryRegion,
53+
state: TensorConfigState,
54+
buffer_mode: BufferMode,
55+
stripe_configs: List[StripeConfig],
56+
copy_tensor: bool = False,
57+
copy_region: Union[MemoryRegion, None] = None,
58+
):
59+
if copy_region is None:
60+
copy_region = home_region
61+
self.__init_handle_by_constructor__(
62+
_ffi_api.TensorConfig,
63+
tensor,
64+
home_region,
65+
state,
66+
buffer_mode,
67+
stripe_configs,
68+
copy_tensor,
69+
copy_region,
70+
)
71+
72+
def get_buffer_size(self):
73+
return _ffi_api.TensorConfigGetBufferSize(self)
74+
75+
@property
76+
def tensor(self):
77+
return self._tensor
78+
79+
@property
80+
def home_region(self):
81+
return self._home_region
82+
83+
@property
84+
def state(self):
85+
return TensorConfigState(self._state)
86+
87+
@property
88+
def buffer_mode(self):
89+
return BufferMode(self._buffer_mode)
90+
91+
@property
92+
def stripe_configs(self):
93+
return list(self._stripe_configs)
94+
95+
@property
96+
def copy_tensor(self):
97+
return bool(self._copy_tensor)
98+
99+
@property
100+
def copy_region(self):
101+
return self._copy_region
102+
103+
def __hash__(self):
104+
return self._hash
105+
106+
def __eq__(self, other):
107+
return _ffi_api.TensorConfigEqual(self, other)
108+
109+
def __repr__(self):
110+
return (
111+
f"TensorConfig(tensor={self.tensor}, "
112+
f"home_region={self.home_region.name}, "
113+
f"state={self.state.name}, "
114+
f"buffer_mode={self.buffer_mode.name}, "
115+
f"stripe_configs={self.stripe_configs}, "
116+
f"copy_tensor={self.copy_tensor}, "
117+
f"copy_region={self.copy_region.name}"
118+
)

0 commit comments

Comments
 (0)