blob: 4fb692ca6322cc245d849e0f688ac218997cf51c [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 Martincigh88054f82019-05-17 12:15:30 +010011#include <backendsCommon/IBackendContext.hpp>
12#include <backendsCommon/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
69namespace
70{
71
72static BackendRegistry::StaticRegistryInitializer g_RegisterHelper
73{
74 BackendRegistryInstance(),
75 MockBackend::GetIdStatic(),
76 []()
77 {
78 return IBackendInternalUniquePtr(new MockBackend);
79 }
80};
81
82}
83
84const BackendId& MockBackend::GetIdStatic()
85{
86 static const BackendId s_Id{MockBackendId()};
87 return s_Id;
88}
89
90IBackendInternal::IWorkloadFactoryPtr MockBackend::CreateWorkloadFactory(
91 const IBackendInternal::IMemoryManagerSharedPtr& memoryManager) const
92{
93 return IWorkloadFactoryPtr{};
94}
95
96IBackendInternal::IBackendContextPtr MockBackend::CreateBackendContext(const IRuntime::CreationOptions&) const
97{
98 return IBackendContextPtr{};
99}
100
101IBackendInternal::IMemoryManagerUniquePtr MockBackend::CreateMemoryManager() const
102{
103 return IMemoryManagerUniquePtr{};
104}
105
106IBackendInternal::Optimizations MockBackend::GetOptimizations() const
107{
108 return Optimizations{};
109}
110
111IBackendInternal::ILayerSupportSharedPtr MockBackend::GetLayerSupport() const
112{
David Monahan7f2c35a2019-05-24 10:46:28 +0100113 static ILayerSupportSharedPtr layerSupport{new MockLayerSupport};
114 return layerSupport;
Matteo Martincigh88054f82019-05-17 12:15:30 +0100115}
116
117OptimizationViews MockBackend::OptimizeSubgraphView(const SubgraphView& subgraph) const
118{
119 // Prepare the optimization views
120 OptimizationViews optimizationViews;
121
122 // Get the layers of the input sub-graph
123 const SubgraphView::Layers& subgraphLayers = subgraph.GetLayers();
124
125 // Parse the layers
126 SubgraphView::Layers supportedLayers;
127 SubgraphView::Layers unsupportedLayers;
128 SubgraphView::Layers untouchedLayers;
129 std::for_each(subgraphLayers.begin(),
130 subgraphLayers.end(),
131 [&](Layer* layer)
132 {
133 bool supported = IsLayerSupported(layer);
134 if (supported)
135 {
136 // Layer supported, check if it's optimizable
137 bool optimizable = IsLayerOptimizable(layer);
138 if (optimizable)
139 {
140 // Layer fully supported
141 supportedLayers.push_back(layer);
142 }
143 else
144 {
145 // Layer supported but not optimizable
146 untouchedLayers.push_back(layer);
147 }
148 }
149 else
150 {
151 // Layer unsupported
152 unsupportedLayers.push_back(layer);
153 }
154 });
155
156 // Check if there are supported layers
157 if (!supportedLayers.empty())
158 {
159 // Select the layers that are neither inputs or outputs, but that are optimizable
160 auto supportedSubgraphSelector = [](const Layer& layer)
161 {
162 return layer.GetType() != LayerType::Input &&
163 layer.GetType() != LayerType::Output &&
164 IsLayerSupported(layer) &&
165 IsLayerOptimizable(layer);
166 };
167
168 // Apply the subgraph selector to the supported layers to group them into sub-graphs were appropriate
169 SubgraphView mutableSubgraph(subgraph);
170 SubgraphViewSelector::Subgraphs supportedSubgraphs =
171 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, supportedSubgraphSelector);
172
173 // Create a substitution pair for each supported sub-graph
174 std::for_each(supportedSubgraphs.begin(),
175 supportedSubgraphs.end(),
176 [&optimizationViews](const SubgraphView::SubgraphViewPtr& supportedSubgraph)
177 {
178 BOOST_ASSERT(supportedSubgraph != nullptr);
179
180 PreCompiledLayer* preCompiledLayer =
181 optimizationViews.GetGraph().AddLayer<PreCompiledLayer>(
182 PreCompiledDescriptor(supportedSubgraph->GetNumInputSlots(),
183 supportedSubgraph->GetNumOutputSlots()),
184 "pre-compiled");
185 preCompiledLayer->SetBackendId(MockBackendId());
186
187 SubgraphView substitutionSubgraph(*supportedSubgraph);
188 SubgraphView replacementSubgraph(preCompiledLayer);
189
190 optimizationViews.AddSubstitution({ substitutionSubgraph, replacementSubgraph });
191 });
192 }
193
194 // Check if there are unsupported layers
195 if (!unsupportedLayers.empty())
196 {
197 // Select the layers that are neither inputs or outputs, and are not optimizable
198 auto unsupportedSubgraphSelector = [](const Layer& layer)
199 {
200 return layer.GetType() != LayerType::Input &&
201 layer.GetType() != LayerType::Output &&
202 !IsLayerSupported(layer);
203 };
204
205 // Apply the subgraph selector to the unsupported layers to group them into sub-graphs were appropriate
206 SubgraphView mutableSubgraph(subgraph);
207 SubgraphViewSelector::Subgraphs unsupportedSubgraphs =
208 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, unsupportedSubgraphSelector);
209
210 // Add each unsupported sub-graph to the list of failed sub-graphs in the optimizization views
211 std::for_each(unsupportedSubgraphs.begin(),
212 unsupportedSubgraphs.end(),
213 [&optimizationViews](const SubgraphView::SubgraphViewPtr& unsupportedSubgraph)
214 {
215 BOOST_ASSERT(unsupportedSubgraph != nullptr);
216
217 optimizationViews.AddFailedSubgraph(SubgraphView(*unsupportedSubgraph));
218 });
219 }
220
221 // Check if there are untouched layers
222 if (!untouchedLayers.empty())
223 {
224 // Select the layers that are neither inputs or outputs, that are supported but that and are not optimizable
225 auto untouchedSubgraphSelector = [](const Layer& layer)
226 {
227 return layer.GetType() != LayerType::Input &&
228 layer.GetType() != LayerType::Output &&
229 IsLayerSupported(layer) &&
230 !IsLayerOptimizable(layer);
231 };
232
233 // Apply the subgraph selector to the untouched layers to group them into sub-graphs were appropriate
234 SubgraphView mutableSubgraph(subgraph);
235 SubgraphViewSelector::Subgraphs untouchedSubgraphs =
236 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, untouchedSubgraphSelector);
237
238 // Add each untouched sub-graph to the list of untouched sub-graphs in the optimizization views
239 std::for_each(untouchedSubgraphs.begin(),
240 untouchedSubgraphs.end(),
241 [&optimizationViews](const SubgraphView::SubgraphViewPtr& untouchedSubgraph)
242 {
243 BOOST_ASSERT(untouchedSubgraph != nullptr);
244
245 optimizationViews.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
246 });
247 }
248
249 return optimizationViews;
250}
251
252} // namespace armnn