ArmNN
 22.05
MockBackend.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
12 #include <SubgraphViewSelector.hpp>
13 
14 namespace armnn
15 {
16 
18 {
19  static const BackendId s_Id{MockBackendId()};
20  return s_Id;
21 }
22 
23 namespace
24 {
25 static const BackendId s_Id{ MockBackendId() };
26 }
27 
28 MockWorkloadFactory::MockWorkloadFactory(const std::shared_ptr<MockMemoryManager>& memoryManager)
29  : m_MemoryManager(memoryManager)
30 {}
31 
33  : m_MemoryManager(new MockMemoryManager())
34 {}
35 
37 {
38  return s_Id;
39 }
40 
41 std::unique_ptr<IWorkload> MockWorkloadFactory::CreateWorkload(LayerType type,
42  const QueueDescriptor& descriptor,
43  const WorkloadInfo& info) const
44 {
45  switch (type)
46  {
47  case LayerType::MemCopy: {
48  auto memCopyQueueDescriptor = PolymorphicDowncast<const MemCopyQueueDescriptor*>(&descriptor);
49  if (descriptor.m_Inputs.empty())
50  {
51  throw InvalidArgumentException("MockWorkloadFactory: CreateMemCopy() expected an input tensor.");
52  }
53  return std::make_unique<CopyMemGenericWorkload>(*memCopyQueueDescriptor, info);
54  }
55  default:
56  return nullptr;
57  }
58 }
59 
60 bool IsLayerSupported(const armnn::Layer* layer)
61 {
62  ARMNN_ASSERT(layer != nullptr);
63 
64  armnn::LayerType layerType = layer->GetType();
65  switch (layerType)
66  {
72  // Layer supported
73  return true;
74  default:
75  // Layer unsupported
76  return false;
77  }
78 }
79 
80 bool IsLayerSupported(const armnn::Layer& layer)
81 {
82  return IsLayerSupported(&layer);
83 }
84 
85 bool IsLayerOptimizable(const armnn::Layer* layer)
86 {
87  ARMNN_ASSERT(layer != nullptr);
88 
89  // A Layer is not optimizable if its name contains "unoptimizable"
90  const std::string layerName(layer->GetName());
91  bool optimizable = layerName.find("unoptimizable") == std::string::npos;
92 
93  return optimizable;
94 }
95 
96 bool IsLayerOptimizable(const armnn::Layer& layer)
97 {
98  return IsLayerOptimizable(&layer);
99 }
100 
101 } // Anonymous namespace
102 
103 namespace armnn
104 {
105 
107 {
109  []()
110  {
112  });
113 }
114 
116 {
117  try
118  {
120  }
121  catch (...)
122  {
123  std::cerr << "could not deregister mock backend" << std::endl;
124  }
125 }
126 
128  const IBackendInternal::IMemoryManagerSharedPtr& /*memoryManager*/) const
129 {
130  return IWorkloadFactoryPtr{};
131 }
132 
134 {
135  return IBackendContextPtr{};
136 }
137 
139  const IRuntime::CreationOptions& options, IBackendProfilingPtr& backendProfiling)
140 {
141  IgnoreUnused(options);
142  std::shared_ptr<armnn::MockBackendProfilingContext> context =
143  std::make_shared<MockBackendProfilingContext>(backendProfiling);
145  return context;
146 }
147 
149 {
150  return IMemoryManagerUniquePtr{};
151 }
152 
154 {
155  static ILayerSupportSharedPtr layerSupport{new MockLayerSupport};
156  return layerSupport;
157 }
158 
160 {
161  // Prepare the optimization views
162  OptimizationViews optimizationViews;
163 
164  // Get the layers of the input sub-graph
165  const SubgraphView::IConnectableLayers& subgraphLayers = subgraph.GetIConnectableLayers();
166 
167  // Parse the layers
168  SubgraphView::IConnectableLayers supportedLayers;
169  SubgraphView::IConnectableLayers unsupportedLayers;
170  SubgraphView::IConnectableLayers untouchedLayers;
171  std::for_each(subgraphLayers.begin(),
172  subgraphLayers.end(),
173  [&](IConnectableLayer* layer)
174  {
175  bool supported = IsLayerSupported(PolymorphicDowncast<Layer*>(layer));
176  if (supported)
177  {
178  // Layer supported, check if it's optimizable
179  bool optimizable = IsLayerOptimizable(PolymorphicDowncast<Layer*>(layer));
180  if (optimizable)
181  {
182  // Layer fully supported
183  supportedLayers.push_back(layer);
184  }
185  else
186  {
187  // Layer supported but not optimizable
188  untouchedLayers.push_back(layer);
189  }
190  }
191  else
192  {
193  // Layer unsupported
194  unsupportedLayers.push_back(layer);
195  }
196  });
197 
198  // Check if there are supported layers
199  if (!supportedLayers.empty())
200  {
201  // Select the layers that are neither inputs or outputs, but that are optimizable
202  auto supportedSubgraphSelector = [](const Layer& layer)
203  {
204  return layer.GetType() != LayerType::Input &&
205  layer.GetType() != LayerType::Output &&
206  IsLayerSupported(layer) &&
207  IsLayerOptimizable(layer);
208  };
209 
210  // Apply the subgraph selector to the supported layers to group them into sub-graphs were appropriate
211  SubgraphView mutableSubgraph(subgraph);
212  SubgraphViewSelector::Subgraphs supportedSubgraphs =
213  SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, supportedSubgraphSelector);
214 
215  // Create a substitution pair for each supported sub-graph
216  std::for_each(supportedSubgraphs.begin(),
217  supportedSubgraphs.end(),
218  [&optimizationViews](const SubgraphView::SubgraphViewPtr& supportedSubgraph)
219  {
220  ARMNN_ASSERT(supportedSubgraph != nullptr);
221 
222  CompiledBlobPtr blobPtr;
223  BackendId backend = MockBackendId();
224 
225  IConnectableLayer* preCompiledLayer =
226  optimizationViews.GetINetwork()->AddPrecompiledLayer(
227  PreCompiledDescriptor(supportedSubgraph->GetNumInputSlots(),
228  supportedSubgraph->GetNumOutputSlots()),
229  std::move(blobPtr),
230  backend,
231  nullptr);
232 
233  SubgraphView substitutionSubgraph(*supportedSubgraph);
234  SubgraphView replacementSubgraph(preCompiledLayer);
235 
236  optimizationViews.AddSubstitution({ substitutionSubgraph, replacementSubgraph });
237  });
238  }
239 
240  // Check if there are unsupported layers
241  if (!unsupportedLayers.empty())
242  {
243  // Select the layers that are neither inputs or outputs, and are not optimizable
244  auto unsupportedSubgraphSelector = [](const Layer& layer)
245  {
246  return layer.GetType() != LayerType::Input &&
247  layer.GetType() != LayerType::Output &&
248  !IsLayerSupported(layer);
249  };
250 
251  // Apply the subgraph selector to the unsupported layers to group them into sub-graphs were appropriate
252  SubgraphView mutableSubgraph(subgraph);
253  SubgraphViewSelector::Subgraphs unsupportedSubgraphs =
254  SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, unsupportedSubgraphSelector);
255 
256  // Add each unsupported sub-graph to the list of failed sub-graphs in the optimizization views
257  std::for_each(unsupportedSubgraphs.begin(),
258  unsupportedSubgraphs.end(),
259  [&optimizationViews](const SubgraphView::SubgraphViewPtr& unsupportedSubgraph)
260  {
261  ARMNN_ASSERT(unsupportedSubgraph != nullptr);
262 
263  optimizationViews.AddFailedSubgraph(SubgraphView(*unsupportedSubgraph));
264  });
265  }
266 
267  // Check if there are untouched layers
268  if (!untouchedLayers.empty())
269  {
270  // Select the layers that are neither inputs or outputs, that are supported but that and are not optimizable
271  auto untouchedSubgraphSelector = [](const Layer& layer)
272  {
273  return layer.GetType() != LayerType::Input &&
274  layer.GetType() != LayerType::Output &&
275  IsLayerSupported(layer) &&
276  !IsLayerOptimizable(layer);
277  };
278 
279  // Apply the subgraph selector to the untouched layers to group them into sub-graphs were appropriate
280  SubgraphView mutableSubgraph(subgraph);
281  SubgraphViewSelector::Subgraphs untouchedSubgraphs =
282  SubgraphViewSelector::SelectSubgraphs(mutableSubgraph, untouchedSubgraphSelector);
283 
284  // Add each untouched sub-graph to the list of untouched sub-graphs in the optimizization views
285  std::for_each(untouchedSubgraphs.begin(),
286  untouchedSubgraphs.end(),
287  [&optimizationViews](const SubgraphView::SubgraphViewPtr& untouchedSubgraph)
288  {
289  ARMNN_ASSERT(untouchedSubgraph != nullptr);
290 
291  optimizationViews.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
292  });
293  }
294 
295  return optimizationViews;
296 }
297 
298 std::unique_ptr<ICustomAllocator> MockBackend::GetDefaultAllocator() const
299 {
300  return std::make_unique<DefaultAllocator>();
301 }
302 
303 } // namespace armnn
ARMNN_DEPRECATED_MSG_REMOVAL_DATE("Use ABI stable " "CreateWorkload(LayerType, const QueueDescriptor&, const WorkloadInfo& info) instead.", "22.11") std std::unique_ptr< IWorkload > CreateWorkload(LayerType type, const QueueDescriptor &descriptor, const WorkloadInfo &info) const override
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)
void Register(const BackendId &id, FactoryFunction factory)
const IConnectableLayers & GetIConnectableLayers() const
IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(const IBackendInternal::IMemoryManagerSharedPtr &memoryManager=nullptr) const override
IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override
void AddSubstitution(SubstitutionPair &&substitution)
constexpr const char * MockBackendId()
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< SubgraphView > SubgraphViewPtr
std::list< IConnectableLayer * > IConnectableLayers
const BackendId & GetBackendId() const override
Definition: MockBackend.cpp:36
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:17
void AddFailedSubgraph(SubgraphView &&subgraph)
LayerType GetType() const override
Returns the armnn::LayerType of this layer.
Definition: Layer.hpp:271
std::vector< SubgraphViewPtr > Subgraphs
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
static bool IsLayerSupported(const BackendId &backendId, const IConnectableLayer &layer, Optional< DataType > dataType, std::string &outReasonIfUnsupported)
bool IsLayerOptimizable(const armnn::Layer *layer)
Definition: MockBackend.cpp:85
static MockBackendProfilingService & Instance()
void AddUntouchedSubgraph(SubgraphView &&subgraph)
std::shared_ptr< arm::pipe::IBackendProfilingContext > IBackendProfilingContextPtr
This is the bridge between backend and backend profiling we&#39;ll keep it in the backend namespace...
IBackendInternal::IBackendProfilingContextPtr CreateBackendProfilingContext(const IRuntime::CreationOptions &creationOptions, IBackendProfilingPtr &backendProfiling) override
Create context specifically used for profiling interaction from backends.
std::shared_ptr< ILayerSupport > ILayerSupportSharedPtr
std::unique_ptr< arm::pipe::IBackendProfiling > IBackendProfilingPtr
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)
Contains information about TensorInfos of a layer.
const char * GetName() const override
Returns the name of the layer.
Definition: Layer.hpp:317
std::vector< ITensorHandle * > m_Inputs
std::unique_ptr< IBackendInternal > IBackendInternalUniquePtr
A PreCompiledDescriptor for the PreCompiledLayer.
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:467
std::unique_ptr< IBackendContext > IBackendContextPtr