ONE - On-device Neural Engine
Loading...
Searching...
No Matches
arm_compute::NEReduceOperation Class Reference

#include <NEReduceOperation.h>

Collaboration diagram for arm_compute::NEReduceOperation:

Public Member Functions

 NEReduceOperation (std::shared_ptr< IMemoryManager > memory_manager=nullptr)
 
void configure (ITensor *input, const Coordinates &reduction_axis, bool keep_dims, ITensor *output, ReductionOperation op)
 
void run () override
 

Static Public Member Functions

static Status validate (const ITensorInfo *input, const Coordinates &reduction_axis, bool keep_dims, const ITensorInfo *output, ReductionOperation op)
 

Detailed Description

Basic function to perform reduce operation

Definition at line 58 of file NEReduceOperation.h.

Constructor & Destructor Documentation

◆ NEReduceOperation()

NEReduceOperation::NEReduceOperation ( std::shared_ptr< IMemoryManager >  memory_manager = nullptr)

Constructor

Definition at line 53 of file NEReduceOperation.cpp.

54 : _memory_group(std::move(memory_manager)), _reduction_kernels(), _reduced_outs(), _reshape(),
55 _reduction_ops(), _keep_dims()
56{
57}

Member Function Documentation

◆ configure()

void NEReduceOperation::configure ( ITensor *  input,
const Coordinates &  reduction_axis,
bool  keep_dims,
ITensor *  output,
ReductionOperation  op 
)

Configure kernel

Note
Supported tensor rank: up to 4
Parameters
[in]inputSource tensor. Data type supported: QASYMM8/F16/F32
[in]reduction_axisReduction axis vector.
[in]keep_dimsIf positive, retains reduced dimensions with length 1.
[out]outputDestination tensor. Data type supported: Same as input
[in]opReduce operation to perform.

Definition at line 106 of file NEReduceOperation.cpp.

108{
109 ARM_COMPUTE_ERROR_ON_NULLPTR(input);
110
111 _reduction_ops = reduction_axis.num_dimensions();
112 _reduction_kernels.resize(_reduction_ops);
113 _reduced_outs.resize(_reduction_ops - (keep_dims ? 1 : 0));
114 _keep_dims = keep_dims;
115
116 Coordinates axis_local = reduction_axis;
117 const int input_dims = input->info()->num_dimensions();
118 const unsigned int reduction_ops = reduction_axis.num_dimensions();
119
120 // Convert negative axis
121 for (unsigned int i = 0; i < reduction_ops; ++i)
122 {
123 axis_local[i] = wrap_around(axis_local[i], input_dims);
124 }
125
126 // Perform reduction for every axis
127 for (unsigned int i = 0; i < _reduction_ops; ++i)
128 {
129 TensorShape out_shape =
130 i == 0 ? input->info()->tensor_shape() : (&_reduced_outs[i - 1])->info()->tensor_shape();
131 out_shape.set(axis_local[i], 1);
132 auto in = (i == 0) ? input : (&_reduced_outs[i - 1]);
133
134 if (i == _reduction_ops - 1 && keep_dims)
135 {
136 _reduction_kernels[i].configure(in, output, axis_local[i], op);
137 }
138 else
139 {
140 _reduced_outs[i].allocator()->init(TensorInfo(out_shape, input->info()->num_channels(),
141 input->info()->data_type(),
142 input->info()->quantization_info()));
143 _memory_group.manage(&_reduced_outs[i]);
144 _reduction_kernels[i].configure(in, &_reduced_outs[i], axis_local[i], op);
145 }
146 }
147
148 // Allocate intermediate tensors
149 for (unsigned int i = 0; i < _reduction_ops - (keep_dims ? 1 : 0); ++i)
150 {
151 _reduced_outs[i].allocator()->allocate();
152 }
153
154 // Configure reshape layer if we want to drop the dimensions
155 if (!keep_dims)
156 {
157 TensorShape out_shape = input->info()->tensor_shape();
158
159 // We have to sort the reduction axis vectors in order for remove_dimension
160 // to work properly
161 std::sort(axis_local.begin(), axis_local.begin() + _reduction_ops);
162 for (unsigned int i = 0; i < _reduction_ops; ++i)
163 {
164 out_shape.remove_dimension(axis_local[i] - i);
165 }
166 auto_init_if_empty(*output->info(), input->info()->clone()->set_tensor_shape(out_shape));
167 _reshape.configure(&_reduced_outs[_reduction_ops - 1], output);
168 }
169}
volatile const char info[]
::nncc::core::ADT::tensor::Shape TensorShape
Definition TensorShape.h:25

References info.

◆ run()

void NEReduceOperation::run ( )
override

Definition at line 171 of file NEReduceOperation.cpp.

172{
173 MemoryGroupResourceScope scope_mg(_memory_group);
174
175 for (unsigned int i = 0; i < _reduction_ops; ++i)
176 {
177 _reduction_kernels[i].run();
178 }
179
180 if (!_keep_dims)
181 {
182 _reshape.run();
183 }
184}

Referenced by package.infer.session::inference().

◆ validate()

Status NEReduceOperation::validate ( const ITensorInfo *  input,
const Coordinates &  reduction_axis,
bool  keep_dims,
const ITensorInfo *  output,
ReductionOperation  op 
)
static

Static function to check if given info will lead to a valid configuration of NEReduceOperation

Parameters
[in]inputSource tensor. Data type supported: QASYMM8/F16/F32
[in]reduction_axisReduction axis vector.
[in]keep_dimsIf positive, retains reduced dimensions with length 1.
[in]outputDestination tensor. Data type supported: Same as input
[in]opReduce operation to perform.
Returns
A status

Definition at line 59 of file NEReduceOperation.cpp.

61{
62 ARM_COMPUTE_UNUSED(keep_dims);
63 ARM_COMPUTE_UNUSED(op);
64 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input);
65 ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(input);
66 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QASYMM8, DataType::F16,
67 DataType::F32);
68 ARM_COMPUTE_RETURN_ERROR_ON(reduction_axis.num_dimensions() > input->num_dimensions());
69
70 TensorShape out_shape = input->tensor_shape();
71 const unsigned int reduction_ops = reduction_axis.num_dimensions();
72 const int input_dims = input->num_dimensions();
73 Coordinates axis_local = reduction_axis;
74
75 // Convert negative axis
76 for (unsigned int i = 0; i < reduction_ops; ++i)
77 {
78 axis_local[i] = wrap_around(axis_local[i], input_dims);
79 }
80
81 std::sort(axis_local.begin(), axis_local.begin() + reduction_ops);
82 for (unsigned int i = 0; i < reduction_ops; ++i)
83 {
84 ARM_COMPUTE_RETURN_ERROR_ON(axis_local[i] > 3);
85 ARM_COMPUTE_RETURN_ERROR_ON(static_cast<unsigned int>(axis_local[i]) >
86 input->num_dimensions() - 1);
87 if (output->total_size() > 0 && keep_dims)
88 {
89 ARM_COMPUTE_RETURN_ERROR_ON(output->dimension(axis_local[i]) != 1);
90 }
91 if (keep_dims)
92 {
93 out_shape.set(axis_local[i], 1);
94 }
95 else
96 {
97 out_shape.remove_dimension(axis_local[i] - i);
98 }
99 }
100 const TensorInfo out_info = input->clone()->set_tensor_shape(out_shape);
101 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_SHAPES(output, &out_info);
102
103 return Status{};
104}

The documentation for this class was generated from the following files: