ArmNN
 22.02
MockBackend.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "MockBackend.hpp"
7 #include "MockBackendId.hpp"
8 
10 
14 
15 #include <Optimizer.hpp>
16 #include <SubgraphViewSelector.hpp>
17 
18 #include <algorithm>
19 
20 namespace
21 {
22 
23 bool IsLayerSupported(const armnn::Layer* layer)
24 {
25  ARMNN_ASSERT(layer != nullptr);
26 
27  armnn::LayerType layerType = layer->GetType();
28  switch (layerType)
29  {
34  // Layer supported
35  return true;
36  default:
37  // Layer unsupported
38  return false;
39  }
40 }
41 
42 bool IsLayerSupported(const armnn::Layer& layer)
43 {
44  return IsLayerSupported(&layer);
45 }
46 
47 bool IsLayerOptimizable(const armnn::Layer* layer)
48 {
49  ARMNN_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 
58 bool IsLayerOptimizable(const armnn::Layer& layer)
59 {
60  return IsLayerOptimizable(&layer);
61 }
62 
63 } // Anonymous namespace
64 
65 namespace armnn
66 {
67 
69 {
71  []()
72  {
74  });
75 }
76 
78 {
79  try
80  {
82  }
83  catch (...)
84  {
85  std::cerr << "could not deregister mock backend" << std::endl;
86  }
87 }
88 
90 {
91  static const BackendId s_Id{MockBackendId()};
92  return s_Id;
93 }
94 
96  const IBackendInternal::IMemoryManagerSharedPtr& /*memoryManager*/) const
97 {
98  return IWorkloadFactoryPtr{};
99 }
100 
102 {
103  return IBackendContextPtr{};
104 }
105 
107  const IRuntime::CreationOptions& options, IBackendProfilingPtr& backendProfiling)
108 {
109  IgnoreUnused(options);
110  std::shared_ptr<armnn::MockBackendProfilingContext> context =
111  std::make_shared<MockBackendProfilingContext>(backendProfiling);
113  return context;
114 }
115 
117 {
118  return IMemoryManagerUniquePtr{};
119 }
120 
122 {
123  static ILayerSupportSharedPtr layerSupport{new MockLayerSupport};
124  return layerSupport;
125 }
126 
128 {
129  // Prepare the optimization views
130  OptimizationViews optimizationViews;
131 
132  // Get the layers of the input sub-graph
133  const SubgraphView::IConnectableLayers& subgraphLayers = subgraph.GetIConnectableLayers();
134 
135  // Parse the layers
136  SubgraphView::IConnectableLayers supportedLayers;
137  SubgraphView::IConnectableLayers unsupportedLayers;
138  SubgraphView::IConnectableLayers untouchedLayers;
139  std::for_each(subgraphLayers.begin(),
140  subgraphLayers.end(),
141  [&](IConnectableLayer* layer)
142  {
143  bool supported = IsLayerSupported(PolymorphicDowncast<Layer*>(layer));
144  if (supported)
145  {
146  // Layer supported, check if it's optimizable
147  bool optimizable = IsLayerOptimizable(PolymorphicDowncast<Layer*>(layer));
148  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  {
188  ARMNN_ASSERT(supportedSubgraph != nullptr);
189 
190  CompiledBlobPtr blobPtr;
191  BackendId backend = MockBackendId();
192 
193  IConnectableLayer* preCompiledLayer =
194  optimizationViews.GetINetwork()->AddPrecompiledLayer(
195  PreCompiledDescriptor(supportedSubgraph->GetNumInputSlots(),
196  supportedSubgraph->GetNumOutputSlots()),
197  std::move(blobPtr),
198  backend,
199  nullptr);
200 
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  {
229  ARMNN_ASSERT(unsupportedSubgraph != nullptr);
230 
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  {
257  ARMNN_ASSERT(untouchedSubgraph != nullptr);
258 
259  optimizationViews.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
260  });
261  }
262 
263  return optimizationViews;
264 }
265 
266 std::unique_ptr<ICustomAllocator> MockBackend::GetDefaultAllocator() const
267 {
268  return std::make_unique<DefaultAllocator>();
269 }
270 
271 } // namespace armnn
std::unique_ptr< IWorkloadFactory > IWorkloadFactoryPtr
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:66
void SetProfilingContextPtr(std::shared_ptr< MockBackendProfilingContext > shared)
constexpr const char * MockBackendId()
Definition: MockBackend.cpp:13
void Register(const BackendId &id, FactoryFunction factory)
const IConnectableLayers & GetIConnectableLayers() const
IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(const IBackendInternal::IMemoryManagerSharedPtr &memoryManager=nullptr) const override
Definition: MockBackend.hpp:29
IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override
Definition: MockBackend.hpp:35
void AddSubstitution(SubstitutionPair &&substitution)
IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions &) const override
Create the runtime context of the backend.
BackendRegistry & BackendRegistryInstance()
OptimizationViews OptimizeSubgraphView(const SubgraphView &subgraph) const override
Copyright (c) 2021 ARM Limited and Contributors.
std::unique_ptr< IMemoryManager > IMemoryManagerUniquePtr
void IgnoreUnused(Ts &&...)
std::unique_ptr< void, CompiledBlobDeleter > CompiledBlobPtr
Definition: INetwork.hpp:245
The SubgraphView class represents a subgraph of a Graph.
std::unique_ptr< armnn::profiling::IBackendProfiling > IBackendProfilingPtr
std::unique_ptr< SubgraphView > SubgraphViewPtr
std::list< IConnectableLayer * > IConnectableLayers
std::unique_ptr< ICustomAllocator > GetDefaultAllocator() const override
Returns the default memory allocator for the backend.
std::shared_ptr< IMemoryManager > IMemoryManagerSharedPtr
static const BackendId & GetIdStatic()
Definition: MockBackend.cpp:18
void AddFailedSubgraph(SubgraphView &&subgraph)
LayerType GetType() const override
Returns the armnn::LayerType of this layer.
Definition: Layer.hpp:270
std::vector< SubgraphViewPtr > Subgraphs
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
static MockBackendProfilingService & Instance()
void AddUntouchedSubgraph(SubgraphView &&subgraph)
IBackendInternal::IBackendProfilingContextPtr CreateBackendProfilingContext(const IRuntime::CreationOptions &creationOptions, IBackendProfilingPtr &backendProfiling) override
Create context specifically used for profiling interaction from backends.
std::shared_ptr< ILayerSupport > ILayerSupportSharedPtr
static Subgraphs SelectSubgraphs(Graph &graph, const LayerSelectorFunction &selector)
Selects subgraphs from a graph based on the selector function and the algorithm.
void Deregister(const BackendId &id)
const char * GetName() const override
Returns the name of the layer.
Definition: Layer.hpp:316
std::unique_ptr< IBackendInternal > IBackendInternalUniquePtr
A PreCompiledDescriptor for the PreCompiledLayer.
std::shared_ptr< armnn::profiling::IBackendProfilingContext > IBackendProfilingContextPtr
This is the bridge between backend and backend profiling we&#39;ll keep it in the backend namespace...
IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager() const override
LayerType
When adding a new layer, adapt also the LastLayer enum value in the enum class LayerType below...
Definition: Types.hpp:458
std::unique_ptr< IBackendContext > IBackendContextPtr