blob: 4bdb8ce786d54897e522c2f16188766118a9b67a [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>
Francis Murtaghe8d7ccb2021-10-14 17:30:24 +010013#include <backendsCommon/DefaultAllocator.hpp>
Matteo Martincigh88054f82019-05-17 12:15:30 +010014
15#include <Optimizer.hpp>
16#include <SubgraphViewSelector.hpp>
17
Matteo Martincigh88054f82019-05-17 12:15:30 +010018#include <algorithm>
19
20namespace
21{
22
23bool IsLayerSupported(const armnn::Layer* layer)
24{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010025 ARMNN_ASSERT(layer != nullptr);
Matteo Martincigh88054f82019-05-17 12:15:30 +010026
27 armnn::LayerType layerType = layer->GetType();
28 switch (layerType)
29 {
30 case armnn::LayerType::Input:
31 case armnn::LayerType::Output:
Matteo Martincighf02e6cd2019-05-17 12:15:30 +010032 case armnn::LayerType::Addition:
Matteo Martincigh88054f82019-05-17 12:15:30 +010033 case armnn::LayerType::Convolution2d:
34 // Layer supported
35 return true;
36 default:
37 // Layer unsupported
38 return false;
39 }
40}
41
42bool IsLayerSupported(const armnn::Layer& layer)
43{
44 return IsLayerSupported(&layer);
45}
46
47bool IsLayerOptimizable(const armnn::Layer* layer)
48{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010049 ARMNN_ASSERT(layer != nullptr);
Matteo Martincigh88054f82019-05-17 12:15:30 +010050
51 // A Layer is not optimizable if its name contains "unoptimizable"
52 const std::string layerName(layer->GetName());
53 bool optimizable = layerName.find("unoptimizable") == std::string::npos;
54
55 return optimizable;
56}
57
58bool IsLayerOptimizable(const armnn::Layer& layer)
59{
60 return IsLayerOptimizable(&layer);
61}
62
63} // Anonymous namespace
64
65namespace armnn
66{
67
David Monahanc1536d62020-02-12 15:52:35 +000068MockBackendInitialiser::MockBackendInitialiser()
Matteo Martincigh88054f82019-05-17 12:15:30 +010069{
David Monahanc1536d62020-02-12 15:52:35 +000070 BackendRegistryInstance().Register(MockBackend::GetIdStatic(),
71 []()
72 {
73 return IBackendInternalUniquePtr(new MockBackend);
74 });
75}
Matteo Martincigh88054f82019-05-17 12:15:30 +010076
David Monahanc1536d62020-02-12 15:52:35 +000077MockBackendInitialiser::~MockBackendInitialiser()
Matteo Martincigh88054f82019-05-17 12:15:30 +010078{
David Monahanc1536d62020-02-12 15:52:35 +000079 try
Matteo Martincigh88054f82019-05-17 12:15:30 +010080 {
David Monahanc1536d62020-02-12 15:52:35 +000081 BackendRegistryInstance().Deregister(MockBackend::GetIdStatic());
Matteo Martincigh88054f82019-05-17 12:15:30 +010082 }
David Monahanc1536d62020-02-12 15:52:35 +000083 catch (...)
84 {
85 std::cerr << "could not deregister mock backend" << std::endl;
86 }
Matteo Martincigh88054f82019-05-17 12:15:30 +010087}
88
89const BackendId& MockBackend::GetIdStatic()
90{
91 static const BackendId s_Id{MockBackendId()};
92 return s_Id;
93}
94
95IBackendInternal::IWorkloadFactoryPtr MockBackend::CreateWorkloadFactory(
Derek Lamberti901ea112019-12-10 22:07:09 +000096 const IBackendInternal::IMemoryManagerSharedPtr& /*memoryManager*/) const
Matteo Martincigh88054f82019-05-17 12:15:30 +010097{
98 return IWorkloadFactoryPtr{};
99}
100
101IBackendInternal::IBackendContextPtr MockBackend::CreateBackendContext(const IRuntime::CreationOptions&) const
102{
103 return IBackendContextPtr{};
104}
105
Colm Donelane49755b2020-01-29 15:22:43 +0000106IBackendInternal::IBackendProfilingContextPtr MockBackend::CreateBackendProfilingContext(
David Monahanc1536d62020-02-12 15:52:35 +0000107 const IRuntime::CreationOptions& options, IBackendProfilingPtr& backendProfiling)
Colm Donelane49755b2020-01-29 15:22:43 +0000108{
Jan Eilers8eb25602020-03-09 12:13:48 +0000109 IgnoreUnused(options);
Colm Donelanfcb802b2020-02-13 20:47:08 +0000110 std::shared_ptr<armnn::MockBackendProfilingContext> context =
111 std::make_shared<MockBackendProfilingContext>(backendProfiling);
David Monahanc1536d62020-02-12 15:52:35 +0000112 MockBackendProfilingService::Instance().SetProfilingContextPtr(context);
113 return context;
Colm Donelane49755b2020-01-29 15:22:43 +0000114}
115
Matteo Martincigh88054f82019-05-17 12:15:30 +0100116IBackendInternal::IMemoryManagerUniquePtr MockBackend::CreateMemoryManager() const
117{
118 return IMemoryManagerUniquePtr{};
119}
120
Matteo Martincigh88054f82019-05-17 12:15:30 +0100121IBackendInternal::ILayerSupportSharedPtr MockBackend::GetLayerSupport() const
122{
David Monahan7f2c35a2019-05-24 10:46:28 +0100123 static ILayerSupportSharedPtr layerSupport{new MockLayerSupport};
124 return layerSupport;
Matteo Martincigh88054f82019-05-17 12:15:30 +0100125}
126
127OptimizationViews MockBackend::OptimizeSubgraphView(const SubgraphView& subgraph) const
128{
129 // Prepare the optimization views
130 OptimizationViews optimizationViews;
131
132 // Get the layers of the input sub-graph
133 const SubgraphView::Layers& subgraphLayers = subgraph.GetLayers();
134
135 // Parse the layers
136 SubgraphView::Layers supportedLayers;
137 SubgraphView::Layers unsupportedLayers;
138 SubgraphView::Layers untouchedLayers;
139 std::for_each(subgraphLayers.begin(),
140 subgraphLayers.end(),
141 [&](Layer* layer)
142 {
143 bool supported = IsLayerSupported(layer);
144 if (supported)
145 {
146 // Layer supported, check if it's optimizable
147 bool optimizable = IsLayerOptimizable(layer);
148 if (optimizable)
149 {
150 // Layer fully supported
151 supportedLayers.push_back(layer);
152 }
153 else
154 {
155 // Layer supported but not optimizable
156 untouchedLayers.push_back(layer);
157 }
158 }
159 else
160 {
161 // Layer unsupported
162 unsupportedLayers.push_back(layer);
163 }
164 });
165
166 // Check if there are supported layers
167 if (!supportedLayers.empty())
168 {
169 // Select the layers that are neither inputs or outputs, but that are optimizable
170 auto supportedSubgraphSelector = [](const Layer& layer)
171 {
172 return layer.GetType() != LayerType::Input &&
173 layer.GetType() != LayerType::Output &&
174 IsLayerSupported(layer) &&
175 IsLayerOptimizable(layer);
176 };
177
178 // Apply the subgraph selector to the supported layers to group them into sub-graphs were appropriate
179 SubgraphView mutableSubgraph(subgraph);
180 SubgraphViewSelector::Subgraphs supportedSubgraphs =
181 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, supportedSubgraphSelector);
182
183 // Create a substitution pair for each supported sub-graph
184 std::for_each(supportedSubgraphs.begin(),
185 supportedSubgraphs.end(),
186 [&optimizationViews](const SubgraphView::SubgraphViewPtr& supportedSubgraph)
187 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100188 ARMNN_ASSERT(supportedSubgraph != nullptr);
Matteo Martincigh88054f82019-05-17 12:15:30 +0100189
190 PreCompiledLayer* preCompiledLayer =
191 optimizationViews.GetGraph().AddLayer<PreCompiledLayer>(
192 PreCompiledDescriptor(supportedSubgraph->GetNumInputSlots(),
193 supportedSubgraph->GetNumOutputSlots()),
194 "pre-compiled");
195 preCompiledLayer->SetBackendId(MockBackendId());
196
197 SubgraphView substitutionSubgraph(*supportedSubgraph);
198 SubgraphView replacementSubgraph(preCompiledLayer);
199
200 optimizationViews.AddSubstitution({ substitutionSubgraph, replacementSubgraph });
201 });
202 }
203
204 // Check if there are unsupported layers
205 if (!unsupportedLayers.empty())
206 {
207 // Select the layers that are neither inputs or outputs, and are not optimizable
208 auto unsupportedSubgraphSelector = [](const Layer& layer)
209 {
210 return layer.GetType() != LayerType::Input &&
211 layer.GetType() != LayerType::Output &&
212 !IsLayerSupported(layer);
213 };
214
215 // Apply the subgraph selector to the unsupported layers to group them into sub-graphs were appropriate
216 SubgraphView mutableSubgraph(subgraph);
217 SubgraphViewSelector::Subgraphs unsupportedSubgraphs =
218 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, unsupportedSubgraphSelector);
219
220 // Add each unsupported sub-graph to the list of failed sub-graphs in the optimizization views
221 std::for_each(unsupportedSubgraphs.begin(),
222 unsupportedSubgraphs.end(),
223 [&optimizationViews](const SubgraphView::SubgraphViewPtr& unsupportedSubgraph)
224 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100225 ARMNN_ASSERT(unsupportedSubgraph != nullptr);
Matteo Martincigh88054f82019-05-17 12:15:30 +0100226
227 optimizationViews.AddFailedSubgraph(SubgraphView(*unsupportedSubgraph));
228 });
229 }
230
231 // Check if there are untouched layers
232 if (!untouchedLayers.empty())
233 {
234 // Select the layers that are neither inputs or outputs, that are supported but that and are not optimizable
235 auto untouchedSubgraphSelector = [](const Layer& layer)
236 {
237 return layer.GetType() != LayerType::Input &&
238 layer.GetType() != LayerType::Output &&
239 IsLayerSupported(layer) &&
240 !IsLayerOptimizable(layer);
241 };
242
243 // Apply the subgraph selector to the untouched layers to group them into sub-graphs were appropriate
244 SubgraphView mutableSubgraph(subgraph);
245 SubgraphViewSelector::Subgraphs untouchedSubgraphs =
246 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, untouchedSubgraphSelector);
247
248 // Add each untouched sub-graph to the list of untouched sub-graphs in the optimizization views
249 std::for_each(untouchedSubgraphs.begin(),
250 untouchedSubgraphs.end(),
251 [&optimizationViews](const SubgraphView::SubgraphViewPtr& untouchedSubgraph)
252 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100253 ARMNN_ASSERT(untouchedSubgraph != nullptr);
Matteo Martincigh88054f82019-05-17 12:15:30 +0100254
255 optimizationViews.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
256 });
257 }
258
259 return optimizationViews;
260}
261
Francis Murtaghe8d7ccb2021-10-14 17:30:24 +0100262std::unique_ptr<ICustomAllocator> MockBackend::GetDefaultAllocator() const
263{
264 return std::make_unique<DefaultAllocator>();
265}
266
Matteo Martincigh88054f82019-05-17 12:15:30 +0100267} // namespace armnn