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