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