blob: 4eb96b53363fc6966117545c94ed9907a1e0937a [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{
112 return ILayerSupportSharedPtr{};
113}
114
115OptimizationViews MockBackend::OptimizeSubgraphView(const SubgraphView& subgraph) const
116{
117 // Prepare the optimization views
118 OptimizationViews optimizationViews;
119
120 // Get the layers of the input sub-graph
121 const SubgraphView::Layers& subgraphLayers = subgraph.GetLayers();
122
123 // Parse the layers
124 SubgraphView::Layers supportedLayers;
125 SubgraphView::Layers unsupportedLayers;
126 SubgraphView::Layers untouchedLayers;
127 std::for_each(subgraphLayers.begin(),
128 subgraphLayers.end(),
129 [&](Layer* layer)
130 {
131 bool supported = IsLayerSupported(layer);
132 if (supported)
133 {
134 // Layer supported, check if it's optimizable
135 bool optimizable = IsLayerOptimizable(layer);
136 if (optimizable)
137 {
138 // Layer fully supported
139 supportedLayers.push_back(layer);
140 }
141 else
142 {
143 // Layer supported but not optimizable
144 untouchedLayers.push_back(layer);
145 }
146 }
147 else
148 {
149 // Layer unsupported
150 unsupportedLayers.push_back(layer);
151 }
152 });
153
154 // Check if there are supported layers
155 if (!supportedLayers.empty())
156 {
157 // Select the layers that are neither inputs or outputs, but that are optimizable
158 auto supportedSubgraphSelector = [](const Layer& layer)
159 {
160 return layer.GetType() != LayerType::Input &&
161 layer.GetType() != LayerType::Output &&
162 IsLayerSupported(layer) &&
163 IsLayerOptimizable(layer);
164 };
165
166 // Apply the subgraph selector to the supported layers to group them into sub-graphs were appropriate
167 SubgraphView mutableSubgraph(subgraph);
168 SubgraphViewSelector::Subgraphs supportedSubgraphs =
169 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, supportedSubgraphSelector);
170
171 // Create a substitution pair for each supported sub-graph
172 std::for_each(supportedSubgraphs.begin(),
173 supportedSubgraphs.end(),
174 [&optimizationViews](const SubgraphView::SubgraphViewPtr& supportedSubgraph)
175 {
176 BOOST_ASSERT(supportedSubgraph != nullptr);
177
178 PreCompiledLayer* preCompiledLayer =
179 optimizationViews.GetGraph().AddLayer<PreCompiledLayer>(
180 PreCompiledDescriptor(supportedSubgraph->GetNumInputSlots(),
181 supportedSubgraph->GetNumOutputSlots()),
182 "pre-compiled");
183 preCompiledLayer->SetBackendId(MockBackendId());
184
185 SubgraphView substitutionSubgraph(*supportedSubgraph);
186 SubgraphView replacementSubgraph(preCompiledLayer);
187
188 optimizationViews.AddSubstitution({ substitutionSubgraph, replacementSubgraph });
189 });
190 }
191
192 // Check if there are unsupported layers
193 if (!unsupportedLayers.empty())
194 {
195 // Select the layers that are neither inputs or outputs, and are not optimizable
196 auto unsupportedSubgraphSelector = [](const Layer& layer)
197 {
198 return layer.GetType() != LayerType::Input &&
199 layer.GetType() != LayerType::Output &&
200 !IsLayerSupported(layer);
201 };
202
203 // Apply the subgraph selector to the unsupported layers to group them into sub-graphs were appropriate
204 SubgraphView mutableSubgraph(subgraph);
205 SubgraphViewSelector::Subgraphs unsupportedSubgraphs =
206 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, unsupportedSubgraphSelector);
207
208 // Add each unsupported sub-graph to the list of failed sub-graphs in the optimizization views
209 std::for_each(unsupportedSubgraphs.begin(),
210 unsupportedSubgraphs.end(),
211 [&optimizationViews](const SubgraphView::SubgraphViewPtr& unsupportedSubgraph)
212 {
213 BOOST_ASSERT(unsupportedSubgraph != nullptr);
214
215 optimizationViews.AddFailedSubgraph(SubgraphView(*unsupportedSubgraph));
216 });
217 }
218
219 // Check if there are untouched layers
220 if (!untouchedLayers.empty())
221 {
222 // Select the layers that are neither inputs or outputs, that are supported but that and are not optimizable
223 auto untouchedSubgraphSelector = [](const Layer& layer)
224 {
225 return layer.GetType() != LayerType::Input &&
226 layer.GetType() != LayerType::Output &&
227 IsLayerSupported(layer) &&
228 !IsLayerOptimizable(layer);
229 };
230
231 // Apply the subgraph selector to the untouched layers to group them into sub-graphs were appropriate
232 SubgraphView mutableSubgraph(subgraph);
233 SubgraphViewSelector::Subgraphs untouchedSubgraphs =
234 SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, untouchedSubgraphSelector);
235
236 // Add each untouched sub-graph to the list of untouched sub-graphs in the optimizization views
237 std::for_each(untouchedSubgraphs.begin(),
238 untouchedSubgraphs.end(),
239 [&optimizationViews](const SubgraphView::SubgraphViewPtr& untouchedSubgraph)
240 {
241 BOOST_ASSERT(untouchedSubgraph != nullptr);
242
243 optimizationViews.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
244 });
245 }
246
247 return optimizationViews;
248}
249
250} // namespace armnn