ArmNN
 22.02
ClBackend Class Reference

#include <ClBackend.hpp>

Inheritance diagram for ClBackend:
IBackendInternal IBackend

Classes

class  ClBackendCustomAllocatorMemoryRegion
 
class  ClBackendCustomAllocatorWrapper
 

Public Member Functions

 ClBackend ()
 
 ClBackend (std::shared_ptr< ICustomAllocator > allocator)
 
 ~ClBackend ()=default
 
const BackendIdGetId () const override
 
IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager () const override
 
IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory (const IBackendInternal::IMemoryManagerSharedPtr &memoryManager=nullptr) const override
 
IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory (TensorHandleFactoryRegistry &registry) const override
 
IWorkloadFactoryPtr CreateWorkloadFactory (const IMemoryManagerSharedPtr &memoryManager, const ModelOptions &modelOptions) const override
 
IWorkloadFactoryPtr CreateWorkloadFactory (class TensorHandleFactoryRegistry &tensorHandleFactoryRegistry, const ModelOptions &modelOptions) const override
 
IWorkloadFactoryPtr CreateWorkloadFactory (class TensorHandleFactoryRegistry &tensorHandleFactoryRegistry, const ModelOptions &modelOptions, MemorySourceFlags inputFlags, MemorySourceFlags outputFlags) const override
 
std::vector< ITensorHandleFactory::FactoryIdGetHandleFactoryPreferences () const override
 (Optional) Returns a vector of supported TensorHandleFactory ids in preference order. More...
 
void RegisterTensorHandleFactories (TensorHandleFactoryRegistry &registry) override
 (Optional) Register TensorHandleFactories Either this method or CreateMemoryManager() and IWorkloadFactory::CreateTensor()/IWorkloadFactory::CreateSubtensor() methods must be implemented. More...
 
void RegisterTensorHandleFactories (TensorHandleFactoryRegistry &registry, MemorySourceFlags inputFlags, MemorySourceFlags outputFlags) override
 (Optional) Register TensorHandleFactories Either this method or CreateMemoryManager() and IWorkloadFactory::CreateTensor()/IWorkloadFactory::CreateSubtensor() methods must be implemented. More...
 
IBackendInternal::IBackendContextPtr CreateBackendContext (const IRuntime::CreationOptions &) const override
 Create the runtime context of the backend. More...
 
IBackendInternal::IBackendProfilingContextPtr CreateBackendProfilingContext (const IRuntime::CreationOptions &, IBackendProfilingPtr &backendProfiling) override
 Create context specifically used for profiling interaction from backends. More...
 
IBackendInternal::ILayerSupportSharedPtr GetLayerSupport () const override
 
IBackendInternal::ILayerSupportSharedPtr GetLayerSupport (const ModelOptions &modelOptions) const override
 
OptimizationViews OptimizeSubgraphView (const SubgraphView &subgraph, const ModelOptions &modelOptions) const override
 
IBackendInternal::IBackendSpecificModelContextPtr CreateBackendSpecificModelContext (const ModelOptions &modelOptions) const override
 
std::unique_ptr< ICustomAllocatorGetDefaultAllocator () const override
 Returns the default memory allocator for the backend. More...
 
BackendCapabilities GetCapabilities () const override
 Returns a BackendCapability if the backend lists the capability The BackendCapability must then be inspected to check whether or not that BackendCapability is supported Otherwise returns an EmptyOptional if the BackendCapability is unlisted. More...
 
virtual bool UseCustomMemoryAllocator (std::shared_ptr< ICustomAllocator > allocator, armnn::Optional< std::string &> errMsg) override
 Signals the backend to use a custom memory allocator provided by the user. More...
 
virtual unsigned int GetNumberOfCacheFiles () const override
 Returns the number of files cached if backend supports caching. More...
 
- Public Member Functions inherited from IBackendInternal
 ~IBackendInternal () override=default
 Allow backends created by the factory function to be destroyed through IBackendInternal. More...
 
virtual OptimizationViews OptimizeSubgraphView (const SubgraphView &subgraph) const
 
bool SupportsTensorAllocatorAPI () const
 
ITensorHandleFactory::FactoryId GetBackwardCompatibleFavoriteHandleFactory ()
 
virtual bool HasCapability (BackendCapability) const
 Returns true if backend support the capability false otherwise. More...
 

Static Public Member Functions

static const BackendIdGetIdStatic ()
 
- Static Public Member Functions inherited from IBackendInternal
static constexpr BackendVersion GetApiVersion ()
 Returns the version of the Backend API. More...
 

Public Attributes

std::shared_ptr< ClBackendCustomAllocatorWrapperm_CustomAllocator
 
bool m_UsingCustomAllocator = false
 

Additional Inherited Members

- Public Types inherited from IBackendInternal
using IWorkloadFactoryPtr = std::unique_ptr< IWorkloadFactory >
 
using IBackendContextPtr = std::unique_ptr< IBackendContext >
 
using IBackendProfilingContextPtr = std::shared_ptr< armnn::profiling::IBackendProfilingContext >
 This is the bridge between backend and backend profiling we'll keep it in the backend namespace. More...
 
using IBackendProfilingPtr = std::unique_ptr< armnn::profiling::IBackendProfiling >
 
using ILayerSupportSharedPtr = std::shared_ptr< ILayerSupport >
 
using IBackendSpecificModelContextPtr = std::shared_ptr< IBackendModelContext >
 
using IMemoryManagerUniquePtr = std::unique_ptr< IMemoryManager >
 
using IMemoryManagerSharedPtr = std::shared_ptr< IMemoryManager >
 
- Protected Member Functions inherited from IBackendInternal
 IBackendInternal ()=default
 Creation must be done through a specific backend interface. More...
 
- Protected Member Functions inherited from IBackend
 IBackend ()
 
virtual ~IBackend ()
 

Detailed Description

Definition at line 37 of file ClBackend.hpp.

Constructor & Destructor Documentation

◆ ClBackend() [1/2]

ClBackend ( )
inline

Definition at line 40 of file ClBackend.hpp.

40 : m_CustomAllocator(nullptr) {};
std::shared_ptr< ClBackendCustomAllocatorWrapper > m_CustomAllocator
Definition: ClBackend.hpp:299

◆ ClBackend() [2/2]

ClBackend ( std::shared_ptr< ICustomAllocator allocator)
inline

Definition at line 41 of file ClBackend.hpp.

References ClBackend::GetIdStatic(), ClBackend::UseCustomMemoryAllocator(), and ClBackend::~ClBackend().

42  {
43  std::string err;
44  UseCustomMemoryAllocator(allocator, err);
45  }
virtual bool UseCustomMemoryAllocator(std::shared_ptr< ICustomAllocator > allocator, armnn::Optional< std::string &> errMsg) override
Signals the backend to use a custom memory allocator provided by the user.
Definition: ClBackend.hpp:98

◆ ~ClBackend()

~ClBackend ( )
default

Referenced by ClBackend::ClBackend().

Member Function Documentation

◆ CreateBackendContext()

IBackendInternal::IBackendContextPtr CreateBackendContext ( const IRuntime::CreationOptions ) const
overridevirtual

Create the runtime context of the backend.

Implementations may return a default-constructed IBackendContextPtr if no context is needed at runtime. Implementations must throw BackendUnavailableException if the backend cannot be used (for example, necessary accelerator hardware is not present). The default implementation always returns a default-constructed pointer.

Reimplemented from IBackendInternal.

Definition at line 236 of file ClBackend.cpp.

Referenced by ClBackend::GetId().

237 {
238  return IBackendContextPtr{new ClBackendContext{options}};
239 }
std::unique_ptr< IBackendContext > IBackendContextPtr

◆ CreateBackendProfilingContext()

IBackendInternal::IBackendProfilingContextPtr CreateBackendProfilingContext ( const IRuntime::CreationOptions creationOptions,
IBackendProfilingPtr backendProfiling 
)
overridevirtual

Create context specifically used for profiling interaction from backends.

Reimplemented from IBackendInternal.

Definition at line 241 of file ClBackend.cpp.

Referenced by ClBackend::GetId().

243 {
245 }
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...

◆ CreateBackendSpecificModelContext()

IBackendInternal::IBackendSpecificModelContextPtr CreateBackendSpecificModelContext ( const ModelOptions modelOptions) const
overridevirtual

Reimplemented from IBackendInternal.

Definition at line 247 of file ClBackend.cpp.

Referenced by ClBackend::CreateWorkloadFactory(), ClBackend::GetId(), ClBackend::GetLayerSupport(), and ClBackend::OptimizeSubgraphView().

249 {
250  return IBackendSpecificModelContextPtr{new ClBackendModelContext{modelOptions}};
251 }
std::shared_ptr< IBackendModelContext > IBackendSpecificModelContextPtr

◆ CreateMemoryManager()

IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager ( ) const
overridevirtual

Reimplemented from IBackendInternal.

Definition at line 51 of file ClBackend.cpp.

References ClBackend::m_CustomAllocator, and ClBackend::m_UsingCustomAllocator.

Referenced by ClBackend::GetId().

52 {
54  {
55  return std::make_unique<ClMemoryManager>(m_CustomAllocator);
56  }
57  return std::make_unique<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
58 }
std::shared_ptr< ClBackendCustomAllocatorWrapper > m_CustomAllocator
Definition: ClBackend.hpp:299
bool m_UsingCustomAllocator
Definition: ClBackend.hpp:300

◆ CreateWorkloadFactory() [1/5]

IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory ( const IBackendInternal::IMemoryManagerSharedPtr memoryManager = nullptr) const
overridevirtual

Implements IBackendInternal.

Definition at line 60 of file ClBackend.cpp.

Referenced by ClBackend::GetId().

62 {
63  return std::make_unique<ClWorkloadFactory>(
64  PolymorphicPointerDowncast<ClMemoryManager>(memoryManager));
65 }

◆ CreateWorkloadFactory() [2/5]

IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory ( TensorHandleFactoryRegistry registry) const
overridevirtual

Reimplemented from IBackendInternal.

Definition at line 74 of file ClBackend.cpp.

References ClBackend::m_CustomAllocator, ClBackend::m_UsingCustomAllocator, armnn::Malloc, TensorHandleFactoryRegistry::RegisterCopyAndImportFactoryPair(), TensorHandleFactoryRegistry::RegisterFactory(), and TensorHandleFactoryRegistry::RegisterMemoryManager().

76 {
77  std::shared_ptr<ClMemoryManager> memoryManager;
79  {
80  memoryManager = std::make_shared<ClMemoryManager>(m_CustomAllocator);
81  }
82  else
83  {
84  memoryManager = std::make_shared<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
85  }
86 
87  std::unique_ptr<ITensorHandleFactory> factory = std::make_unique<ClTensorHandleFactory>(memoryManager);
88  std::unique_ptr<ITensorHandleFactory> importFactory = std::make_unique<ClImportTensorHandleFactory>(
89  static_cast<MemorySourceFlags>(MemorySource::Malloc), static_cast<MemorySourceFlags>(MemorySource::Malloc));
90 
91  registry.RegisterCopyAndImportFactoryPair(factory->GetId(), importFactory->GetId());
92  registry.RegisterCopyAndImportFactoryPair(importFactory->GetId(), factory->GetId());
93 
94  registry.RegisterMemoryManager(memoryManager);
95  registry.RegisterFactory(std::move(factory));
96  registry.RegisterFactory(std::move(importFactory));
97 
98  return std::make_unique<ClWorkloadFactory>(
99  PolymorphicPointerDowncast<ClMemoryManager>(memoryManager));
100 }
std::shared_ptr< ClBackendCustomAllocatorWrapper > m_CustomAllocator
Definition: ClBackend.hpp:299
unsigned int MemorySourceFlags
bool m_UsingCustomAllocator
Definition: ClBackend.hpp:300

◆ CreateWorkloadFactory() [3/5]

IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory ( const IMemoryManagerSharedPtr memoryManager,
const ModelOptions modelOptions 
) const
overridevirtual

Reimplemented from IBackendInternal.

Definition at line 67 of file ClBackend.cpp.

References ClBackend::CreateBackendSpecificModelContext().

69 {
70  return std::make_unique<ClWorkloadFactory>(
71  PolymorphicPointerDowncast<ClMemoryManager>(memoryManager), CreateBackendSpecificModelContext(modelOptions));
72 }
IBackendInternal::IBackendSpecificModelContextPtr CreateBackendSpecificModelContext(const ModelOptions &modelOptions) const override
Definition: ClBackend.cpp:247

◆ CreateWorkloadFactory() [4/5]

IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory ( class TensorHandleFactoryRegistry tensorHandleFactoryRegistry,
const ModelOptions modelOptions 
) const
overridevirtual

Reimplemented from IBackendInternal.

Definition at line 102 of file ClBackend.cpp.

References ClBackend::CreateBackendSpecificModelContext(), ClBackend::m_CustomAllocator, ClBackend::m_UsingCustomAllocator, armnn::Malloc, TensorHandleFactoryRegistry::RegisterCopyAndImportFactoryPair(), TensorHandleFactoryRegistry::RegisterFactory(), and TensorHandleFactoryRegistry::RegisterMemoryManager().

104 {
105  std::shared_ptr<ClMemoryManager> memoryManager;
107  {
108  memoryManager = std::make_shared<ClMemoryManager>(m_CustomAllocator);
109  }
110  else
111  {
112  memoryManager = std::make_shared<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
113  }
114 
115  std::unique_ptr<ITensorHandleFactory> factory = std::make_unique<ClTensorHandleFactory>(memoryManager);
116  std::unique_ptr<ITensorHandleFactory> importFactory = std::make_unique<ClImportTensorHandleFactory>(
117  static_cast<MemorySourceFlags>(MemorySource::Malloc), static_cast<MemorySourceFlags>(MemorySource::Malloc));
118 
119  registry.RegisterCopyAndImportFactoryPair(factory->GetId(), importFactory->GetId());
120  registry.RegisterCopyAndImportFactoryPair(importFactory->GetId(), factory->GetId());
121 
122  registry.RegisterMemoryManager(memoryManager);
123  registry.RegisterFactory(std::move(factory));
124  registry.RegisterFactory(std::move(importFactory));
125 
126  return std::make_unique<ClWorkloadFactory>(
127  PolymorphicPointerDowncast<ClMemoryManager>(memoryManager), CreateBackendSpecificModelContext(modelOptions));
128 }
std::shared_ptr< ClBackendCustomAllocatorWrapper > m_CustomAllocator
Definition: ClBackend.hpp:299
unsigned int MemorySourceFlags
IBackendInternal::IBackendSpecificModelContextPtr CreateBackendSpecificModelContext(const ModelOptions &modelOptions) const override
Definition: ClBackend.cpp:247
bool m_UsingCustomAllocator
Definition: ClBackend.hpp:300

◆ CreateWorkloadFactory() [5/5]

IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory ( class TensorHandleFactoryRegistry tensorHandleFactoryRegistry,
const ModelOptions modelOptions,
MemorySourceFlags  inputFlags,
MemorySourceFlags  outputFlags 
) const
overridevirtual

Reimplemented from IBackendInternal.

Definition at line 130 of file ClBackend.cpp.

References ClBackend::CreateBackendSpecificModelContext(), ClBackend::m_CustomAllocator, ClBackend::m_UsingCustomAllocator, armnn::Malloc, TensorHandleFactoryRegistry::RegisterCopyAndImportFactoryPair(), TensorHandleFactoryRegistry::RegisterFactory(), TensorHandleFactoryRegistry::RegisterMemoryManager(), and armnn::Undefined.

135 {
136  // To allow force import if inputFlags/outputFlags are Undefined, set it as Malloc
137  if (inputFlags == static_cast<MemorySourceFlags>(MemorySource::Undefined))
138  {
139  inputFlags = static_cast<MemorySourceFlags>(MemorySource::Malloc);
140  }
141  if (outputFlags == static_cast<MemorySourceFlags>(MemorySource::Undefined))
142  {
143  outputFlags = static_cast<MemorySourceFlags>(MemorySource::Malloc);
144  }
145  std::shared_ptr<ClMemoryManager> memoryManager;
147  {
148  memoryManager = std::make_shared<ClMemoryManager>(m_CustomAllocator);
149  }
150  else
151  {
152  memoryManager = std::make_shared<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
153  }
154 
155  std::unique_ptr<ITensorHandleFactory> factory = std::make_unique<ClTensorHandleFactory>(memoryManager);
156  std::unique_ptr<ITensorHandleFactory> importFactory = std::make_unique<ClImportTensorHandleFactory>(
157  inputFlags, outputFlags);
158 
159  registry.RegisterCopyAndImportFactoryPair(factory->GetId(), importFactory->GetId());
160  registry.RegisterCopyAndImportFactoryPair(importFactory->GetId(), factory->GetId());
161 
162  registry.RegisterMemoryManager(memoryManager);
163  registry.RegisterFactory(std::move(factory));
164  registry.RegisterFactory(std::move(importFactory));
165 
166  return std::make_unique<ClWorkloadFactory>(
167  PolymorphicPointerDowncast<ClMemoryManager>(memoryManager), CreateBackendSpecificModelContext(modelOptions));
168 }
std::shared_ptr< ClBackendCustomAllocatorWrapper > m_CustomAllocator
Definition: ClBackend.hpp:299
unsigned int MemorySourceFlags
IBackendInternal::IBackendSpecificModelContextPtr CreateBackendSpecificModelContext(const ModelOptions &modelOptions) const override
Definition: ClBackend.cpp:247
bool m_UsingCustomAllocator
Definition: ClBackend.hpp:300

◆ GetCapabilities()

BackendCapabilities GetCapabilities ( ) const
inlineoverridevirtual

Returns a BackendCapability if the backend lists the capability The BackendCapability must then be inspected to check whether or not that BackendCapability is supported Otherwise returns an EmptyOptional if the BackendCapability is unlisted.

Reimplemented from IBackendInternal.

Definition at line 93 of file ClBackend.hpp.

References armnn::gpuAccCapabilities.

94  {
95  return gpuAccCapabilities;
96  };
const BackendCapabilities gpuAccCapabilities("GpuAcc", { {"NonConstWeights", false}, {"AsyncExecution", false}, {"ProtectedContentAllocation", true}, {"ConstantTensorsAsInputs", false}, {"PreImportIOTensors", false}, {"ExternallyManagedMemory", true}, {"MultiAxisPacking", false}, {"SingleAxisPacking", true} })

◆ GetDefaultAllocator()

std::unique_ptr< ICustomAllocator > GetDefaultAllocator ( ) const
overridevirtual

Returns the default memory allocator for the backend.

Returns
- Returns unique pointer to the Default Allocator of the Backend

Reimplemented from IBackendInternal.

Definition at line 271 of file ClBackend.cpp.

Referenced by ClBackend::GetId().

272 {
273  return std::make_unique<ClBackendDefaultAllocator>();
274 }

◆ GetHandleFactoryPreferences()

std::vector< ITensorHandleFactory::FactoryId > GetHandleFactoryPreferences ( ) const
overridevirtual

(Optional) Returns a vector of supported TensorHandleFactory ids in preference order.

Reimplemented from IBackendInternal.

Definition at line 170 of file ClBackend.cpp.

References ClTensorHandleFactory::GetIdStatic(), and ClImportTensorHandleFactory::GetIdStatic().

Referenced by ClBackend::GetId().

171 {
172  return std::vector<ITensorHandleFactory::FactoryId> {ClTensorHandleFactory::GetIdStatic(),
174 }
static const FactoryId & GetIdStatic()

◆ GetId()

◆ GetIdStatic()

const BackendId & GetIdStatic ( )
static

Definition at line 45 of file ClBackend.cpp.

References armnn::ClBackendId().

Referenced by ClBackend::ClBackend(), and ClBackend::GetId().

46 {
47  static const BackendId s_Id{ClBackendId()};
48  return s_Id;
49 }
constexpr const char * ClBackendId()
Definition: ClBackendId.hpp:10

◆ GetLayerSupport() [1/2]

IBackendInternal::ILayerSupportSharedPtr GetLayerSupport ( ) const
overridevirtual

Implements IBackendInternal.

Definition at line 253 of file ClBackend.cpp.

Referenced by ClBackend::GetId().

254 {
255  static ILayerSupportSharedPtr layerSupport
256  {
258  };
259  return layerSupport;
260 }
std::shared_ptr< IBackendModelContext > IBackendSpecificModelContextPtr
std::shared_ptr< ILayerSupport > ILayerSupportSharedPtr

◆ GetLayerSupport() [2/2]

IBackendInternal::ILayerSupportSharedPtr GetLayerSupport ( const ModelOptions modelOptions) const
overridevirtual

Reimplemented from IBackendInternal.

Definition at line 262 of file ClBackend.cpp.

References ClBackend::CreateBackendSpecificModelContext().

263 {
264  static ILayerSupportSharedPtr layerSupport
265  {
266  new ClLayerSupport(CreateBackendSpecificModelContext(modelOptions))
267  };
268  return layerSupport;
269 }
IBackendInternal::IBackendSpecificModelContextPtr CreateBackendSpecificModelContext(const ModelOptions &modelOptions) const override
Definition: ClBackend.cpp:247
std::shared_ptr< ILayerSupport > ILayerSupportSharedPtr

◆ GetNumberOfCacheFiles()

virtual unsigned int GetNumberOfCacheFiles ( ) const
inlineoverridevirtual

Returns the number of files cached if backend supports caching.

Returns
- Returns 0 if backend does not support caching otherwise number of files cached

Reimplemented from IBackendInternal.

Definition at line 110 of file ClBackend.hpp.

110 { return 1; }

◆ OptimizeSubgraphView()

OptimizationViews OptimizeSubgraphView ( const SubgraphView subgraph,
const ModelOptions modelOptions 
) const
overridevirtual

Reimplemented from IBackendInternal.

Definition at line 276 of file ClBackend.cpp.

References armnn::Activation, armnn::Addition, OptimizationViews::AddUntouchedSubgraph(), armnn::BatchNormalization, SubgraphView::beginIConnectable(), Layer::BeginOutputSlots(), armnn::ClAdditionValidate(), armnn::ClBatchNormalizationValidate(), armnn::ClConvolution2dWorkloadValidate(), armnn::ClDepthwiseConvolutionWorkloadValidate(), armnn::ClDivisionWorkloadValidate(), armnn::ClFullyConnectedWorkloadValidate(), armnn::ClMultiplicationWorkloadValidate(), armnn::ClSubtractionValidate(), armnn::Convolution2d, ClBackend::CreateBackendSpecificModelContext(), armnn::DepthwiseConvolution2d, armnn::Division, SubgraphView::endIConnectable(), Layer::EndOutputSlots(), armnn::FullyConnected, Layer::GetAdditionalInformation(), InputSlot::GetConnectedOutputSlot(), Layer::GetGuid(), Layer::GetInputSlot(), Layer::GetName(), LayerWithParameters< Parameters >::GetParameters(), OptimizationViews::GetSubstitutions(), OutputSlot::GetTensorInfo(), Layer::GetType(), ClBackendModelContext::IsFastMathEnabled(), BatchNormalizationLayer::m_Beta, DepthwiseConvolution2dLayer::m_Bias, Convolution2dLayer::m_Bias, FullyConnectedLayer::m_Bias, FullyConnectedDescriptor::m_BiasEnabled, Convolution2dDescriptor::m_BiasEnabled, DepthwiseConvolution2dDescriptor::m_BiasEnabled, BatchNormalizationLayer::m_Gamma, BatchNormalizationLayer::m_Mean, BatchNormalizationLayer::m_Variance, DepthwiseConvolution2dLayer::m_Weight, Convolution2dLayer::m_Weight, FullyConnectedLayer::m_Weight, armnn::Multiplication, armnn::Reduce, armnn::ReportUntouchedLayers(), and armnn::Subtraction.

Referenced by ClBackend::GetId().

278 {
279  OptimizationViews optimizationViews;
280 
281  auto it = subgraph.endIConnectable();
282  bool isFastMathEnabled = false;
283  std::map<LayerGuid, Layer*> untouched;
284 
285  while (it != subgraph.beginIConnectable())
286  {
287  --it;
288  Layer& base = *(PolymorphicDowncast<Layer*>(*it));
289  untouched.insert({base.GetGuid(), &base});
290  }
291 
292  it = subgraph.endIConnectable();
293 #if defined(ARMCOMPUTECL_ENABLED)
295 
296  if (modelContextPtr)
297  {
298  auto clModelOptions = dynamic_cast<ClBackendModelContext*>(modelContextPtr.get());
299  if (clModelOptions)
300  {
301  isFastMathEnabled = clModelOptions->IsFastMathEnabled();
302  }
303  }
304 #endif
305  while (it != subgraph.beginIConnectable())
306  {
307  --it;
308  Layer& base = *(PolymorphicDowncast<Layer*>(*it));
309 
310  // Fuse activation into previous layer if supported by backend
311  if ((base.GetType() == LayerType::DepthwiseConvolution2d || base.GetType() == LayerType::Convolution2d
312  || base.GetType() == LayerType::BatchNormalization || base.GetType() == LayerType::FullyConnected
313  || base.GetType() == LayerType::Addition || base.GetType() == LayerType::Multiplication
314  || base.GetType() == LayerType::Subtraction || base.GetType() == LayerType::Division)
315  && (base.GetAdditionalInformation<ActivationDescriptor>() == nullptr))
316  {
317  for (auto output = base.BeginOutputSlots(); output != base.EndOutputSlots(); ++output)
318  {
319  if (output->GetNumConnections() == 1)
320  {
321  for (auto&& childInput : output->GetConnections())
322  {
323  if ((childInput->GetOwningLayer().GetType() == LayerType::Activation) &&
324  (checkDataTypeInputandOutput(childInput->GetOwningLayer())))
325  {
326  Layer& child = childInput->GetOwningLayer();
327 
328  auto* activationLayer = PolymorphicDowncast<ActivationLayer*>(&child);
329 
330  const std::string name = std::string("fused-") + child.GetName() + std::string("-into-") +
331  base.GetName();
332 
333  // Get params from activation layer
334  ActivationDescriptor activationDesc = activationLayer->GetParameters();
335 
336  if (base.GetType() == LayerType::Convolution2d)
337  {
338  Convolution2dLayer* baseLayer = PolymorphicDowncast<Convolution2dLayer*>(&base);
339 
340  Optional<TensorInfo> biases;
341 
342  if (baseLayer->GetParameters().m_BiasEnabled)
343  {
344  biases = baseLayer->m_Bias->GetTensorInfo();
345  }
346 
348  baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
349  activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
350  baseLayer->GetParameters(),
351  baseLayer->m_Weight->GetTensorInfo(),
352  biases,
353  isFastMathEnabled,
354  &activationDesc);
355 
356  if (status)
357  {
358  FuseConvolution2dLayer<Convolution2dLayer>(optimizationViews,
359  baseLayer,
360  activationLayer,
361  activationDesc,
362  name);
363  untouched.erase(baseLayer->GetGuid());
364  untouched.erase(activationLayer->GetGuid());
365  }
366  }
367  else if (base.GetType() == LayerType::DepthwiseConvolution2d)
368  {
369  DepthwiseConvolution2dLayer* baseLayer =
370  PolymorphicDowncast<DepthwiseConvolution2dLayer*>(&base);
371 
372  Optional<TensorInfo> biases;
373 
374  if (baseLayer->GetParameters().m_BiasEnabled)
375  {
376  biases = baseLayer->m_Bias->GetTensorInfo();
377  }
378 
380  baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
381  activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
382  baseLayer->GetParameters(),
383  baseLayer->m_Weight->GetTensorInfo(),
384  biases,
385  &activationDesc);
386 
387  if (status)
388  {
389  FuseDepthwiseConvolution2dLayer<DepthwiseConvolution2dLayer>(optimizationViews,
390  baseLayer,
391  activationLayer,
392  activationDesc,
393  name);
394  untouched.erase(baseLayer->GetGuid());
395  untouched.erase(activationLayer->GetGuid());
396  }
397  }
398  else if (base.GetType() == LayerType::FullyConnected)
399  {
400  FullyConnectedLayer* baseLayer = PolymorphicDowncast<FullyConnectedLayer*>(&base);
401 
402  Optional<TensorInfo> biases;
403 
404  if (baseLayer->GetParameters().m_BiasEnabled)
405  {
406  biases = baseLayer->m_Bias->GetTensorInfo();
407  }
408 
410  baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
411  activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
412  baseLayer->m_Weight->GetTensorInfo(),
413  biases,
414  baseLayer->GetParameters(),
415  &activationDesc);
416 
417  if (status)
418  {
419  FuseFullyConnectedLayer<FullyConnectedLayer>(optimizationViews,
420  baseLayer,
421  activationLayer,
422  activationDesc,
423  name);
424  untouched.erase(baseLayer->GetGuid());
425  untouched.erase(activationLayer->GetGuid());
426  }
427  }
428  else if (base.GetType() == LayerType::BatchNormalization)
429  {
430  BatchNormalizationLayer* baseLayer =
431  PolymorphicDowncast<BatchNormalizationLayer*>(&base);
432 
434  baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
435  activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
436  baseLayer->m_Mean->GetTensorInfo(),
437  baseLayer->m_Variance->GetTensorInfo(),
438  baseLayer->m_Beta->GetTensorInfo(),
439  baseLayer->m_Gamma->GetTensorInfo(),
440  baseLayer->GetParameters(),
441  &activationDesc);
442 
443  if (status)
444  {
445  BatchNormalizationLayer* replacementLayer =
446  FuseBatchNormalizationLayer<BatchNormalizationLayer>(optimizationViews,
447  baseLayer,
448  activationLayer,
449  activationDesc,
450  name);
451 
452  replacementLayer->m_Beta = std::move(baseLayer->m_Beta);
453  replacementLayer->m_Gamma = std::move(baseLayer->m_Gamma);
454  replacementLayer->m_Mean = std::move(baseLayer->m_Mean);
455  replacementLayer->m_Variance = std::move(baseLayer->m_Variance);
456  untouched.erase(baseLayer->GetGuid());
457  untouched.erase(activationLayer->GetGuid());
458  }
459  }
460  else if (base.GetType() == LayerType::Addition)
461  {
462  AdditionLayer* baseLayer = PolymorphicDowncast<AdditionLayer*>(&base);
463 
465  baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
466  baseLayer->GetInputSlot(1).GetConnectedOutputSlot()->GetTensorInfo(),
467  activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
468  &activationDesc);
469 
470  if (status)
471  {
472  FuseAdditionLayer<AdditionLayer>(optimizationViews,
473  baseLayer,
474  activationLayer,
475  activationDesc,
476  name);
477  untouched.erase(baseLayer->GetGuid());
478  untouched.erase(activationLayer->GetGuid());
479  }
480  }
481  else if (base.GetType() == LayerType::Division)
482  {
483  DivisionLayer* baseLayer = PolymorphicDowncast<DivisionLayer*>(&base);
484 
486  baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
487  baseLayer->GetInputSlot(1).GetConnectedOutputSlot()->GetTensorInfo(),
488  activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
489  &activationDesc);
490 
491  if (status)
492  {
493  FuseDivisionLayer<DivisionLayer>(optimizationViews,
494  baseLayer,
495  activationLayer,
496  activationDesc,
497  name);
498  untouched.erase(baseLayer->GetGuid());
499  untouched.erase(activationLayer->GetGuid());
500  }
501  }
502  else if (base.GetType() == LayerType::Multiplication)
503  {
504  MultiplicationLayer* baseLayer = PolymorphicDowncast<MultiplicationLayer*>(&base);
505 
507  baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
508  baseLayer->GetInputSlot(1).GetConnectedOutputSlot()->GetTensorInfo(),
509  activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
510  &activationDesc);
511 
512  if (status)
513  {
514  FuseMultiplicationLayer<MultiplicationLayer>(optimizationViews,
515  baseLayer,
516  activationLayer,
517  activationDesc,
518  name);
519  untouched.erase(baseLayer->GetGuid());
520  untouched.erase(activationLayer->GetGuid());
521  }
522  }
523  else if (base.GetType() == LayerType::Subtraction)
524  {
525  SubtractionLayer* baseLayer = PolymorphicDowncast<SubtractionLayer*>(&base);
526 
528  baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
529  baseLayer->GetInputSlot(1).GetConnectedOutputSlot()->GetTensorInfo(),
530  activationLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo(),
531  &activationDesc);
532 
533  if (status)
534  {
535  FuseSubtractionLayer<SubtractionLayer>(optimizationViews,
536  baseLayer,
537  activationLayer,
538  activationDesc,
539  name);
540  untouched.erase(baseLayer->GetGuid());
541  untouched.erase(activationLayer->GetGuid());
542  }
543  }
544  }
545  }
546  }
547  }
548  }
549 
550  // Separate reduce layer with multiple axes into multiple reduce layers with 1 axis.
551  if (base.GetType() == LayerType::Reduce)
552  {
553  ReduceLayer* baseLayer = PolymorphicDowncast<ReduceLayer*>(&base);
554  ReduceDescriptor reduceDescriptor = baseLayer->GetParameters();
555 
556  if (!reduceDescriptor.m_vAxis.empty() && reduceDescriptor.m_vAxis.size() > 1)
557  {
558  // Add new layers to the graph and connect them.
559  std::vector<IConnectableLayer*> layers = ChainReduceLayers<ReduceLayer>(optimizationViews,
560  baseLayer,
561  reduceDescriptor);
562 
563  // Replace existing baselayer with new subgraph.
564  ReplaceLayers<ReduceLayer>(optimizationViews, baseLayer, layers);
565  untouched.erase(baseLayer->GetGuid());
566  }
567  }
568  }
569 
570  if (optimizationViews.GetSubstitutions().empty())
571  {
572  optimizationViews.AddUntouchedSubgraph(SubgraphView(subgraph));
573  }
574  else
575  {
576  ReportUntouchedLayers(optimizationViews, untouched);
577  }
578 
579  return optimizationViews;
580 }
arm_compute::Status ClAdditionValidate(const TensorInfo &input0, const TensorInfo &input1, const TensorInfo &output, const ActivationDescriptor *activationDescriptor)
arm_compute::Status ClDivisionWorkloadValidate(const TensorInfo &input0, const TensorInfo &input1, const TensorInfo &output, const ActivationDescriptor *activationDescriptor)
void ReportUntouchedLayers(OptimizationViews &optimizationViews, std::map< LayerGuid, Layer *> untouched)
arm_compute::Status ClSubtractionValidate(const TensorInfo &input0, const TensorInfo &input1, const TensorInfo &output, const ActivationDescriptor *activationDescriptor)
arm_compute::Status ClConvolution2dWorkloadValidate(const TensorInfo &input, const TensorInfo &output, const Convolution2dDescriptor &descriptor, const TensorInfo &weights, const Optional< TensorInfo > &biases, bool isFastMathEnabled, const ActivationDescriptor *activationDescriptor)
IBackendInternal::IBackendSpecificModelContextPtr CreateBackendSpecificModelContext(const ModelOptions &modelOptions) const override
Definition: ClBackend.cpp:247
std::shared_ptr< IBackendModelContext > IBackendSpecificModelContextPtr
arm_compute::Status ClMultiplicationWorkloadValidate(const TensorInfo &input0, const TensorInfo &input1, const TensorInfo &output, const ActivationDescriptor *activationDescriptor)
Status
enumeration
Definition: Types.hpp:29
arm_compute::Status ClFullyConnectedWorkloadValidate(const TensorInfo &input, const TensorInfo &output, const TensorInfo &weights, const Optional< TensorInfo > &biases, const FullyConnectedDescriptor &descriptor, const ActivationDescriptor *activationDescriptor)
arm_compute::Status ClBatchNormalizationValidate(const TensorInfo &input, const TensorInfo &output, const TensorInfo &mean, const TensorInfo &var, const TensorInfo &beta, const TensorInfo &gamma, const BatchNormalizationDescriptor &descriptor, const ActivationDescriptor *activationDescriptor)
arm_compute::Status ClDepthwiseConvolutionWorkloadValidate(const TensorInfo &input, const TensorInfo &output, const DepthwiseConvolution2dDescriptor &descriptor, const TensorInfo &weights, const Optional< TensorInfo > &biases, const ActivationDescriptor *activationDescriptor)

◆ RegisterTensorHandleFactories() [1/2]

void RegisterTensorHandleFactories ( TensorHandleFactoryRegistry )
overridevirtual

(Optional) Register TensorHandleFactories Either this method or CreateMemoryManager() and IWorkloadFactory::CreateTensor()/IWorkloadFactory::CreateSubtensor() methods must be implemented.

Reimplemented from IBackendInternal.

Definition at line 176 of file ClBackend.cpp.

References ClBackend::m_CustomAllocator, ClBackend::m_UsingCustomAllocator, armnn::Malloc, TensorHandleFactoryRegistry::RegisterCopyAndImportFactoryPair(), TensorHandleFactoryRegistry::RegisterFactory(), and TensorHandleFactoryRegistry::RegisterMemoryManager().

Referenced by ClBackend::GetId().

177 {
178  std::shared_ptr<ClMemoryManager> memoryManager;
180  {
181  memoryManager = std::make_shared<ClMemoryManager>(m_CustomAllocator);
182  }
183  else
184  {
185  memoryManager = std::make_shared<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
186  }
187 
188  std::unique_ptr<ITensorHandleFactory> factory = std::make_unique<ClTensorHandleFactory>(memoryManager);
189  std::unique_ptr<ITensorHandleFactory> importFactory = std::make_unique<ClImportTensorHandleFactory>(
190  static_cast<MemorySourceFlags>(MemorySource::Malloc), static_cast<MemorySourceFlags>(MemorySource::Malloc));
191 
192  registry.RegisterCopyAndImportFactoryPair(factory->GetId(), importFactory->GetId());
193  registry.RegisterCopyAndImportFactoryPair(importFactory->GetId(), factory->GetId());
194 
195  registry.RegisterMemoryManager(memoryManager);
196  registry.RegisterFactory(std::move(factory));
197  registry.RegisterFactory(std::move(importFactory));
198 
199 }
std::shared_ptr< ClBackendCustomAllocatorWrapper > m_CustomAllocator
Definition: ClBackend.hpp:299
unsigned int MemorySourceFlags
bool m_UsingCustomAllocator
Definition: ClBackend.hpp:300

◆ RegisterTensorHandleFactories() [2/2]

void RegisterTensorHandleFactories ( TensorHandleFactoryRegistry registry,
MemorySourceFlags  inputFlags,
MemorySourceFlags  outputFlags 
)
overridevirtual

(Optional) Register TensorHandleFactories Either this method or CreateMemoryManager() and IWorkloadFactory::CreateTensor()/IWorkloadFactory::CreateSubtensor() methods must be implemented.

Reimplemented from IBackendInternal.

Definition at line 201 of file ClBackend.cpp.

References ClBackend::m_CustomAllocator, ClBackend::m_UsingCustomAllocator, armnn::Malloc, TensorHandleFactoryRegistry::RegisterCopyAndImportFactoryPair(), TensorHandleFactoryRegistry::RegisterFactory(), TensorHandleFactoryRegistry::RegisterMemoryManager(), and armnn::Undefined.

204 {
205  // To allow force import if inputFlags/outputFlags are Undefined, set it as Malloc
206  if (inputFlags == static_cast<MemorySourceFlags>(MemorySource::Undefined))
207  {
208  inputFlags = static_cast<MemorySourceFlags>(MemorySource::Malloc);
209  }
210  if (outputFlags == static_cast<MemorySourceFlags>(MemorySource::Undefined))
211  {
212  outputFlags = static_cast<MemorySourceFlags>(MemorySource::Malloc);
213  }
214  std::shared_ptr<ClMemoryManager> memoryManager;
216  {
217  memoryManager = std::make_shared<ClMemoryManager>(m_CustomAllocator);
218  }
219  else
220  {
221  memoryManager = std::make_shared<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
222  }
223 
224  std::unique_ptr<ITensorHandleFactory> factory = std::make_unique<ClTensorHandleFactory>(memoryManager);
225  std::unique_ptr<ITensorHandleFactory> importFactory = std::make_unique<ClImportTensorHandleFactory>(
226  inputFlags, outputFlags);
227 
228  registry.RegisterCopyAndImportFactoryPair(factory->GetId(), importFactory->GetId());
229  registry.RegisterCopyAndImportFactoryPair(importFactory->GetId(), factory->GetId());
230 
231  registry.RegisterMemoryManager(memoryManager);
232  registry.RegisterFactory(std::move(factory));
233  registry.RegisterFactory(std::move(importFactory));
234 }
std::shared_ptr< ClBackendCustomAllocatorWrapper > m_CustomAllocator
Definition: ClBackend.hpp:299
unsigned int MemorySourceFlags
bool m_UsingCustomAllocator
Definition: ClBackend.hpp:300

◆ UseCustomMemoryAllocator()

virtual bool UseCustomMemoryAllocator ( std::shared_ptr< ICustomAllocator allocator,
armnn::Optional< std::string &>  errMsg 
)
inlineoverridevirtual

Signals the backend to use a custom memory allocator provided by the user.

Parameters
allocator- a pointer to the provided ICustomAllocator to use with this backend
errMsg- Optional string variable to return error messages
Returns
- Returns true if switching to custom allocator was successful

Reimplemented from IBackendInternal.

Definition at line 98 of file ClBackend.hpp.

References ARMNN_LOG, armnn::IgnoreUnused(), armnn::info, ClBackend::m_CustomAllocator, and ClBackend::m_UsingCustomAllocator.

Referenced by ClBackend::ClBackend().

100  {
101  IgnoreUnused(errMsg);
102  ARMNN_LOG(info) << "Using Custom Allocator for ClBackend";
103 
104  // Set flag to signal the backend to use a custom memory allocator
105  m_CustomAllocator = std::make_shared<ClBackendCustomAllocatorWrapper>(std::move(allocator));
106  m_UsingCustomAllocator = true;
107  return m_UsingCustomAllocator;
108  }
#define ARMNN_LOG(severity)
Definition: Logging.hpp:205
std::shared_ptr< ClBackendCustomAllocatorWrapper > m_CustomAllocator
Definition: ClBackend.hpp:299
void IgnoreUnused(Ts &&...)
bool m_UsingCustomAllocator
Definition: ClBackend.hpp:300

Member Data Documentation

◆ m_CustomAllocator

◆ m_UsingCustomAllocator


The documentation for this class was generated from the following files: