From 5c54c3874ff5dc1656b9f28288e46086586f21b9 Mon Sep 17 00:00:00 2001 From: Matthew Sloyan Date: Wed, 9 Nov 2022 16:28:51 +0000 Subject: IVGCVSW-7165 Implement TosaRefPreCompiledWorkload::Execute() * Added FP32 support for TOSA Reference Backend. * Added main block creation to OptimizeSubgraphView, this will only occur once. Change-Id: I169dac50b78e2c693da6327962c9f1d3ae3bd712 Signed-off-by: James Conroy Signed-off-by: Matthew Sloyan --- src/backends/tosaCommon/TosaMappings.cpp | 10 +-- src/backends/tosaCommon/TosaMappings.hpp | 5 +- .../operatorMappings/AdditionOperator.cpp | 9 ++- .../operatorMappings/AdditionOperator.hpp | 3 +- .../tosaCommon/test/TosaOperatorMappingTests.cpp | 6 +- src/backends/tosaReference/TosaRefBackend.cpp | 10 ++- src/backends/tosaReference/TosaRefLayerSupport.cpp | 2 +- .../workloads/TosaRefPreCompiledWorkload.cpp | 82 +++++++++++++++++++++- .../workloads/TosaRefPreCompiledWorkload.hpp | 11 +++ 9 files changed, 123 insertions(+), 15 deletions(-) diff --git a/src/backends/tosaCommon/TosaMappings.cpp b/src/backends/tosaCommon/TosaMappings.cpp index 3c14bfd1f9..71d2012cbc 100644 --- a/src/backends/tosaCommon/TosaMappings.cpp +++ b/src/backends/tosaCommon/TosaMappings.cpp @@ -26,13 +26,14 @@ void SetBasicBlockConstantTensorData(Layer* layer, TosaSerializationBasicBlock* TosaSerializationBasicBlock* GetTosaMapping(const LayerType type, const std::vector& inputs, const std::vector& outputs, - const BaseDescriptor& /*descriptor*/) + const BaseDescriptor& /*descriptor*/, + bool isMain = false) { switch (type) { case LayerType::Addition: { - return ConvertAdditionToTosaOperator(inputs, outputs); + return ConvertAdditionToTosaOperator(inputs, outputs, isMain); } default: { @@ -43,7 +44,7 @@ TosaSerializationBasicBlock* GetTosaMapping(const LayerType type, } } -TosaSerializationBasicBlock* GetTosaMappingFromLayer(Layer* layer) +TosaSerializationBasicBlock* GetTosaMappingFromLayer(Layer* layer, bool isMain = false) { std::vector inputs; for (auto inputSlot : layer->GetInputSlots()) @@ -60,7 +61,8 @@ TosaSerializationBasicBlock* GetTosaMappingFromLayer(Layer* layer) TosaSerializationBasicBlock* basicBlock = GetTosaMapping(layer->GetType(), inputs, outputs, - layer->GetParameters()); + layer->GetParameters(), + isMain); SetBasicBlockConstantTensorData(layer, basicBlock); return basicBlock; } diff --git a/src/backends/tosaCommon/TosaMappings.hpp b/src/backends/tosaCommon/TosaMappings.hpp index c721bcaf59..7f137ca322 100644 --- a/src/backends/tosaCommon/TosaMappings.hpp +++ b/src/backends/tosaCommon/TosaMappings.hpp @@ -26,8 +26,9 @@ void SetBasicBlockConstantTensorData(Layer* layer, TosaSerializationBasicBlock* TosaSerializationBasicBlock* GetTosaMapping(const LayerType type, const std::vector& inputs, const std::vector& outputs, - const BaseDescriptor& /*descriptor*/); + const BaseDescriptor& /*descriptor*/, + bool isMain); // Function called in armnn::OptimizeSubgraphView() when access to armnn::Layer is available // and there is an option to set tosa basic block data from constant layer tenors available from the input layer. -TosaSerializationBasicBlock* GetTosaMappingFromLayer(Layer* layer); +TosaSerializationBasicBlock* GetTosaMappingFromLayer(Layer* layer, bool isMain); diff --git a/src/backends/tosaCommon/operatorMappings/AdditionOperator.cpp b/src/backends/tosaCommon/operatorMappings/AdditionOperator.cpp index 98ea03ac3c..796797728e 100644 --- a/src/backends/tosaCommon/operatorMappings/AdditionOperator.cpp +++ b/src/backends/tosaCommon/operatorMappings/AdditionOperator.cpp @@ -6,7 +6,8 @@ #include "AdditionOperator.hpp" TosaSerializationBasicBlock* ConvertAdditionToTosaOperator(const std::vector& inputs, - const std::vector& outputs) + const std::vector& outputs, + bool isMain) { // A helper function with static global variables ensures uniqueness // for dynamically generating input, output and block names @@ -15,6 +16,12 @@ TosaSerializationBasicBlock* ConvertAdditionToTosaOperator(const std::vector& inputs, - const std::vector& outputs); + const std::vector& outputs, + bool isMain); diff --git a/src/backends/tosaCommon/test/TosaOperatorMappingTests.cpp b/src/backends/tosaCommon/test/TosaOperatorMappingTests.cpp index f4435bdf42..d7cc5d8f91 100644 --- a/src/backends/tosaCommon/test/TosaOperatorMappingTests.cpp +++ b/src/backends/tosaCommon/test/TosaOperatorMappingTests.cpp @@ -72,7 +72,7 @@ TEST_CASE("GetTosaMapping_AdditionLayer") { TensorInfo info = TensorInfo({ 1, 2, 4, 2 }, DataType::Float32, 0.0f, 0, true); TosaSerializationBasicBlock* basicBlock = - GetTosaMapping(LayerType::Addition, {&info, &info}, {&info}, BaseDescriptor()); + GetTosaMapping(LayerType::Addition, {&info, &info}, {&info}, BaseDescriptor(), false); AssertTosaOneToOneMappingBasicBlock(basicBlock, { 1, 2, 4, 2 }, 2, 1, Op::Op_ADD, "Op_ADD"); } @@ -100,14 +100,14 @@ TEST_CASE("GetTosaMappingFromLayer_AdditionLayer") add->GetOutputSlot(0).SetTensorInfo(info); TosaSerializationBasicBlock* basicBlock = - GetTosaMappingFromLayer(PolymorphicDowncast(add)); + GetTosaMappingFromLayer(PolymorphicDowncast(add), false); AssertTosaOneToOneMappingBasicBlock(basicBlock, { 1, 2, 4, 2 }, 2, 1, Op::Op_ADD, "Op_ADD"); } TEST_CASE("GetTosaMapping_Unimplemented") { TosaSerializationBasicBlock* basicBlock = - GetTosaMapping(LayerType::UnidirectionalSequenceLstm, {}, {}, BaseDescriptor()); + GetTosaMapping(LayerType::UnidirectionalSequenceLstm, {}, {}, BaseDescriptor(), false); CHECK(basicBlock->GetName() == ""); CHECK(basicBlock->GetTensors().size() == 0); diff --git a/src/backends/tosaReference/TosaRefBackend.cpp b/src/backends/tosaReference/TosaRefBackend.cpp index 688cf93b49..e3a516a5f9 100644 --- a/src/backends/tosaReference/TosaRefBackend.cpp +++ b/src/backends/tosaReference/TosaRefBackend.cpp @@ -85,6 +85,9 @@ OptimizationViews TosaRefBackend::OptimizeSubgraphView(const SubgraphView& subgr OptimizationViews optimizationViews(modelOptions); auto handler = std::make_unique(); + // A main block should only be added once. + bool isMain = true; + auto it = subgraph.endIConnectable(); while (it != subgraph.beginIConnectable()) { @@ -97,8 +100,13 @@ OptimizationViews TosaRefBackend::OptimizeSubgraphView(const SubgraphView& subgr continue; } - tosa::TosaSerializationBasicBlock* mappings = GetTosaMappingFromLayer(&base); + tosa::TosaSerializationBasicBlock* mappings = GetTosaMappingFromLayer(&base, isMain); handler.get()->GetBlocks().push_back(mappings); + + if(isMain) + { + isMain = false; + } } auto compiledBlob = diff --git a/src/backends/tosaReference/TosaRefLayerSupport.cpp b/src/backends/tosaReference/TosaRefLayerSupport.cpp index f5f34a814b..c2b0b1b0b9 100644 --- a/src/backends/tosaReference/TosaRefLayerSupport.cpp +++ b/src/backends/tosaReference/TosaRefLayerSupport.cpp @@ -113,7 +113,7 @@ bool TosaRefLayerSupport::IsLayerSupported(const LayerType& type, break; } - auto mappings = GetTosaMapping(type, inputInfos, outputInfos, descriptor); + auto mappings = GetTosaMapping(type, inputInfos, outputInfos, descriptor, false); if (mappings->GetName() == "") { // There currently isn't a TOSA mapping for this layer, as the default was returned. diff --git a/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.cpp b/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.cpp index c4af4d40b1..18d2900eff 100644 --- a/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.cpp +++ b/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.cpp @@ -11,13 +11,91 @@ namespace armnn TosaRefPreCompiledWorkload::TosaRefPreCompiledWorkload(const PreCompiledQueueDescriptor& descriptor, const WorkloadInfo& info) : BaseWorkload(descriptor, info) + , m_workloadInfo(info) { - // Do nothing for now + // Check that the workload is holding a pointer to a valid pre-compiled object + if (m_Data.m_PreCompiledObject == nullptr) + { + throw InvalidArgumentException( + "TosaRefPreCompiledWorkload requires a valid pre-compiled object (TosaSerializationHandler)."); + } } void TosaRefPreCompiledWorkload::Execute() const { - // Do nothing for now + uint32_t numInputBuffers = static_cast(m_Data.m_Inputs.size()); + uint32_t numOutputBuffers = static_cast(m_Data.m_Outputs.size()); + + tosa::TosaSerializationHandler* handler = static_cast(m_Data.m_PreCompiledObject); + + std::vector input_names = handler->GetInputs(); + std::vector output_names = handler->GetOutputs(); + + TosaReference::IModelRunner runner; + GraphStatus status; + + // Initialise the model runner with the TosaSerializationHandler + status = runner.initialize(*handler); + if(status != GraphStatus::TOSA_VALID) + { + throw armnn::Exception("An error has occurred while initialising the TOSA Reference Model."); + } + + // Set the inputs + for (uint32_t inputSlotIdx = 0; inputSlotIdx < numInputBuffers; ++inputSlotIdx) + { + DataType dataType = m_workloadInfo.m_InputTensorInfos[inputSlotIdx].GetDataType(); + switch (dataType) + { + case DataType::Float32: + SetInput(runner, input_names[inputSlotIdx], inputSlotIdx); + break; + default: + throw armnn::Exception("Input data type is unsupported in TOSA Reference Backend."); + } + } + + // Run the TOSA Reference Model + status = runner.run(); + if(status != GraphStatus::TOSA_VALID) + { + throw armnn::Exception("An error has occurred while running the TOSA Reference Model."); + } + + // Gets the outputs + for (uint32_t outputSlotIdx = 0; outputSlotIdx < numOutputBuffers; ++outputSlotIdx) + { + DataType dataType = m_workloadInfo.m_OutputTensorInfos[outputSlotIdx].GetDataType(); + switch (dataType) + { + case DataType::Float32: + GetOutput(runner, output_names[outputSlotIdx], outputSlotIdx); + break; + default: + throw armnn::Exception("Output data type is unsupported in TOSA Reference Backend."); + } + } +} + +template +void TosaRefPreCompiledWorkload::SetInput(TosaReference::IModelRunner& runner, + std::string inputName, + uint32_t inputIndex) const +{ + std::vector inputData(m_Data.m_Inputs[inputIndex]->GetShape().GetNumElements()); + m_Data.m_Inputs[inputIndex]->CopyOutTo(inputData.data()); + + runner.setInput(inputName, inputData); +} + +template +void TosaRefPreCompiledWorkload::GetOutput(TosaReference::IModelRunner& runner, + std::string outputName, + uint32_t outputIndex) const +{ + std::vector actualOutputs = runner.getOutput(outputName); + + m_Data.m_Outputs[outputIndex]->CopyInFrom(actualOutputs.data()); } bool TosaRefPreCompiledWorkloadValidate(std::string*) diff --git a/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.hpp b/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.hpp index 30972693de..2b3a314888 100644 --- a/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.hpp +++ b/src/backends/tosaReference/workloads/TosaRefPreCompiledWorkload.hpp @@ -7,6 +7,9 @@ #include "armnn/backends/Workload.hpp" +#include +#include + #include #include #include @@ -38,6 +41,14 @@ private: { this->m_Data.m_Outputs[slot] = tensorHandle; } + + template + void SetInput(TosaReference::IModelRunner& runner, std::string inputName, uint32_t inputIndex) const; + + template + void GetOutput(TosaReference::IModelRunner& runner, std::string outputName, uint32_t outputIndex) const; + + WorkloadInfo m_workloadInfo; }; } //namespace armnn -- cgit v1.2.1