From 0c3ea5b8ac5ad8ca516930a0491afb1d1074e45b Mon Sep 17 00:00:00 2001 From: Sadik Armagan Date: Wed, 3 Feb 2021 09:29:30 +0000 Subject: backends/reference: Add ReduceSum operation support This patch addes ReduceSum operation support for reference backend, which computes the sum of elements across dimensions of a tensor. Changelog v1: - Fix file header descriptions. Chagelog v2: - Fix line limit issue. - Fix type conversion issue. Changelog v3: - Remove tabs. - Modify newly added file headers. Changelog v4: - Symbol on header isn't allowed so drop it from newly added file headers. Changelog v5: - Remove tabs, fix the use of brackets and align lines correctly. Changelog v6: - Add serializer and deserializer support. Changelog v7: - Fix build error add missed code. Changelog v8: - Rename ReduceSumDecriptor to ReduceDescriptor - Update m_KeepDims field data type to bool on ReduceDescriptor - Add ReduceOperation field to ReduceDescriptor - Rename ReduceSumLayer to ReduceLayer - Update ReduceLayer to use ReduceDescriptor - Update ReduceLayer::ValidateTensorShapesFromInputs() function - Rename RefReduceSumWokload to RefReduceWorkload - Update workload to use ReduceDescriptor - Update workload to use Decoders and Encoders - Remove ReduceSum.hpp and ReduceSum.cpp - Added Reduce.hpp and Reduce.cpp - Move Mean.cpp (which is implementing REDUCE_MEAN) functionality to Reduce.cpp - Update RefMeanWorkload to call Reduce function with ReduceOperation::Mean argument - Remove Mean.hpp and Mean.cpp - Update the Serializer/Deserializer ArmnnSchema.fbs for ReduceLayer, ReduceDescriptor, and ReduceOperation - Update Serializer and Deserializer for serializing/parsing ReduceLayer - Added TfLiter parser Sum test for REDUCE_SUM operator - Make corresponding changes on front-end and Ref backend to support REDUCE_SUM operator Changelog v9: - Fixed build errors. Change-Id: I8c8e034f3df73f9565b3c18eff51ecca6c542195 Signed-off-by: Inki Dae Signed-off-by: Sadik Armagan --- src/armnn/layers/ReduceLayer.cpp | 100 +++++++++++++++++++++++++++++++++++++++ src/armnn/layers/ReduceLayer.hpp | 42 ++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 src/armnn/layers/ReduceLayer.cpp create mode 100644 src/armnn/layers/ReduceLayer.hpp (limited to 'src/armnn/layers') diff --git a/src/armnn/layers/ReduceLayer.cpp b/src/armnn/layers/ReduceLayer.cpp new file mode 100644 index 0000000000..b68cd2eabc --- /dev/null +++ b/src/armnn/layers/ReduceLayer.cpp @@ -0,0 +1,100 @@ +// +// Copyright © 2020 Samsung Electronics Co Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "ReduceLayer.hpp" +#include "LayerCloneBase.hpp" + +#include + +#include +#include + +namespace armnn +{ + +ReduceLayer::ReduceLayer(const ReduceDescriptor& param, const char* name) + : LayerWithParameters(1, 1, LayerType::Reduce, param, name) +{ +} + +std::unique_ptr ReduceLayer::CreateWorkload(const IWorkloadFactory& factory) const +{ + ReduceQueueDescriptor descriptor; + return factory.CreateReduce(descriptor, PrepInfoAndDesc(descriptor)); +} + +ReduceLayer* ReduceLayer::Clone(Graph& graph) const +{ + return CloneBase(graph, m_Param, GetName()); +} + +void ReduceLayer::ValidateTensorShapesFromInputs() +{ + VerifyLayerConnections(1, CHECK_LOCATION()); + + const TensorShape& outputShape = GetOutputSlot(0).GetTensorInfo().GetShape(); + + VerifyShapeInferenceType(outputShape, m_ShapeInferenceMethod); + + const TensorInfo& input = GetInputSlot(0).GetConnection()->GetTensorInfo(); + + ARMNN_ASSERT_MSG(input.GetNumDimensions() > 0 && input.GetNumDimensions() <= 4, + "ReduceLayer: Reduce supports up to 4D input."); + + unsigned int rank = input.GetNumDimensions(); + unsigned int outputRank = 0; + + // Calculate output dimension + if (m_Param.m_KeepDims) + { + outputRank = rank; + } + else if (m_Param.m_vAxis.empty()) + { + outputRank = 1; + } + else if (m_Param.m_vAxis.size() > input.GetNumDimensions()) + { + throw LayerValidationException("ReduceLayer: Dimensions to reduce can not be bigger than input dimensions"); + } + else + { + outputRank = input.GetNumDimensions() - armnn::numeric_cast(m_Param.m_vAxis.size()); + if (outputRank == 0) + { + outputRank = 1; + } + } + + std::vector dimSizes(outputRank, 1); + if (!m_Param.m_vAxis.empty()) + { + // Skip the dimension that has been reduced unless keepDims is true. + unsigned int outputIndex = 0; + for (unsigned int i = 0; i < input.GetNumDimensions(); ++i) + { + if (std::find(m_Param.m_vAxis.begin(), m_Param.m_vAxis.end(), i) == m_Param.m_vAxis.end()) + { + dimSizes[outputIndex] = armnn::numeric_cast(input.GetShape()[i]); + ++outputIndex; + } + else if (m_Param.m_KeepDims) + { + dimSizes[outputIndex] = 1; + ++outputIndex; + } + } + } + const TensorShape& inferredShape = TensorShape(outputRank, dimSizes.data()); + + ValidateAndCopyShape(outputShape, inferredShape, m_ShapeInferenceMethod, "ReduceLayer"); +} + +void ReduceLayer::Accept(ILayerVisitor& visitor) const +{ + visitor.VisitReduceLayer(this, GetParameters(), GetName()); +} + +} // namespace armnn diff --git a/src/armnn/layers/ReduceLayer.hpp b/src/armnn/layers/ReduceLayer.hpp new file mode 100644 index 0000000000..fd4f2073f1 --- /dev/null +++ b/src/armnn/layers/ReduceLayer.hpp @@ -0,0 +1,42 @@ +// +// Copyright © 2020 Samsung Electronics Co Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// +#pragma once + +#include "LayerWithParameters.hpp" + +namespace armnn +{ + +/// This layer represents a reduction operation. +class ReduceLayer : public LayerWithParameters +{ +public: + /// Makes a workload for the Reduce type. + /// @param [in] graph The graph where this layer can be found. + /// @param [in] factory The workload factory which will create the workload. + /// @return A pointer to the created workload, or nullptr if not created. + virtual std::unique_ptrCreateWorkload(const IWorkloadFactory& factory) const override; + + /// Creates a dynamically-allocated copy of this layer. + /// @param [in] graph The graph into which this layer is being cloned. + ReduceLayer* Clone(Graph& graph) const override; + + /// Check if the input tensor shape(s) + /// will lead to a valid configuration of @ref ReduceLayer. + void ValidateTensorShapesFromInputs() override; + + void Accept(ILayerVisitor& visitor) const override; + +protected: + /// Constructor to create a ReduceLayer. + /// @param [in] param ReduceDescriptor to configure the reduction operation. + /// @param [in] name Optional name for the layer. + ReduceLayer(const ReduceDescriptor& param, const char* name); + + /// Default destructor + ~ReduceLayer() = default; +}; + +} // namespace armnn -- cgit v1.2.1