ONE - On-device Neural Engine
Loading...
Searching...
No Matches
AvgPool2D.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
3 * Copyright 2019 The TensorFlow Authors. All Rights Reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include "AvgPool2D.h"
19#include "Common.h"
20
21#include "mir/ShapeRange.h"
22#include "mir/Tensor.h"
23
24namespace mir_interpreter
25{
26
27using namespace mir;
28
29template <typename T> class AvgPool2DImpl
30{
31public:
32 static void run(const mir::ops::AvgPool2DOp &op, const mir::TensorVariant &input_var,
33 mir::TensorVariant &output);
34};
35
36template <typename T>
37void AvgPool2DImpl<T>::run(const ops::AvgPool2DOp &op, const TensorVariant &input_var,
38 TensorVariant &output)
39{
40 const auto &input_shape = op.getInputShape(0);
41 const auto &output_shape = op.getOutputShape(0);
42 const auto &window_size = op.getWindowSize();
43 const auto &strides = op.getStrides();
44 const auto &padding_before = op.getPaddingBefore();
45 const auto &padding_after = op.getPaddingAfter();
46 (void)padding_after;
47
48 constexpr int num_spatial_dims = 2;
49 assert(input_var.getShape().rank() == 4);
50 assert(window_size.size() == num_spatial_dims);
51 assert(strides.size() == num_spatial_dims);
52 assert(padding_before.size() == num_spatial_dims);
53 assert(padding_after.size() == num_spatial_dims);
54
55 Tensor<T> res_accessor(output);
56 Tensor<T> input(input_var);
57
58 ShapeRange in_range(input_shape);
59 Index in_index(input_shape.rank());
60
61 for (const auto &out_index : ShapeRange(output_shape))
62 {
63 T result = 0;
64 size_t num_elements = 0;
65
66 // Assuming NHWC format.
67 in_index.at(0) = out_index.at(0);
68 in_index.at(3) = out_index.at(3);
69
70 for (const auto &window_index : ShapeRange(Shape(window_size)))
71 {
72 // Assuming NHWC format.
73 for (int i = 0; i < num_spatial_dims; ++i)
74 in_index.at(1 + i) =
75 out_index.at(1 + i) * strides[i] + window_index.at(i) - padding_before[i];
76
77 if (in_range.contains(in_index))
78 {
79 num_elements++;
80 result += input.at(in_index);
81 }
82 else if (op.getIncludePad())
83 {
84 num_elements++;
85 }
86 }
87
88 result /= num_elements;
89 res_accessor.at(out_index) = result;
90 }
91}
92
93template <> struct AvgPool2DImpl<uint8_t>
94{
95 static void run(const mir::ops::AvgPool2DOp &op, const mir::TensorVariant &input,
96 mir::TensorVariant &output);
97};
98
100 TensorVariant &output)
101{
102 const auto &input_type = input.getType();
103 const auto &output_type = op.getOutput(0)->getType();
104 (void)input_type;
105
106 assert(input_type.isQuantized());
107 assert(output_type.isQuantized());
108 assert(input_type.getElementType() == DataType::UINT8);
109
110 const auto &input_shape = op.getInputShape(0);
111 const auto &output_shape = op.getOutputShape(0);
112 const auto &window_size = op.getWindowSize();
113 const auto &strides = op.getStrides();
114 const auto &padding_before = op.getPaddingBefore();
115 const auto &padding_after = op.getPaddingAfter();
116 (void)padding_after;
117
118 constexpr int num_spatial_dims = 2;
119 assert(input.getShape().rank() == 4);
120 assert(window_size.size() == num_spatial_dims);
121 assert(strides.size() == num_spatial_dims);
122 assert(padding_before.size() == num_spatial_dims);
123 assert(padding_after.size() == num_spatial_dims);
124
125 Tensor<uint8_t> input_accessor(input);
126 Tensor<uint8_t> res_accessor(output);
127
128 ShapeRange in_range(input_shape);
129 Index in_index(input_shape.rank());
130
131 int32_t output_min = std::numeric_limits<uint8_t>::min();
132 int32_t output_max = std::numeric_limits<uint8_t>::max();
133
134 for (const auto &out_index : ShapeRange(output_shape))
135 {
136 int32_t result = 0;
137 size_t num_elements = 0;
138
139 // Assuming NHWC format.
140 in_index.at(0) = out_index.at(0);
141 in_index.at(3) = out_index.at(3);
142
143 for (const auto &window_index : ShapeRange(Shape(window_size)))
144 {
145 // Assuming NHWC format.
146 for (int i = 0; i < num_spatial_dims; ++i)
147 in_index.at(1 + i) =
148 out_index.at(1 + i) * strides[i] + window_index.at(i) - padding_before[i];
149
150 if (in_range.contains(in_index))
151 {
152 num_elements++;
153 result += input_accessor.at(in_index);
154 }
155 else if (op.getIncludePad())
156 {
157 num_elements++;
158 }
159 }
160 result = (result + num_elements / 2) / num_elements;
161 result = std::max(result, output_min);
162 result = std::min(result, output_max);
163 res_accessor.at(out_index) = static_cast<uint8_t>(result);
164 }
165}
166
168 mir::TensorVariant &output)
169{
170 dispatch<AvgPool2DImpl>(output.getElementType(), op, input, output);
171}
172
173} // namespace mir_interpreter
int32_t & at(int32_t axis)
return position on given axis
Definition Index.h:64
const TensorType & getType() const
Gets the type of this output.
Definition Operation.h:91
Output * getOutput(std::size_t index)
Definition Operation.h:149
const Shape & getInputShape(std::size_t index) const
Definition Operation.h:161
const Shape & getOutputShape(std::size_t index) const
Definition Operation.h:163
int32_t rank() const
Definition Shape.h:43
bool contains(const Index &idx)
Definition ShapeRange.h:92
T at(const Index &id) const
Definition Tensor.h:31
const Shape & getShape() const
const std::vector< std::int32_t > & getWindowSize() const
Definition AvgPool2DOp.h:45
const std::vector< std::int32_t > & getPaddingBefore() const
Definition AvgPool2DOp.h:49
const std::vector< std::int32_t > & getPaddingAfter() const
Definition AvgPool2DOp.h:51
bool getIncludePad() const
Definition AvgPool2DOp.h:53
const std::vector< std::int32_t > & getStrides() const
Definition AvgPool2DOp.h:47
static void run(const mir::ops::AvgPool2DOp &op, const mir::TensorVariant &input_var, mir::TensorVariant &output)
Definition AvgPool2D.cpp:37
const luci_interpreter::RuntimeShape output_shape