ArmNN
 22.05
MockBackend.hpp
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 #pragma once
6 
7 #include <atomic>
8 
13 
14 namespace armnn
15 {
16 
17 // A bare bones Mock backend to enable unit testing of simple tensor manipulation features.
19 {
20 public:
21  MockBackend() = default;
22 
23  ~MockBackend() = default;
24 
25  static const BackendId& GetIdStatic();
26 
27  const BackendId& GetId() const override
28  {
29  return GetIdStatic();
30  }
32  CreateWorkloadFactory(const IBackendInternal::IMemoryManagerSharedPtr& memoryManager = nullptr) const override;
33 
35 
37 
41  IBackendProfilingPtr& backendProfiling) override;
42 
43  OptimizationViews OptimizeSubgraphView(const SubgraphView& subgraph) const override;
44 
45  std::unique_ptr<ICustomAllocator> GetDefaultAllocator() const override;
46 };
47 
49 {
50 
51 public:
52  explicit MockWorkloadFactory(const std::shared_ptr<MockMemoryManager>& memoryManager);
54 
56  {}
57 
58  const BackendId& GetBackendId() const override;
59 
60  bool SupportsSubTensors() const override
61  {
62  return false;
63  }
64 
65  ARMNN_DEPRECATED_MSG("Use ITensorHandleFactory::CreateSubTensorHandle instead")
66  std::unique_ptr<ITensorHandle> CreateSubTensorHandle(ITensorHandle&,
67  TensorShape const&,
68  unsigned int const*) const override
69  {
70  return nullptr;
71  }
72 
73  ARMNN_DEPRECATED_MSG("Use ITensorHandleFactory::CreateTensorHandle instead")
74  std::unique_ptr<ITensorHandle> CreateTensorHandle(const TensorInfo& tensorInfo,
75  const bool IsMemoryManaged = true) const override
76  {
77  IgnoreUnused(IsMemoryManaged);
78  return std::make_unique<MockTensorHandle>(tensorInfo, m_MemoryManager);
79  };
80 
81  ARMNN_DEPRECATED_MSG("Use ITensorHandleFactory::CreateTensorHandle instead")
82  std::unique_ptr<ITensorHandle> CreateTensorHandle(const TensorInfo& tensorInfo,
83  DataLayout dataLayout,
84  const bool IsMemoryManaged = true) const override
85  {
86  IgnoreUnused(dataLayout, IsMemoryManaged);
87  return std::make_unique<MockTensorHandle>(tensorInfo, static_cast<unsigned int>(MemorySource::Malloc));
88  };
89 
91  "Use ABI stable "
92  "CreateWorkload(LayerType, const QueueDescriptor&, const WorkloadInfo& info) instead.",
93  "22.11")
94  std::unique_ptr<IWorkload> CreateInput(const InputQueueDescriptor& descriptor,
95  const WorkloadInfo& info) const override
96  {
97  if (info.m_InputTensorInfos.empty())
98  {
99  throw InvalidArgumentException("MockWorkloadFactory::CreateInput: Input cannot be zero length");
100  }
101  if (info.m_OutputTensorInfos.empty())
102  {
103  throw InvalidArgumentException("MockWorkloadFactory::CreateInput: Output cannot be zero length");
104  }
105 
106  if (info.m_InputTensorInfos[0].GetNumBytes() != info.m_OutputTensorInfos[0].GetNumBytes())
107  {
109  "MockWorkloadFactory::CreateInput: data input and output differ in byte count.");
110  }
111 
112  return std::make_unique<CopyMemGenericWorkload>(descriptor, info);
113  };
114 
115  std::unique_ptr<IWorkload>
116  CreateWorkload(LayerType type, const QueueDescriptor& descriptor, const WorkloadInfo& info) const override;
117 
118 private:
119  mutable std::shared_ptr<MockMemoryManager> m_MemoryManager;
120 };
121 
123 {
124 public:
127 };
128 
129 class MockBackendProfilingContext : public arm::pipe::IBackendProfilingContext
130 {
131 public:
133  : m_BackendProfiling(std::move(backendProfiling))
134  , m_CapturePeriod(0)
135  , m_IsTimelineEnabled(true)
136  {}
137 
138  ~MockBackendProfilingContext() = default;
139 
141  {
142  return m_BackendProfiling;
143  }
144 
145  uint16_t RegisterCounters(uint16_t currentMaxGlobalCounterId)
146  {
147  std::unique_ptr<arm::pipe::IRegisterBackendCounters> counterRegistrar =
148  m_BackendProfiling->GetCounterRegistrationInterface(static_cast<uint16_t>(currentMaxGlobalCounterId));
149 
150  std::string categoryName("MockCounters");
151  counterRegistrar->RegisterCategory(categoryName);
152 
153  counterRegistrar->RegisterCounter(0, categoryName, 0, 0, 1.f, "Mock Counter One", "Some notional counter");
154 
155  counterRegistrar->RegisterCounter(1, categoryName, 0, 0, 1.f, "Mock Counter Two",
156  "Another notional counter");
157 
158  std::string units("microseconds");
159  uint16_t nextMaxGlobalCounterId =
160  counterRegistrar->RegisterCounter(2, categoryName, 0, 0, 1.f, "Mock MultiCore Counter",
161  "A dummy four core counter", units, 4);
162  return nextMaxGlobalCounterId;
163  }
164 
165  arm::pipe::Optional<std::string> ActivateCounters(uint32_t capturePeriod, const std::vector<uint16_t>& counterIds)
166  {
167  if (capturePeriod == 0 || counterIds.size() == 0)
168  {
169  m_ActiveCounters.clear();
170  }
171  else if (capturePeriod == 15939u)
172  {
173  return arm::pipe::Optional<std::string>("ActivateCounters example test error");
174  }
175  m_CapturePeriod = capturePeriod;
176  m_ActiveCounters = counterIds;
177  return arm::pipe::Optional<std::string>();
178  }
179 
180  std::vector<arm::pipe::Timestamp> ReportCounterValues()
181  {
182  std::vector<arm::pipe::CounterValue> counterValues;
183 
184  for (auto counterId : m_ActiveCounters)
185  {
186  counterValues.emplace_back(arm::pipe::CounterValue{ counterId, counterId + 1u });
187  }
188 
189  uint64_t timestamp = m_CapturePeriod;
190  return { arm::pipe::Timestamp{ timestamp, counterValues } };
191  }
192 
193  bool EnableProfiling(bool)
194  {
195  auto sendTimelinePacket = m_BackendProfiling->GetSendTimelinePacket();
196  sendTimelinePacket->SendTimelineEntityBinaryPacket(4256);
197  sendTimelinePacket->Commit();
198  return true;
199  }
200 
201  bool EnableTimelineReporting(bool isEnabled)
202  {
203  m_IsTimelineEnabled = isEnabled;
204  return isEnabled;
205  }
206 
208  {
209  return m_IsTimelineEnabled;
210  }
211 
212 private:
213  IBackendInternal::IBackendProfilingPtr m_BackendProfiling;
214  uint32_t m_CapturePeriod;
215  std::vector<uint16_t> m_ActiveCounters;
216  std::atomic<bool> m_IsTimelineEnabled;
217 };
218 
220 {
221 public:
222  // Getter for the singleton instance
224  {
225  static MockBackendProfilingService instance;
226  return instance;
227  }
228 
230  {
231  return m_sharedContext.get();
232  }
233 
234  void SetProfilingContextPtr(std::shared_ptr<MockBackendProfilingContext> shared)
235  {
236  m_sharedContext = shared;
237  }
238 
239 private:
240  std::shared_ptr<MockBackendProfilingContext> m_sharedContext;
241 };
242 
244 {
245 public:
246  bool IsLayerSupported(const LayerType& type,
247  const std::vector<TensorInfo>& infos,
248  const BaseDescriptor& descriptor,
249  const Optional<LstmInputParamsInfo>& /*lstmParamsInfo*/,
250  const Optional<QuantizedLstmInputParamsInfo>& /*quantizedLstmParamsInfo*/,
251  Optional<std::string&> reasonIfUnsupported) const override
252  {
253  switch(type)
254  {
255  case LayerType::Input:
256  return IsInputSupported(infos[0], reasonIfUnsupported);
257  case LayerType::Output:
258  return IsOutputSupported(infos[0], reasonIfUnsupported);
259  case LayerType::Addition:
260  return IsAdditionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
262  {
263  if (infos.size() != 4)
264  {
265  throw InvalidArgumentException("Invalid number of TransposeConvolution2d "
266  "TensorInfos. TensorInfos should be of format: "
267  "{input, output, weights, biases}.");
268  }
269 
270  auto desc = *(PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor));
271  if (infos[3] == TensorInfo())
272  {
273  return IsConvolution2dSupported(infos[0],
274  infos[1],
275  desc,
276  infos[2],
277  EmptyOptional(),
278  reasonIfUnsupported);
279  }
280  else
281  {
282  return IsConvolution2dSupported(infos[0],
283  infos[1],
284  desc,
285  infos[2],
286  infos[3],
287  reasonIfUnsupported);
288  }
289  }
290  default:
291  return false;
292  }
293  }
294 
295  bool IsInputSupported(const TensorInfo& /*input*/,
296  Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
297  {
298  return true;
299  }
300 
301  bool IsOutputSupported(const TensorInfo& /*input*/,
302  Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
303  {
304  return true;
305  }
306 
307  bool IsAdditionSupported(const TensorInfo& /*input0*/,
308  const TensorInfo& /*input1*/,
309  const TensorInfo& /*output*/,
310  Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
311  {
312  return true;
313  }
314 
315  bool IsConvolution2dSupported(const TensorInfo& /*input*/,
316  const TensorInfo& /*output*/,
317  const Convolution2dDescriptor& /*descriptor*/,
318  const TensorInfo& /*weights*/,
319  const Optional<TensorInfo>& /*biases*/,
320  Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
321  {
322  return true;
323  }
324 };
325 
326 } // 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
MockBackendProfilingContext(IBackendInternal::IBackendProfilingPtr &backendProfiling)
bool IsOutputSupported(const BackendId &backend, const TensorInfo &output, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.
std::unique_ptr< IWorkloadFactory > IWorkloadFactoryPtr
~MockBackend()=default
void SetProfilingContextPtr(std::shared_ptr< MockBackendProfilingContext > shared)
DataLayout
Definition: Types.hpp:62
bool IsOutputSupported(const TensorInfo &, Optional< std::string &>) const override
A Convolution2dDescriptor for the Convolution2dLayer.
IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(const IBackendInternal::IMemoryManagerSharedPtr &memoryManager=nullptr) const override
bool IsInputSupported(const TensorInfo &, Optional< std::string &>) const override
IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override
IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions &) const override
Create the runtime context of the backend.
OptimizationViews OptimizeSubgraphView(const SubgraphView &subgraph) const override
Copyright (c) 2021 ARM Limited and Contributors.
std::unique_ptr< IMemoryManager > IMemoryManagerUniquePtr
void IgnoreUnused(Ts &&...)
const BackendId & GetId() const override
Definition: MockBackend.hpp:27
Base class for all descriptors.
Definition: Descriptors.hpp:22
The SubgraphView class represents a subgraph of a Graph.
std::vector< TensorInfo > m_InputTensorInfos
const char * GetBackendId()
std::unique_ptr< ICustomAllocator > GetDefaultAllocator() const override
Returns the default memory allocator for the backend.
MockBackend()=default
std::shared_ptr< IMemoryManager > IMemoryManagerSharedPtr
static const BackendId & GetIdStatic()
Definition: MockBackend.cpp:17
ARMNN_NO_DEPRECATE_WARN_BEGIN struct ARMNN_DEPRECATED_MSG_REMOVAL_DATE("ResizeBilinearQueueDescriptor is deprecated use ResizeQueueDescriptor instead", "22.08") ResizeBilinearQueueDescriptor
std::vector< TensorInfo > m_OutputTensorInfos
bool IsConvolution2dSupported(const TensorInfo &, const TensorInfo &, const Convolution2dDescriptor &, const TensorInfo &, const Optional< TensorInfo > &, Optional< std::string &>) const override
static MockBackendProfilingService & Instance()
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...
std::vector< arm::pipe::Timestamp > ReportCounterValues()
bool IsConvolution2dSupported(const BackendId &backend, const TensorInfo &input, const TensorInfo &output, const Convolution2dDescriptor &descriptor, const TensorInfo &weights, const Optional< TensorInfo > &biases, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.
bool IsAdditionSupported(const TensorInfo &, const TensorInfo &, const TensorInfo &, Optional< std::string &>) const override
IBackendInternal::IBackendProfilingContextPtr CreateBackendProfilingContext(const IRuntime::CreationOptions &creationOptions, IBackendProfilingPtr &backendProfiling) override
Create context specifically used for profiling interaction from backends.
std::shared_ptr< ILayerSupport > ILayerSupportSharedPtr
bool IsInputSupported(const BackendId &backend, const TensorInfo &input, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.
MockBackendProfilingContext * GetContext()
std::unique_ptr< arm::pipe::IBackendProfiling > IBackendProfilingPtr
EmptyOptional is used to initialize the Optional class in case we want to have default value for an O...
Definition: Optional.hpp:32
arm::pipe::Optional< std::string > ActivateCounters(uint32_t capturePeriod, const std::vector< uint16_t > &counterIds)
Contains information about TensorInfos of a layer.
IBackendInternal::IBackendProfilingPtr & GetBackendProfiling()
#define ARMNN_DEPRECATED_MSG(message)
Definition: Deprecated.hpp:43
bool IsAdditionSupported(const BackendId &backend, const TensorInfo &input0, const TensorInfo &input1, const TensorInfo &output, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.
bool EnableTimelineReporting(bool isEnabled)
bool SupportsSubTensors() const override
Definition: MockBackend.hpp:60
bool IsLayerSupported(const LayerType &type, const std::vector< TensorInfo > &infos, const BaseDescriptor &descriptor, const Optional< LstmInputParamsInfo > &, const Optional< QuantizedLstmInputParamsInfo > &, Optional< std::string &> reasonIfUnsupported) const override
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
uint16_t RegisterCounters(uint16_t currentMaxGlobalCounterId)
std::unique_ptr< IBackendContext > IBackendContextPtr