blob: e706fc81575b7eb0b612051f922e64c735c9b968 [file] [log] [blame]
Matteo Martincigh88054f82019-05-17 12:15:30 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "MockBackend.hpp"
7#include "MockBackendId.hpp"
8
Matteo Martincighc601aa62019-10-29 15:03:22 +00009#include <armnn/BackendRegistry.hpp>
10
Matteo Martincighe5b8eb92019-11-28 15:45:42 +000011#include <armnn/backends/IBackendContext.hpp>
12#include <armnn/backends/IMemoryManager.hpp>
Matteo Martincigh88054f82019-05-17 12:15:30 +010013
14#include <Optimizer.hpp>
15#include <SubgraphViewSelector.hpp>
16
Matteo Martincigh88054f82019-05-17 12:15:30 +010017#include <algorithm>
18
19namespace
20{
21
22bool IsLayerSupported(const armnn::Layer* layer)
23{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010024 ARMNN_ASSERT(layer != nullptr);
Matteo Martincigh88054f82019-05-17 12:15:30 +010025
26 armnn::LayerType layerType = layer->GetType();
27 switch (layerType)
28 {
29 case armnn::LayerType::Input:
30 case armnn::LayerType::Output:
Matteo Martincighf02e6cd2019-05-17 12:15:30 +010031 case armnn::LayerType::Addition:
Matteo Martincigh88054f82019-05-17 12:15:30 +010032 case armnn::LayerType::Convolution2d:
33 // Layer supported
34 return true;
35 default:
36 // Layer unsupported
37 return false;
38 }
39}
40
41bool IsLayerSupported(const armnn::Layer& layer)
42{
43 return IsLayerSupported(&layer);
44}
45
46bool IsLayerOptimizable(const armnn::Layer* layer)
47{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010048 ARMNN_ASSERT(layer != nullptr);
Matteo Martincigh88054f82019-05-17 12:15:30 +010049
50 // A Layer is not optimizable if its name contains "unoptimizable"
51 const std::string layerName(layer->GetName());
52 bool optimizable = layerName.find("unoptimizable") == std::string::npos;
53
54 return optimizable;
55}
56
57bool IsLayerOptimizable(const armnn::Layer& layer)
58{
59 return IsLayerOptimizable(&layer);
60}
61
62} // Anonymous namespace
63
64namespace armnn
65{
66
David Monahanc1536d62020-02-12 15:52:35 +000067MockBackendInitialiser::MockBackendInitialiser()
Matteo Martincigh88054f82019-05-17 12:15:30 +010068{
David Monahanc1536d62020-02-12 15:52:35 +000069 BackendRegistryInstance().Register(MockBackend::GetIdStatic(),
70 []()
71 {
72 return IBackendInternalUniquePtr(new MockBackend);
73 });
74}
Matteo Martincigh88054f82019-05-17 12:15:30 +010075
David Monahanc1536d62020-02-12 15:52:35 +000076MockBackendInitialiser::~MockBackendInitialiser()
Matteo Martincigh88054f82019-05-17 12:15:30 +010077{
David Monahanc1536d62020-02-12 15:52:35 +000078 try
Matteo Martincigh88054f82019-05-17 12:15:30 +010079 {
David Monahanc1536d62020-02-12 15:52:35 +000080 BackendRegistryInstance().Deregister(MockBackend::GetIdStatic());
Matteo Martincigh88054f82019-05-17 12:15:30 +010081 }
David Monahanc1536d62020-02-12 15:52:35 +000082 catch (...)
83 {
84 std::cerr << "could not deregister mock backend" << std::endl;
85 }
Matteo Martincigh88054f82019-05-17 12:15:30 +010086}
87
88const BackendId& MockBackend::GetIdStatic()
89{
90 static const BackendId s_Id{MockBackendId()};
91 return s_Id;
92}
93
94IBackendInternal::IWorkloadFactoryPtr MockBackend::CreateWorkloadFactory(
Derek Lamberti901ea112019-12-10 22:07:09 +000095 const IBackendInternal::IMemoryManagerSharedPtr& /*memoryManager*/) const
Matteo Martincigh88054f82019-05-17 12:15:30 +010096{
97 return IWorkloadFactoryPtr{};
98}
99
100IBackendInternal::IBackendContextPtr MockBackend::CreateBackendContext(const IRuntime::CreationOptions&) const
101{
102 return IBackendContextPtr{};
103}
104
Colm Donelane49755b2020-01-29 15:22:43 +0000105IBackendInternal::IBackendProfilingContextPtr MockBackend::CreateBackendProfilingContext(
David Monahanc1536d62020-02-12 15:52:35 +0000106 const IRuntime::CreationOptions& options, IBackendProfilingPtr& backendProfiling)
Colm Donelane49755b2020-01-29 15:22:43 +0000107{
Jan Eilers8eb25602020-03-09 12:13:48 +0000108 IgnoreUnused(options);
Colm Donelanfcb802b2020-02-13 20:47:08 +0000109 std::shared_ptr<armnn::MockBackendProfilingContext> context =
110 std::make_shared<MockBackendProfilingContext>(backendProfiling);
David Monahanc1536d62020-02-12 15:52:35 +0000111 MockBackendProfilingService::Instance().SetProfilingContextPtr(context);
112 return context;
Colm Donelane49755b2020-01-29 15:22:43 +0000113}
114
Matteo Martincigh88054f82019-05-17 12:15:30 +0100115IBackendInternal::IMemoryManagerUniquePtr MockBackend::CreateMemoryManager() const
116{
117 return IMemoryManagerUniquePtr{};
118}
119
120IBackendInternal::Optimizations MockBackend::GetOptimizations() const
121{
122 return Optimizations{};
123}
124
125IBackendInternal::ILayerSupportSharedPtr MockBackend::GetLayerSupport() const
126{
David Monahan7f2c35a2019-05-24 10:46:28 +0100127 static ILayerSupportSharedPtr layerSupport{new MockLayerSupport};
128 return layerSupport;
Matteo Martincigh88054f82019-05-17 12:15:30 +0100129}
130
131OptimizationViews MockBackend::OptimizeSubgraphView(const SubgraphView& subgraph) const
132{
133 // Prepare the optimization views
134 OptimizationViews optimizationViews;
135
136 // Get the layers of the input sub-graph
137 const SubgraphView::Layers& subgraphLayers = subgraph.GetLayers();
138
139 // Parse the layers
140 SubgraphView::Layers supportedLayers;
141 SubgraphView::Layers unsupportedLayers;
142 SubgraphView::Layers untouchedLayers;
143 std::for_each(subgraphLayers.begin(),
144 subgraphLayers.end(),
145 [&](Layer* layer)
146 {
147 bool supported = IsLayerSupported(layer);
148 if (supported)
149 {
150 // Layer supported, check if it's optimizable
151 bool optimizable = IsLayerOptimizable(layer);
152 if (optimizable)
153 {
154 // Layer fully supported
155 supportedLayers.push_back(layer);
156 }
157 else
158 {
159 // Layer supported but not optimizable
160 untouchedLayers.push_back(layer);
161 }
162 }
163 else
164 {
165 // Layer unsupported
166 unsupportedLayers.push_back(layer);
167 }
168 });
169
170 // Check if there are supported layers
171 if (!supportedLayers.empty())
172 {
173 // Select the layers that are neither inputs or outputs, but that are optimizable
174 auto supportedSubgraphSelector = [](const Layer& layer)
175 {
176 return layer.GetType() != LayerType::Input &&
177 layer.GetType() != LayerType::Output &&
178 IsLayerSupported(layer) &&
179 IsLayerOptimizable(layer);
180 };
181
182 // Apply the subgraph selector to the supported layers to group them into sub-graphs were appropriate
183 SubgraphView mutableSubgraph(subgraph);
184 SubgraphViewSelector::Subgraphs supportedSubgraphs =
185 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, supportedSubgraphSelector);
186
187 // Create a substitution pair for each supported sub-graph
188 std::for_each(supportedSubgraphs.begin(),
189 supportedSubgraphs.end(),
190 [&optimizationViews](const SubgraphView::SubgraphViewPtr& supportedSubgraph)
191 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100192 ARMNN_ASSERT(supportedSubgraph != nullptr);
Matteo Martincigh88054f82019-05-17 12:15:30 +0100193
194 PreCompiledLayer* preCompiledLayer =
195 optimizationViews.GetGraph().AddLayer<PreCompiledLayer>(
196 PreCompiledDescriptor(supportedSubgraph->GetNumInputSlots(),
197 supportedSubgraph->GetNumOutputSlots()),
198 "pre-compiled");
199 preCompiledLayer->SetBackendId(MockBackendId());
200
201 SubgraphView substitutionSubgraph(*supportedSubgraph);
202 SubgraphView replacementSubgraph(preCompiledLayer);
203
204 optimizationViews.AddSubstitution({ substitutionSubgraph, replacementSubgraph });
205 });
206 }
207
208 // Check if there are unsupported layers
209 if (!unsupportedLayers.empty())
210 {
211 // Select the layers that are neither inputs or outputs, and are not optimizable
212 auto unsupportedSubgraphSelector = [](const Layer& layer)
213 {
214 return layer.GetType() != LayerType::Input &&
215 layer.GetType() != LayerType::Output &&
216 !IsLayerSupported(layer);
217 };
218
219 // Apply the subgraph selector to the unsupported layers to group them into sub-graphs were appropriate
220 SubgraphView mutableSubgraph(subgraph);
221 SubgraphViewSelector::Subgraphs unsupportedSubgraphs =
222 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, unsupportedSubgraphSelector);
223
224 // Add each unsupported sub-graph to the list of failed sub-graphs in the optimizization views
225 std::for_each(unsupportedSubgraphs.begin(),
226 unsupportedSubgraphs.end(),
227 [&optimizationViews](const SubgraphView::SubgraphViewPtr& unsupportedSubgraph)
228 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100229 ARMNN_ASSERT(unsupportedSubgraph != nullptr);
Matteo Martincigh88054f82019-05-17 12:15:30 +0100230
231 optimizationViews.AddFailedSubgraph(SubgraphView(*unsupportedSubgraph));
232 });
233 }
234
235 // Check if there are untouched layers
236 if (!untouchedLayers.empty())
237 {
238 // Select the layers that are neither inputs or outputs, that are supported but that and are not optimizable
239 auto untouchedSubgraphSelector = [](const Layer& layer)
240 {
241 return layer.GetType() != LayerType::Input &&
242 layer.GetType() != LayerType::Output &&
243 IsLayerSupported(layer) &&
244 !IsLayerOptimizable(layer);
245 };
246
247 // Apply the subgraph selector to the untouched layers to group them into sub-graphs were appropriate
248 SubgraphView mutableSubgraph(subgraph);
249 SubgraphViewSelector::Subgraphs untouchedSubgraphs =
250 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, untouchedSubgraphSelector);
251
252 // Add each untouched sub-graph to the list of untouched sub-graphs in the optimizization views
253 std::for_each(untouchedSubgraphs.begin(),
254 untouchedSubgraphs.end(),
255 [&optimizationViews](const SubgraphView::SubgraphViewPtr& untouchedSubgraph)
256 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100257 ARMNN_ASSERT(untouchedSubgraph != nullptr);
Matteo Martincigh88054f82019-05-17 12:15:30 +0100258
259 optimizationViews.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
260 });
261 }
262
263 return optimizationViews;
264}
265
266} // namespace armnn