// // Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #include "RefBackend.hpp" #include "RefBackendId.hpp" #include "RefWorkloadFactory.hpp" #include "RefLayerSupport.hpp" #include "RefTensorHandleFactory.hpp" #include #include #include #include #include #include namespace armnn { const BackendId& RefBackend::GetIdStatic() { static const BackendId s_Id{RefBackendId()}; return s_Id; } IBackendInternal::IWorkloadFactoryPtr RefBackend::CreateWorkloadFactory( const IBackendInternal::IMemoryManagerSharedPtr& memoryManager) const { return std::make_unique(PolymorphicPointerDowncast(memoryManager)); } IBackendInternal::IWorkloadFactoryPtr RefBackend::CreateWorkloadFactory( class TensorHandleFactoryRegistry& tensorHandleFactoryRegistry) const { auto memoryManager = std::make_shared(); tensorHandleFactoryRegistry.RegisterMemoryManager(memoryManager); std::unique_ptr factory = std::make_unique(memoryManager); // Register copy and import factory pair tensorHandleFactoryRegistry.RegisterCopyAndImportFactoryPair(factory->GetId(), factory->GetId()); // Register the factory tensorHandleFactoryRegistry.RegisterFactory(std::move(factory)); return std::make_unique(PolymorphicPointerDowncast(memoryManager)); } IBackendInternal::IBackendContextPtr RefBackend::CreateBackendContext(const IRuntime::CreationOptions&) const { return IBackendContextPtr{}; } IBackendInternal::IBackendProfilingContextPtr RefBackend::CreateBackendProfilingContext( const IRuntime::CreationOptions&, IBackendProfilingPtr&) { return IBackendProfilingContextPtr{}; } IBackendInternal::IMemoryManagerUniquePtr RefBackend::CreateMemoryManager() const { return std::make_unique(); } IBackendInternal::ILayerSupportSharedPtr RefBackend::GetLayerSupport() const { static ILayerSupportSharedPtr layerSupport{new RefLayerSupport}; return layerSupport; } OptimizationViews RefBackend::OptimizeSubgraphView(const SubgraphView& subgraph, const ModelOptions& modelOptions) const { OptimizationViews optimizationViews(modelOptions); auto it = subgraph.endIConnectable(); std::map untouched; while (it != subgraph.beginIConnectable()) { --it; Layer& base = *(PolymorphicDowncast(*it)); untouched.insert({base.GetGuid(), &base}); } it = subgraph.endIConnectable(); while (it != subgraph.beginIConnectable()) { --it; Layer& base = *(PolymorphicDowncast(*it)); // Special case to fuse padding into average pooling 2d for quantized datatype. // Required to be done as a backend specific optimization as Neon does not support this special case. if (base.GetType() == LayerType::Pooling2d) { Pooling2dLayer* baseLayer = PolymorphicDowncast(&base); Pooling2dDescriptor poolingDescriptor = baseLayer->GetParameters(); if (baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetOwningLayer().GetType() == LayerType::Pad) { PadLayer* padLayer = PolymorphicDowncast( &baseLayer->GetInputSlot(0).GetConnectedOutputSlot()->GetOwningLayer()); if (padLayer->GetOutputSlot(0).GetNumConnections() == 1 && optimizations::pad_fold::TryFoldPadIntoLayer2d(padLayer->GetParameters(), poolingDescriptor, padLayer->GetOutputSlot().GetTensorInfo(), true)) { FoldPadIntoAveragePool2d(optimizationViews, baseLayer, poolingDescriptor, padLayer); untouched.erase(baseLayer->GetGuid()); untouched.erase(padLayer->GetGuid()); } } } // Remove Reshape where possible if (base.GetType() == LayerType::Reshape) { ReshapeLayer* baseLayer = PolymorphicDowncast(&base); RemoveReshapeLayer(baseLayer, untouched, optimizationViews); } } if (optimizationViews.GetSubstitutions().empty() && optimizationViews.GetDeletedSubgraphs().empty()) { optimizationViews.AddUntouchedSubgraph(SubgraphView(subgraph)); } else { ReportUntouchedLayers(optimizationViews, untouched); } return optimizationViews; } std::vector RefBackend::GetHandleFactoryPreferences() const { return std::vector { RefTensorHandleFactory::GetIdStatic() }; } void RefBackend::RegisterTensorHandleFactories(class TensorHandleFactoryRegistry& registry) { auto memoryManager = std::make_shared(); registry.RegisterMemoryManager(memoryManager); std::unique_ptr factory = std::make_unique(memoryManager); // Register copy and import factory pair registry.RegisterCopyAndImportFactoryPair(factory->GetId(), factory->GetId()); // Register the factory registry.RegisterFactory(std::move(factory)); } std::unique_ptr RefBackend::GetDefaultAllocator() const { return std::make_unique(); } ExecutionData RefBackend::CreateExecutionData(WorkingMemDescriptor& workingMemDescriptor) const { ExecutionData executionData; executionData.m_Data = &workingMemDescriptor; return executionData; } void RefBackend::UpdateExecutionData(ExecutionData& executionData, WorkingMemDescriptor& workingMemDescriptor) const { executionData.m_Data = &workingMemDescriptor; } } // namespace armnn