diff options
author | Matthew Sloyan <matthew.sloyan@arm.com> | 2022-10-28 18:02:17 +0100 |
---|---|---|
committer | Matthew Sloyan <matthew.sloyan@arm.com> | 2022-11-02 15:08:37 +0000 |
commit | 164bf4f29f6f1b2a3e6714ef4f5a21fc0fd16c2b (patch) | |
tree | e7296130a787578e1be4d3a93de46a9c466944b4 /src/backends/tosaReference | |
parent | 2e950f4fa774ac995230addea898f3b11bf146cc (diff) | |
download | armnn-164bf4f29f6f1b2a3e6714ef4f5a21fc0fd16c2b.tar.gz |
IVGCVSW-7164 Implement TosaRefBackend::OptimizeSubgraphView
* Added TosaRefBackend::OptimizeSubgraphView implementation.
* Generalised TosaRefLayerSupport::IsLayerSupported to work with any
operator.
* Changed TosaCommon.hpp utils to inline functions.
* Added source files for TosaMappings.hpp and AdditionOperator.hpp.
* Fixed multiple defines issue with HALF_ROUND_STYLE and
HALF_ROUND_TIES_TO_EVEN.
Signed-off-by: Matthew Sloyan <matthew.sloyan@arm.com>
Change-Id: Ib2576ec3fb97faa3a2256b2fb93ec16ac8745760
Diffstat (limited to 'src/backends/tosaReference')
4 files changed, 121 insertions, 14 deletions
diff --git a/src/backends/tosaReference/TosaRefBackend.cpp b/src/backends/tosaReference/TosaRefBackend.cpp index 093802958b..688cf93b49 100644 --- a/src/backends/tosaReference/TosaRefBackend.cpp +++ b/src/backends/tosaReference/TosaRefBackend.cpp @@ -9,6 +9,7 @@ #include "TosaRefLayerSupport.hpp" #include "TosaRefTensorHandleFactory.hpp" +#include <tosaCommon/TosaMappings.hpp> #include <armnn/BackendRegistry.hpp> #include <armnn/backends/IBackendContext.hpp> #include <armnn/backends/IMemoryManager.hpp> @@ -21,6 +22,13 @@ namespace armnn { +// Utility function to construct a valid Deleter for TosaSerializationHandler ptrs passed back to ArmNN +template <typename T> +void DeleteAsType(const void* const blob) +{ + delete static_cast<const T*>(blob); +} + const BackendId& TosaRefBackend::GetIdStatic() { static const BackendId s_Id{TosaRefBackendId()}; @@ -75,11 +83,44 @@ OptimizationViews TosaRefBackend::OptimizeSubgraphView(const SubgraphView& subgr const ModelOptions& modelOptions) const { OptimizationViews optimizationViews(modelOptions); - optimizationViews.AddUntouchedSubgraph(SubgraphView(subgraph)); - + auto handler = std::make_unique<TosaSerializationHandler>(); + + auto it = subgraph.endIConnectable(); + while (it != subgraph.beginIConnectable()) + { + --it; + Layer &base = *(PolymorphicDowncast<Layer*>(*it)); + + if(base.GetType() == armnn::LayerType::Input || + base.GetType() == armnn::LayerType::Output) + { + continue; + } + + tosa::TosaSerializationBasicBlock* mappings = GetTosaMappingFromLayer(&base); + handler.get()->GetBlocks().push_back(mappings); + } + + auto compiledBlob = + std::make_unique<PreCompiledObjectPtr>(handler.release(), DeleteAsType<TosaSerializationHandler>); + + IConnectableLayer* preCompiledLayer = optimizationViews.GetINetwork()->AddPrecompiledLayer( + PreCompiledDescriptor(subgraph.GetNumInputSlots(), subgraph.GetNumOutputSlots()), + std::move(*compiledBlob), + armnn::Optional<BackendId>(GetId()), + "TOSA_Pre_Compiled_Layer"); + + // Copy the output tensor infos from sub-graph + for (unsigned int i = 0; i < subgraph.GetNumOutputSlots(); i++) + { + preCompiledLayer->GetOutputSlot(i).SetTensorInfo(subgraph.GetIOutputSlot(i)->GetTensorInfo()); + } + + optimizationViews.AddSubstitution({ std::move(subgraph), SubgraphView(preCompiledLayer) }); return optimizationViews; } + std::vector<ITensorHandleFactory::FactoryId> TosaRefBackend::GetHandleFactoryPreferences() const { return std::vector<ITensorHandleFactory::FactoryId> { TosaRefTensorHandleFactory::GetIdStatic() }; diff --git a/src/backends/tosaReference/TosaRefLayerSupport.cpp b/src/backends/tosaReference/TosaRefLayerSupport.cpp index 18530bb535..f5f34a814b 100644 --- a/src/backends/tosaReference/TosaRefLayerSupport.cpp +++ b/src/backends/tosaReference/TosaRefLayerSupport.cpp @@ -95,25 +95,36 @@ bool TosaRefLayerSupport::IsLayerSupported(const LayerType& type, IgnoreUnused(lstmParamsInfo); IgnoreUnused(quantizedLstmInputParamsInfo); - // Setup Inputs - const auto input0 = infos[0]; - const TensorInfo* ptr0 = &input0; - const auto input1 = infos[1]; - const TensorInfo* ptr1 = &input1; - std::vector<const TensorInfo*> inputInfos = {ptr0, ptr1}; - - // Setup Outputs - const auto output = infos[2]; - const TensorInfo* ptr2 = &output; - std::vector<const TensorInfo*> outputInfos = {ptr2}; + std::vector<const TensorInfo*> inputInfos; + std::vector<const TensorInfo*> outputInfos; + + switch (type) + { + case LayerType::Addition: + // Setup inputs and outputs + inputInfos.push_back(&infos[0]); + inputInfos.push_back(&infos[1]); + outputInfos.push_back(&infos[2]); + break; + case LayerType::Input: + case LayerType::Output: + return true; + default: + break; + } auto mappings = GetTosaMapping(type, inputInfos, outputInfos, descriptor); + if (mappings->GetName() == "") + { + // There currently isn't a TOSA mapping for this layer, as the default was returned. + return false; + } // Loop through block and get each tensor and operator for (long unsigned int i = 0; i < mappings->GetOperators().size(); ++i) { // While looping over operators check for op_UNKNOWN which is unsupported - if (mappings->GetOperators()[i]->GetOp() == tosa::Op_UNKNOWN) { return false;} + if (mappings->GetOperators()[i]->GetOp() == tosa::Op_UNKNOWN) { return false; } // Loop over operators and get GetInput/OutputTensorNames, loop over resulting names and // use GetTensorByName to pass pointers to tensors on to the IsTosaLayerSupported() diff --git a/src/backends/tosaReference/test/CMakeLists.txt b/src/backends/tosaReference/test/CMakeLists.txt index 8366901605..627a1836e1 100644 --- a/src/backends/tosaReference/test/CMakeLists.txt +++ b/src/backends/tosaReference/test/CMakeLists.txt @@ -6,6 +6,7 @@ list(APPEND armnnTosaRefBackendUnitTests_sources TosaRefLayerTests.cpp TosaRefLayerSupportTests.cpp + TosaRefOptimizedNetworkTests.cpp ) add_library(armnnTosaRefBackendUnitTests OBJECT ${armnnTosaRefBackendUnitTests_sources}) diff --git a/src/backends/tosaReference/test/TosaRefOptimizedNetworkTests.cpp b/src/backends/tosaReference/test/TosaRefOptimizedNetworkTests.cpp new file mode 100644 index 0000000000..64b6805d2c --- /dev/null +++ b/src/backends/tosaReference/test/TosaRefOptimizedNetworkTests.cpp @@ -0,0 +1,54 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include <armnn/INetwork.hpp> + +#include <GraphUtils.hpp> +#include <TestUtils.hpp> + +#include <doctest/doctest.h> + +TEST_SUITE("TosaReferenceOptimizedNetwork") +{ + +TEST_CASE("SimpleSupportedOptimizedNetwork") +{ + armnn::IRuntime::CreationOptions options; + armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options)); + armnn::INetworkPtr network(armnn::INetwork::Create()); + + auto inputLayer1 = network->AddInputLayer(0, "input_1"); + auto inputLayer2 = network->AddInputLayer(1, "input_2"); + auto addLayer = network->AddAdditionLayer("add"); + auto outputLayer = network->AddOutputLayer(2, "output"); + + armnn::TensorInfo tensorInfo{{4}, armnn::DataType::Float32}; + + inputLayer1->GetOutputSlot(0).Connect(addLayer->GetInputSlot(0)); + inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo); + + inputLayer2->GetOutputSlot(0).Connect(addLayer->GetInputSlot(1)); + inputLayer2->GetOutputSlot(0).SetTensorInfo(tensorInfo); + + addLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0)); + addLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo); + + std::vector<armnn::BackendId> backends = { "TosaRef" }; + + armnn::OptimizerOptions optimizedOptions; + armnn::IOptimizedNetworkPtr optNet = Optimize(*network, backends, runtime->GetDeviceSpec(), optimizedOptions); + CHECK(optNet); + + armnn::Graph& graph = GetGraphForTesting(optNet.get()); + + // Check graph layer sequence to ensure that the network has been replaced with a PreCompiledLayer + CHECK(CheckSequence(graph.cbegin(), graph.cend(), + &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::InputLayer>, + &IsLayerOfType<armnn::PreCompiledLayer>, + &IsLayerOfType<armnn::OutputLayer>)); +} + +} |