blob: 2ce14f92a48112a86b67f22e21a9e6917aacf475 [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
Francis Murtagh56ccf682021-12-13 18:48:12 +0000133 const SubgraphView::IConnectableLayers& subgraphLayers = subgraph.GetIConnectableLayers();
Matteo Martincigh88054f82019-05-17 12:15:30 +0100134
135 // Parse the layers
Francis Murtagh56ccf682021-12-13 18:48:12 +0000136 SubgraphView::IConnectableLayers supportedLayers;
137 SubgraphView::IConnectableLayers unsupportedLayers;
138 SubgraphView::IConnectableLayers untouchedLayers;
Matteo Martincigh88054f82019-05-17 12:15:30 +0100139 std::for_each(subgraphLayers.begin(),
140 subgraphLayers.end(),
Francis Murtagh56ccf682021-12-13 18:48:12 +0000141 [&](IConnectableLayer* layer)
Matteo Martincigh88054f82019-05-17 12:15:30 +0100142 {
Francis Murtagh56ccf682021-12-13 18:48:12 +0000143 bool supported = IsLayerSupported(PolymorphicDowncast<Layer*>(layer));
Matteo Martincigh88054f82019-05-17 12:15:30 +0100144 if (supported)
145 {
146 // Layer supported, check if it's optimizable
Francis Murtagh56ccf682021-12-13 18:48:12 +0000147 bool optimizable = IsLayerOptimizable(PolymorphicDowncast<Layer*>(layer));
Matteo Martincigh88054f82019-05-17 12:15:30 +0100148 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
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000190 CompiledBlobPtr blobPtr;
191 BackendId backend = MockBackendId();
192
193 IConnectableLayer* preCompiledLayer =
194 optimizationViews.GetINetwork()->AddPrecompiledLayer(
Matteo Martincigh88054f82019-05-17 12:15:30 +0100195 PreCompiledDescriptor(supportedSubgraph->GetNumInputSlots(),
196 supportedSubgraph->GetNumOutputSlots()),
Cathal Corbett3ea01072022-01-06 10:29:43 +0000197 std::move(blobPtr),
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000198 backend,
199 nullptr);
Matteo Martincigh88054f82019-05-17 12:15:30 +0100200
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
Francis Murtaghe8d7ccb2021-10-14 17:30:24 +0100266std::unique_ptr<ICustomAllocator> MockBackend::GetDefaultAllocator() const
267{
268 return std::make_unique<DefaultAllocator>();
269}
270
Matteo Martincigh88054f82019-05-17 12:15:30 +0100271} // namespace armnn