ArmNN
 25.02
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
TosaRefBackend.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2022-2024 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "TosaRefBackend.hpp"
7 #include "TosaRefBackendId.hpp"
11 
19 
20 #include <Optimizer.hpp>
21 
22 namespace armnn
23 {
24 
25 // Utility function to construct a valid Deleter for TosaSerializationHandler ptrs passed back to ArmNN
26 template <typename T>
27 void DeleteAsType(const void* const blob)
28 {
29  delete static_cast<const T*>(blob);
30 }
31 
33 {
34  static const BackendId s_Id{TosaRefBackendId()};
35  return s_Id;
36 }
37 
39  const IBackendInternal::IMemoryManagerSharedPtr& memoryManager) const
40 {
41  return std::make_unique<TosaRefWorkloadFactory>(PolymorphicPointerDowncast<TosaRefMemoryManager>(memoryManager));
42 }
43 
45  class TensorHandleFactoryRegistry& tensorHandleFactoryRegistry) const
46 {
47  auto memoryManager = std::make_shared<TosaRefMemoryManager>();
48 
49  tensorHandleFactoryRegistry.RegisterMemoryManager(memoryManager);
50 
51  auto factory = std::make_unique<TosaRefTensorHandleFactory>(memoryManager);
52  // Register copy and import factory pair
53  tensorHandleFactoryRegistry.RegisterCopyAndImportFactoryPair(factory->GetId(), factory->GetId());
54  // Register the factory
55  tensorHandleFactoryRegistry.RegisterFactory(std::move(factory));
56 
57  return std::make_unique<TosaRefWorkloadFactory>(PolymorphicPointerDowncast<TosaRefMemoryManager>(memoryManager));
58 }
59 
61 {
62  return IBackendContextPtr{};
63 }
64 
67 {
69 }
70 
72 {
73  return std::make_unique<TosaRefMemoryManager>();
74 }
75 
77 {
78  static ILayerSupportSharedPtr layerSupport{new TosaRefLayerSupport};
79  return layerSupport;
80 }
81 
82 static void LayerToTosaMappings(const Layer& base,
83  std::vector<std::string>& graphInputs,
84  std::vector<std::string>& graphOutputs,
85  std::vector<TosaSerializationOperator*>& operators,
86  std::vector<TosaSerializationTensor*>& tensors)
87 {
88  tosa::TosaSerializationBasicBlock* mappings = GetTosaMappingFromLayer(&base);
89 
90  // Loop through inputs to see if there are any graph inputs, if so save them.
91  // If it's an input to the graph "input" can be found in the string.
92  for (const std::string& blockInputName : mappings->GetInputs())
93  {
94  if (blockInputName.find("input") != std::string::npos)
95  {
96  graphInputs.push_back(blockInputName);
97  }
98  }
99 
100  // Loop through outputs to see if there are any graph outputs, if so save them.
101  // If it's an output to the graph "output" can be found in the string.
102  for (const std::string& blockOutputName : mappings->GetOutputs())
103  {
104  if (blockOutputName.find("output") != std::string::npos)
105  {
106  graphOutputs.push_back(blockOutputName);
107  }
108  }
109 
110  auto blockOperators = mappings->GetOperators();
111  operators.insert(operators.end(), blockOperators.begin(), blockOperators.end());
112 
113  auto blockTensors = mappings->GetTensors();
114  tensors.insert(tensors.end(), blockTensors.begin(), blockTensors.end());
115 }
116 
118  const ModelOptions& modelOptions) const
119 {
120  OptimizationViews optimizationViews(modelOptions);
121 
122  auto handler = std::make_unique<TosaSerializationHandler>();
123 
124  std::vector<std::string> graphInputs;
125  std::vector<std::string> graphOutputs;
126 
127  std::vector<TosaSerializationOperator*> operators;
128  std::vector<TosaSerializationTensor*> tensors;
129 
130  auto it = subgraph.begin();
131  while (it != subgraph.end())
132  {
133  Layer& base = *(PolymorphicDowncast<Layer*>(*it));
134 
135  if (base.GetType() == LayerType::Input ||
136  base.GetType() == LayerType::Output)
137  {
138  ++it;
139  continue;
140  }
141 
142  bool baseContainsBroadcastReshape = false;
144  {
145  auto nextIt = it;
146  if (++nextIt != subgraph.end())
147  {
148  Layer& nextLayer = *(PolymorphicDowncast<Layer*>(*(nextIt)));
149 
150  for (uint32_t i = 0; i < base.GetNumInputSlots(); i++)
151  {
152  const auto& parentLayer = base.GetInputSlot(i).GetConnectedOutputSlot()->GetOwningLayer();
153  if (parentLayer.GetType() == LayerType::Reshape && &parentLayer == &nextLayer)
154  {
155  LayerToTosaMappings(nextLayer, graphInputs, graphOutputs, operators, tensors);
156  baseContainsBroadcastReshape = true;
157  }
158  }
159  }
160  }
161 
162  LayerToTosaMappings(base, graphInputs, graphOutputs, operators, tensors);
163 
164  ++it;
165  if (baseContainsBroadcastReshape)
166  {
167  ++it;
168  }
169  }
170 
171  std::sort(graphInputs.begin(), graphInputs.end());
172 
173 
174  // Add all mappings to main block.
175  auto* block = new TosaSerializationBasicBlock("main", "main", operators, tensors, graphInputs, graphOutputs);
176 
177  std::vector<TosaSerializationBasicBlock*> blocks;
178  blocks.emplace_back(block);
179 
180  // Add blocks to the main region.
181  auto* region = new TosaSerializationRegion("main", blocks);
182  handler->GetRegions().emplace_back(region);
183 
184  auto compiledBlob =
185  std::make_unique<PreCompiledObjectPtr>(handler.release(), DeleteAsType<TosaSerializationHandler>);
186 
187  IConnectableLayer* preCompiledLayer = optimizationViews.GetINetwork()->AddPrecompiledLayer(
189  std::move(*compiledBlob),
191  "TOSA_Pre_Compiled_Layer");
192 
193  // Copy the output tensor infos from sub-graph
194  for (unsigned int i = 0; i < subgraph.GetNumOutputSlots(); i++)
195  {
196  preCompiledLayer->GetOutputSlot(i).SetTensorInfo(subgraph.GetIOutputSlot(i)->GetTensorInfo());
197  }
198 
199  optimizationViews.AddSubstitution({ std::move(subgraph), SubgraphView(preCompiledLayer) });
200  return optimizationViews;
201 }
202 
203 
204 std::vector<ITensorHandleFactory::FactoryId> TosaRefBackend::GetHandleFactoryPreferences() const
205 {
206  return std::vector<ITensorHandleFactory::FactoryId> { TosaRefTensorHandleFactory::GetIdStatic() };
207 }
208 
210 {
211  auto memoryManager = std::make_shared<TosaRefMemoryManager>();
212 
213  registry.RegisterMemoryManager(memoryManager);
214 
215  auto factory = std::make_unique<TosaRefTensorHandleFactory>(memoryManager);
216 
217  // Register copy and import factory pair
218  registry.RegisterCopyAndImportFactoryPair(factory->GetId(), factory->GetId());
219  // Register the factory
220  registry.RegisterFactory(std::move(factory));
221 }
222 
223 std::unique_ptr<ICustomAllocator> TosaRefBackend::GetDefaultAllocator() const
224 {
225  return std::make_unique<DefaultAllocator>();
226 }
227 
228 } // namespace armnn
TosaSerializationBasicBlock * GetTosaMappingFromLayer(const Layer *layer)
std::shared_ptr< ILayerSupport > ILayerSupportSharedPtr
std::unique_ptr< IMemoryManager > IMemoryManagerUniquePtr
std::unique_ptr< arm::pipe::IBackendProfiling > IBackendProfilingPtr
std::shared_ptr< IMemoryManager > IMemoryManagerSharedPtr
std::unique_ptr< IWorkloadFactory > IWorkloadFactoryPtr
std::unique_ptr< IBackendContext > IBackendContextPtr
std::shared_ptr< arm::pipe::IBackendProfilingContext > IBackendProfilingContextPtr
This is the bridge between backend and backend profiling we'll keep it in the backend namespace.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:81
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
IConnectableLayer * AddPrecompiledLayer(const PreCompiledDescriptor &preCompiledDescriptor, CompiledBlobPtr compiledBlobPtr, const Optional< BackendId > &backend, const char *name=nullptr)
Adds a Precompiled layer to the network.
Definition: Network.cpp:368
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
virtual const TensorInfo & GetTensorInfo() const =0
const OutputSlot * GetConnectedOutputSlot() const
Definition: Layer.hpp:56
unsigned int GetNumInputSlots() const override
Returns the number of connectable input slots.
Definition: Layer.hpp:334
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:337
LayerType GetType() const override
Returns the armnn::LayerType of this layer.
Definition: Layer.hpp:286
void AddSubstitution(SubstitutionPair &&substitution)
Layer & GetOwningLayer() const
Definition: Layer.hpp:132
The SubgraphView class represents a subgraph of a Graph.
IConnectableLayerIterator begin()
unsigned int GetNumOutputSlots() const
unsigned int GetNumInputSlots() const
const IOutputSlot * GetIOutputSlot(unsigned int index) const
IConnectableLayerIterator end()
void RegisterFactory(std::unique_ptr< ITensorHandleFactory > allocator)
Register a TensorHandleFactory and transfer ownership.
void RegisterMemoryManager(std::shared_ptr< IMemoryManager > memoryManger)
Register a memory manager with shared ownership.
void RegisterCopyAndImportFactoryPair(ITensorHandleFactory::FactoryId copyFactoryId, ITensorHandleFactory::FactoryId importFactoryId)
Register a pair of TensorHandleFactory Id for Memory Copy and TensorHandleFactory Id for Memory Impor...
static const BackendId & GetIdStatic()
OptimizationViews OptimizeSubgraphView(const SubgraphView &subgraph, const ModelOptions &modelOptions) const override
void RegisterTensorHandleFactories(class TensorHandleFactoryRegistry &registry) override
(Optional) Register TensorHandleFactories Either this method or CreateMemoryManager() and IWorkloadFa...
std::vector< ITensorHandleFactory::FactoryId > GetHandleFactoryPreferences() const override
(Optional) Returns a vector of supported TensorHandleFactory ids in preference order.
const BackendId & GetId() const override
IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions &) const override
Create the runtime context of the backend.
IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(const IBackendInternal::IMemoryManagerSharedPtr &memoryManager=nullptr) const override
IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override
IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager() const override
IBackendInternal::IBackendProfilingContextPtr CreateBackendProfilingContext(const IRuntime::CreationOptions &creationOptions, IBackendProfilingPtr &backendProfiling) override
Create context specifically used for profiling interaction from backends.
std::unique_ptr< ICustomAllocator > GetDefaultAllocator() const override
Returns the default memory allocator for the backend.
Copyright (c) 2021 ARM Limited and Contributors.
constexpr const char * TosaRefBackendId()
void DeleteAsType(const void *const blob)
std::vector< BackendOptions > ModelOptions
A PreCompiledDescriptor for the PreCompiledLayer.