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