ArmNN
 25.11
Loading...
Searching...
No Matches
TosaRefBackend.cpp
Go to the documentation of this file.
1//
2// Copyright © 2022-2025 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "TosaRefBackend.hpp"
11
19
20#include <Optimizer.hpp>
21
22namespace armnn
23{
24
25// Utility function to construct a valid Deleter for TosaSerializationHandler ptrs passed back to ArmNN
26template <typename T>
27void 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
64
70
72{
73 return std::make_unique<TosaRefMemoryManager>();
74}
75
81
83 const ModelOptions& modelOptions) const
84{
85 OptimizationViews optimizationViews(modelOptions);
86
87 auto handler = std::make_unique<TosaSerializationHandler>();
88
89 std::vector<std::string> graphInputs;
90 std::vector<std::string> graphOutputs;
91 std::vector<TosaSerializationOperator*> operators;
92 std::vector<TosaSerializationTensor*> tensors;
94
95 // These sets are created to check the duplication of tensor and input
96 std::unordered_set<std::string> graphInputsSet;
97 std::unordered_set<std::string> uniqueTensorNamesSet;
98
99 auto it = subgraph.begin();
100 while (it != subgraph.end())
101 {
102 Layer& base = *(PolymorphicDowncast<Layer*>(*it));
103 ++it;
104
105 if (base.GetType() == LayerType::Input ||
106 base.GetType() == LayerType::Output)
107 {
108 continue;
109 }
110
111 TosaSerializationBasicBlock* mappings = GetTosaMappingFromLayer(&base);
112
113 // Loop through inputs to see if there are any graph inputs, if so save them.
114 // If it's an input to the graph "input" can be found in the string.
115 for (const std::string& blockInputName : mappings->GetInputs())
116 {
117 if ((blockInputName.find("input") != std::string::npos) && !graphInputsSet.count(blockInputName))
118 {
119 graphInputs.push_back(blockInputName);
120 graphInputsSet.insert(blockInputName);
121 }
122 }
123
124 // Loop through outputs to see if there are any graph outputs, if so save them.
125 // If it's an output to the graph "output" can be found in the string.
126 for (const std::string& blockOutputName : mappings->GetOutputs())
127 {
128 if (blockOutputName.find("output") != std::string::npos)
129 {
130 graphOutputs.push_back(blockOutputName);
131 }
132 }
133
134 sequencer.Add(&base, mappings);
135 }
136
137 for (auto & pair : sequencer.Finish())
138 {
139 auto blockOperators = pair.block->GetOperators();
140 operators.insert(operators.end(), blockOperators.begin(), blockOperators.end());
141
142 auto blockTensors = pair.block->GetTensors();
143
144 // Checking for duplicate tensors, to handle special cases where same input is
145 // added to different layer in the architecture.
146 for (const auto& tensor : blockTensors)
147 {
148 const std::string& name = tensor->GetName();
149
150 // If the input tensor is already present, we don't need to add to the list
151 if (!uniqueTensorNamesSet.count(name))
152 {
153 uniqueTensorNamesSet.insert(name);
154 tensors.push_back(tensor);
155 }
156 }
157 }
158
159 // Add all mappings to main block.
160 auto* block = new TosaSerializationBasicBlock("main", "main", operators, tensors, graphInputs, graphOutputs);
161
162 std::vector<TosaSerializationBasicBlock*> blocks;
163 blocks.emplace_back(block);
164
165 // Add blocks to the main region.
166 auto* region = new TosaSerializationRegion("main", blocks);
167 handler->GetRegions().emplace_back(region);
168
169 auto compiledBlob =
170 std::make_unique<PreCompiledObjectPtr>(handler.release(), DeleteAsType<TosaSerializationHandler>);
171
172 IConnectableLayer* preCompiledLayer = optimizationViews.GetINetwork()->AddPrecompiledLayer(
174 std::move(*compiledBlob),
176 "TOSA_Pre_Compiled_Layer");
177
178 // Copy the output tensor infos from sub-graph
179 for (unsigned int i = 0; i < subgraph.GetNumOutputSlots(); i++)
180 {
181 preCompiledLayer->GetOutputSlot(i).SetTensorInfo(subgraph.GetIOutputSlot(i)->GetTensorInfo());
182 }
183
184 optimizationViews.AddSubstitution({ std::move(subgraph), SubgraphView(preCompiledLayer) });
185 return optimizationViews;
186}
187
188
189std::vector<ITensorHandleFactory::FactoryId> TosaRefBackend::GetHandleFactoryPreferences() const
190{
191 return std::vector<ITensorHandleFactory::FactoryId> { TosaRefTensorHandleFactory::GetIdStatic() };
192}
193
195{
196 auto memoryManager = std::make_shared<TosaRefMemoryManager>();
197
198 registry.RegisterMemoryManager(memoryManager);
199
200 auto factory = std::make_unique<TosaRefTensorHandleFactory>(memoryManager);
201
202 // Register copy and import factory pair
203 registry.RegisterCopyAndImportFactoryPair(factory->GetId(), factory->GetId());
204 // Register the factory
205 registry.RegisterFactory(std::move(factory));
206}
207
208std::unique_ptr<ICustomAllocator> TosaRefBackend::GetDefaultAllocator() const
209{
210 return std::make_unique<DefaultAllocator>();
211}
212
214{
215 return BackendCapabilities ("TosaRef",
216 {
217 {"NonConstWeights", true},
218 {"ConstantTensorsAsInputs", true}
219 });
220}
221
222} // 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
LayerType GetType() const override
Returns the armnn::LayerType of this layer.
Definition Layer.hpp:286
std::list< Pair > & Finish()
void Add(LayerT *layer, BlockT *block)
void AddSubstitution(SubstitutionPair &&substitution)
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()
const BackendId & GetId() const override
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.
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
BackendCapabilities GetCapabilities() const override
Returns a BackendCapability if the backend lists the capability The BackendCapability must then be in...
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.
auto PolymorphicPointerDowncast(const SourceType &value)
Polymorphic downcast for shared pointers and build in pointers.
std::vector< BackendOptions > ModelOptions
void DeleteAsType(const void *const blob)
DestType PolymorphicDowncast(SourceType *value)
Polymorphic downcast for build in pointers only.
BackendOptions BackendCapabilities
constexpr const char * TosaRefBackendId()
A PreCompiledDescriptor for the PreCompiledLayer.