blob: d514aa6a6dd617421ddcca27c23897f537fbc48e [file] [log] [blame]
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +00001//
Matthew Sloyan6dd07022023-01-25 12:40:11 +00002// Copyright © 2020 Samsung Electronics Co Ltd and Contributors. All rights reserved.
Declan-ARM7c75e332024-03-12 16:40:25 +00003// Copyright © 2023-2024 Arm Ltd and Contributors. All rights reserved.
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +00004// SPDX-License-Identifier: MIT
5//
6
7#include "ReduceLayer.hpp"
8#include "LayerCloneBase.hpp"
9
10#include <armnn/TypesUtils.hpp>
11
Colm Donelan0c479742021-12-10 12:43:54 +000012#include <armnn/backends/WorkloadData.hpp>
13#include <armnn/backends/WorkloadFactory.hpp>
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +000014
15namespace armnn
16{
17
18ReduceLayer::ReduceLayer(const ReduceDescriptor& param, const char* name)
19 : LayerWithParameters(1, 1, LayerType::Reduce, param, name)
20{
21}
22
23std::unique_ptr<IWorkload> ReduceLayer::CreateWorkload(const IWorkloadFactory& factory) const
24{
25 ReduceQueueDescriptor descriptor;
Sadik Armagan58fb0ee2021-03-12 09:15:35 +000026 descriptor.m_Parameters.m_vAxis = m_Param.m_vAxis;
27 descriptor.m_Parameters.m_KeepDims = m_Param.m_KeepDims;
28 descriptor.m_Parameters.m_ReduceOperation = m_Param.m_ReduceOperation;
29 SetAdditionalInfo(descriptor);
30
Teresa Charlin611c7fb2022-01-07 09:47:29 +000031 return factory.CreateWorkload(LayerType::Reduce, descriptor, PrepInfoAndDesc(descriptor));
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +000032}
33
34ReduceLayer* ReduceLayer::Clone(Graph& graph) const
35{
Sadik Armagan58fb0ee2021-03-12 09:15:35 +000036 auto layer = CloneBase<ReduceLayer>(graph, m_Param, GetName());
37 layer->m_Param.m_vAxis = m_Param.m_vAxis;
38 layer->m_Param.m_KeepDims = m_Param.m_KeepDims;
39 layer->m_Param.m_ReduceOperation = m_Param.m_ReduceOperation;
40
41 return std::move(layer);
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +000042}
43
44void ReduceLayer::ValidateTensorShapesFromInputs()
45{
46 VerifyLayerConnections(1, CHECK_LOCATION());
47
48 const TensorShape& outputShape = GetOutputSlot(0).GetTensorInfo().GetShape();
49
50 VerifyShapeInferenceType(outputShape, m_ShapeInferenceMethod);
51
Mike Kellya9ac6ba2023-06-30 15:18:26 +010052 const TensorInfo& input = GetInputSlot(0).GetTensorInfo();
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +000053
Kevin Mayb4474c42024-03-14 15:28:43 +000054 auto inputDims = input.GetNumDimensions();
Declan-ARM60eadf52024-03-15 12:47:55 +000055 if (inputDims < 1 || inputDims > 4)
Declan-ARM7c75e332024-03-12 16:40:25 +000056 {
57 throw armnn::LayerValidationException("ReduceLayer: Reduce supports up to 4D input.");
58 }
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +000059
Mike Kelly377fb212023-01-10 15:55:28 +000060 std::vector<TensorShape> inferredShapes = InferOutputShapes( {input.GetShape() });
61
62 ValidateAndCopyShape(outputShape, inferredShapes[0], m_ShapeInferenceMethod, "ReduceLayer");
63}
64
65std::vector<TensorShape> ReduceLayer::InferOutputShapes(const std::vector<TensorShape>& inputShapes) const
66{
Declan-ARM7c75e332024-03-12 16:40:25 +000067 if (inputShapes.size() != 1)
68 {
69 throw armnn::Exception("inputShapes' size is \"" + std::to_string(inputShapes.size()) +
70 "\" - should be \"1\".");
71 }
72
Mike Kelly377fb212023-01-10 15:55:28 +000073 const TensorShape& input = inputShapes[0];
74
Kevin Mayb4474c42024-03-14 15:28:43 +000075 auto inputDims = input.GetNumDimensions();
Declan-ARM60eadf52024-03-15 12:47:55 +000076 if (inputDims < 1 || inputDims > 4)
Declan-ARM7c75e332024-03-12 16:40:25 +000077 {
78 throw armnn::Exception("ReduceLayer: Reduce supports up to 4D input.");
79 }
Mike Kelly377fb212023-01-10 15:55:28 +000080
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +000081 unsigned int rank = input.GetNumDimensions();
82 unsigned int outputRank = 0;
83
84 // Calculate output dimension
85 if (m_Param.m_KeepDims)
86 {
87 outputRank = rank;
88 }
89 else if (m_Param.m_vAxis.empty())
90 {
91 outputRank = 1;
92 }
93 else if (m_Param.m_vAxis.size() > input.GetNumDimensions())
94 {
95 throw LayerValidationException("ReduceLayer: Dimensions to reduce can not be bigger than input dimensions");
96 }
97 else
98 {
99 outputRank = input.GetNumDimensions() - armnn::numeric_cast<unsigned int>(m_Param.m_vAxis.size());
100 if (outputRank == 0)
101 {
102 outputRank = 1;
103 }
104 }
105
106 std::vector<unsigned int> dimSizes(outputRank, 1);
107 if (!m_Param.m_vAxis.empty())
108 {
109 // Skip the dimension that has been reduced unless keepDims is true.
110 unsigned int outputIndex = 0;
111 for (unsigned int i = 0; i < input.GetNumDimensions(); ++i)
112 {
113 if (std::find(m_Param.m_vAxis.begin(), m_Param.m_vAxis.end(), i) == m_Param.m_vAxis.end())
114 {
Mike Kelly377fb212023-01-10 15:55:28 +0000115 dimSizes[outputIndex] = armnn::numeric_cast<unsigned int>(input[i]);
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +0000116 ++outputIndex;
117 }
118 else if (m_Param.m_KeepDims)
119 {
120 dimSizes[outputIndex] = 1;
121 ++outputIndex;
122 }
123 }
124 }
Mike Kelly377fb212023-01-10 15:55:28 +0000125 return std::vector<TensorShape>({ TensorShape(outputRank, dimSizes.data()) });
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +0000126}
127
Nikhil Raj4d2eec02022-05-30 11:08:52 +0100128void ReduceLayer::ExecuteStrategy(IStrategy& strategy) const
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +0000129{
Nikhil Raj4d2eec02022-05-30 11:08:52 +0100130 strategy.ExecuteStrategy(this, GetParameters(), {}, GetName());
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +0000131}
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +0000132
133} // namespace armnn