blob: 116bf77c63c9d5346724069ea0652e484afbb27e [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
17#include <boost/cast.hpp>
18
19#include <algorithm>
20
21namespace
22{
23
24bool IsLayerSupported(const armnn::Layer* layer)
25{
26 BOOST_ASSERT(layer != nullptr);
27
28 armnn::LayerType layerType = layer->GetType();
29 switch (layerType)
30 {
31 case armnn::LayerType::Input:
32 case armnn::LayerType::Output:
Matteo Martincighf02e6cd2019-05-17 12:15:30 +010033 case armnn::LayerType::Addition:
Matteo Martincigh88054f82019-05-17 12:15:30 +010034 case armnn::LayerType::Convolution2d:
35 // Layer supported
36 return true;
37 default:
38 // Layer unsupported
39 return false;
40 }
41}
42
43bool IsLayerSupported(const armnn::Layer& layer)
44{
45 return IsLayerSupported(&layer);
46}
47
48bool IsLayerOptimizable(const armnn::Layer* layer)
49{
50 BOOST_ASSERT(layer != nullptr);
51
52 // A Layer is not optimizable if its name contains "unoptimizable"
53 const std::string layerName(layer->GetName());
54 bool optimizable = layerName.find("unoptimizable") == std::string::npos;
55
56 return optimizable;
57}
58
59bool IsLayerOptimizable(const armnn::Layer& layer)
60{
61 return IsLayerOptimizable(&layer);
62}
63
64} // Anonymous namespace
65
66namespace armnn
67{
68
David Monahanc1536d62020-02-12 15:52:35 +000069MockBackendInitialiser::MockBackendInitialiser()
Matteo Martincigh88054f82019-05-17 12:15:30 +010070{
David Monahanc1536d62020-02-12 15:52:35 +000071 BackendRegistryInstance().Register(MockBackend::GetIdStatic(),
72 []()
73 {
74 return IBackendInternalUniquePtr(new MockBackend);
75 });
76}
Matteo Martincigh88054f82019-05-17 12:15:30 +010077
David Monahanc1536d62020-02-12 15:52:35 +000078MockBackendInitialiser::~MockBackendInitialiser()
Matteo Martincigh88054f82019-05-17 12:15:30 +010079{
David Monahanc1536d62020-02-12 15:52:35 +000080 try
Matteo Martincigh88054f82019-05-17 12:15:30 +010081 {
David Monahanc1536d62020-02-12 15:52:35 +000082 BackendRegistryInstance().Deregister(MockBackend::GetIdStatic());
Matteo Martincigh88054f82019-05-17 12:15:30 +010083 }
David Monahanc1536d62020-02-12 15:52:35 +000084 catch (...)
85 {
86 std::cerr << "could not deregister mock backend" << std::endl;
87 }
Matteo Martincigh88054f82019-05-17 12:15:30 +010088}
89
90const BackendId& MockBackend::GetIdStatic()
91{
92 static const BackendId s_Id{MockBackendId()};
93 return s_Id;
94}
95
96IBackendInternal::IWorkloadFactoryPtr MockBackend::CreateWorkloadFactory(
Derek Lamberti901ea112019-12-10 22:07:09 +000097 const IBackendInternal::IMemoryManagerSharedPtr& /*memoryManager*/) const
Matteo Martincigh88054f82019-05-17 12:15:30 +010098{
99 return IWorkloadFactoryPtr{};
100}
101
102IBackendInternal::IBackendContextPtr MockBackend::CreateBackendContext(const IRuntime::CreationOptions&) const
103{
104 return IBackendContextPtr{};
105}
106
Colm Donelane49755b2020-01-29 15:22:43 +0000107IBackendInternal::IBackendProfilingContextPtr MockBackend::CreateBackendProfilingContext(
David Monahanc1536d62020-02-12 15:52:35 +0000108 const IRuntime::CreationOptions& options, IBackendProfilingPtr& backendProfiling)
Colm Donelane49755b2020-01-29 15:22:43 +0000109{
Jan Eilers8eb25602020-03-09 12:13:48 +0000110 IgnoreUnused(options);
Colm Donelanfcb802b2020-02-13 20:47:08 +0000111 std::shared_ptr<armnn::MockBackendProfilingContext> context =
112 std::make_shared<MockBackendProfilingContext>(backendProfiling);
David Monahanc1536d62020-02-12 15:52:35 +0000113 MockBackendProfilingService::Instance().SetProfilingContextPtr(context);
114 return context;
Colm Donelane49755b2020-01-29 15:22:43 +0000115}
116
Matteo Martincigh88054f82019-05-17 12:15:30 +0100117IBackendInternal::IMemoryManagerUniquePtr MockBackend::CreateMemoryManager() const
118{
119 return IMemoryManagerUniquePtr{};
120}
121
122IBackendInternal::Optimizations MockBackend::GetOptimizations() const
123{
124 return Optimizations{};
125}
126
127IBackendInternal::ILayerSupportSharedPtr MockBackend::GetLayerSupport() const
128{
David Monahan7f2c35a2019-05-24 10:46:28 +0100129 static ILayerSupportSharedPtr layerSupport{new MockLayerSupport};
130 return layerSupport;
Matteo Martincigh88054f82019-05-17 12:15:30 +0100131}
132
133OptimizationViews MockBackend::OptimizeSubgraphView(const SubgraphView& subgraph) const
134{
135 // Prepare the optimization views
136 OptimizationViews optimizationViews;
137
138 // Get the layers of the input sub-graph
139 const SubgraphView::Layers& subgraphLayers = subgraph.GetLayers();
140
141 // Parse the layers
142 SubgraphView::Layers supportedLayers;
143 SubgraphView::Layers unsupportedLayers;
144 SubgraphView::Layers untouchedLayers;
145 std::for_each(subgraphLayers.begin(),
146 subgraphLayers.end(),
147 [&](Layer* layer)
148 {
149 bool supported = IsLayerSupported(layer);
150 if (supported)
151 {
152 // Layer supported, check if it's optimizable
153 bool optimizable = IsLayerOptimizable(layer);
154 if (optimizable)
155 {
156 // Layer fully supported
157 supportedLayers.push_back(layer);
158 }
159 else
160 {
161 // Layer supported but not optimizable
162 untouchedLayers.push_back(layer);
163 }
164 }
165 else
166 {
167 // Layer unsupported
168 unsupportedLayers.push_back(layer);
169 }
170 });
171
172 // Check if there are supported layers
173 if (!supportedLayers.empty())
174 {
175 // Select the layers that are neither inputs or outputs, but that are optimizable
176 auto supportedSubgraphSelector = [](const Layer& layer)
177 {
178 return layer.GetType() != LayerType::Input &&
179 layer.GetType() != LayerType::Output &&
180 IsLayerSupported(layer) &&
181 IsLayerOptimizable(layer);
182 };
183
184 // Apply the subgraph selector to the supported layers to group them into sub-graphs were appropriate
185 SubgraphView mutableSubgraph(subgraph);
186 SubgraphViewSelector::Subgraphs supportedSubgraphs =
187 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, supportedSubgraphSelector);
188
189 // Create a substitution pair for each supported sub-graph
190 std::for_each(supportedSubgraphs.begin(),
191 supportedSubgraphs.end(),
192 [&optimizationViews](const SubgraphView::SubgraphViewPtr& supportedSubgraph)
193 {
194 BOOST_ASSERT(supportedSubgraph != nullptr);
195
196 PreCompiledLayer* preCompiledLayer =
197 optimizationViews.GetGraph().AddLayer<PreCompiledLayer>(
198 PreCompiledDescriptor(supportedSubgraph->GetNumInputSlots(),
199 supportedSubgraph->GetNumOutputSlots()),
200 "pre-compiled");
201 preCompiledLayer->SetBackendId(MockBackendId());
202
203 SubgraphView substitutionSubgraph(*supportedSubgraph);
204 SubgraphView replacementSubgraph(preCompiledLayer);
205
206 optimizationViews.AddSubstitution({ substitutionSubgraph, replacementSubgraph });
207 });
208 }
209
210 // Check if there are unsupported layers
211 if (!unsupportedLayers.empty())
212 {
213 // Select the layers that are neither inputs or outputs, and are not optimizable
214 auto unsupportedSubgraphSelector = [](const Layer& layer)
215 {
216 return layer.GetType() != LayerType::Input &&
217 layer.GetType() != LayerType::Output &&
218 !IsLayerSupported(layer);
219 };
220
221 // Apply the subgraph selector to the unsupported layers to group them into sub-graphs were appropriate
222 SubgraphView mutableSubgraph(subgraph);
223 SubgraphViewSelector::Subgraphs unsupportedSubgraphs =
224 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, unsupportedSubgraphSelector);
225
226 // Add each unsupported sub-graph to the list of failed sub-graphs in the optimizization views
227 std::for_each(unsupportedSubgraphs.begin(),
228 unsupportedSubgraphs.end(),
229 [&optimizationViews](const SubgraphView::SubgraphViewPtr& unsupportedSubgraph)
230 {
231 BOOST_ASSERT(unsupportedSubgraph != nullptr);
232
233 optimizationViews.AddFailedSubgraph(SubgraphView(*unsupportedSubgraph));
234 });
235 }
236
237 // Check if there are untouched layers
238 if (!untouchedLayers.empty())
239 {
240 // Select the layers that are neither inputs or outputs, that are supported but that and are not optimizable
241 auto untouchedSubgraphSelector = [](const Layer& layer)
242 {
243 return layer.GetType() != LayerType::Input &&
244 layer.GetType() != LayerType::Output &&
245 IsLayerSupported(layer) &&
246 !IsLayerOptimizable(layer);
247 };
248
249 // Apply the subgraph selector to the untouched layers to group them into sub-graphs were appropriate
250 SubgraphView mutableSubgraph(subgraph);
251 SubgraphViewSelector::Subgraphs untouchedSubgraphs =
252 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, untouchedSubgraphSelector);
253
254 // Add each untouched sub-graph to the list of untouched sub-graphs in the optimizization views
255 std::for_each(untouchedSubgraphs.begin(),
256 untouchedSubgraphs.end(),
257 [&optimizationViews](const SubgraphView::SubgraphViewPtr& untouchedSubgraph)
258 {
259 BOOST_ASSERT(untouchedSubgraph != nullptr);
260
261 optimizationViews.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
262 });
263 }
264
265 return optimizationViews;
266}
267
268} // namespace armnn