ONE - On-device Neural Engine
Loading...
Searching...
No Matches
MaxPool2D.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "MaxPool2D.h"
18#include "Common.h"
19
20#include "mir/ShapeRange.h"
21#include "mir/Tensor.h"
22
23#include <limits>
24
25namespace mir_interpreter
26{
27
28using namespace mir;
29
30template <typename T> struct MaxPool2DImpl
31{
32 static void run(const mir::TensorVariant &inputv, const mir::ops::MaxPool2DOp &op,
33 mir::TensorVariant &result);
34};
35
36template <typename T>
38 TensorVariant &result)
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 Tensor<T> input(inputv);
49
50 constexpr int num_spatial_dims = 2;
51 assert(input.getShape().rank() == 4);
52 assert(window_size.size() == num_spatial_dims);
53 assert(strides.size() == num_spatial_dims);
54 assert(padding_before.size() == num_spatial_dims);
55 assert(padding_after.size() == num_spatial_dims);
56
57 Tensor<T> res_accessor(result);
58
59 ShapeRange in_range(input_shape);
60 Index in_index(input_shape.rank());
61
62 for (const auto &out_index : ShapeRange(output_shape))
63 {
64 T result = std::numeric_limits<T>::lowest();
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 result = std::max(result, input.at(in_index));
80 }
81 }
82
83 res_accessor.at(out_index) = result;
84 }
85}
86
87template <> struct MaxPool2DImpl<uint8_t>
88{
89 static void run(const mir::TensorVariant &input, const mir::ops::MaxPool2DOp &op,
90 mir::TensorVariant &result);
91};
92
94 TensorVariant &result)
95{
96 const auto &input_type = input.getType();
97 const auto &output_type = op.getOutput(0)->getType();
98 (void)input_type;
99
100 assert(input_type.isQuantized());
101 assert(output_type.isQuantized());
102 assert(input_type.getElementType() == DataType::UINT8);
103
104 const auto &input_shape = op.getInputShape(0);
105 const auto &output_shape = op.getOutputShape(0);
106 const auto &window_size = op.getWindowSize();
107 const auto &strides = op.getStrides();
108 const auto &padding_before = op.getPaddingBefore();
109 const auto &padding_after = op.getPaddingAfter();
110 (void)padding_after;
111
112 constexpr int num_spatial_dims = 2;
113 assert(input.getShape().rank() == 4);
114 assert(window_size.size() == num_spatial_dims);
115 assert(strides.size() == num_spatial_dims);
116 assert(padding_before.size() == num_spatial_dims);
117 assert(padding_after.size() == num_spatial_dims);
118
119 Tensor<uint8_t> input_accessor(input);
120
121 TensorType res_type(mir::DataType::UINT8, output_shape, output_type.getQuantization());
122 TensorVariant res(res_type);
123 Tensor<uint8_t> res_accessor(res);
124
125 ShapeRange in_range(input_shape);
126 Index in_index(input_shape.rank());
127
128 for (const auto &out_index : ShapeRange(output_shape))
129 {
130 // Assuming NHWC format.
131 in_index.at(0) = out_index.at(0);
132 in_index.at(3) = out_index.at(3);
133
134 uint8_t result = 0;
135 for (const auto &window_index : ShapeRange(Shape(window_size)))
136 {
137 // Assuming NHWC format.
138 for (int i = 0; i < num_spatial_dims; ++i)
139 in_index.at(1 + i) =
140 out_index.at(1 + i) * strides[i] + window_index.at(i) - padding_before[i];
141
142 if (in_range.contains(in_index))
143 {
144 result = std::max(result, input_accessor.at(in_index));
145 }
146 }
147 res_accessor.at(out_index) = result;
148 }
149}
150
152 mir::TensorVariant &result)
153{
154 dispatch<MaxPool2DImpl>(input.getElementType(), input, op, result);
155};
156
157} // 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
bool contains(const Index &idx)
Definition ShapeRange.h:92
T at(const Index &id) const
Definition Tensor.h:31
const std::vector< std::int32_t > & getPaddingBefore() const
Definition MaxPool2DOp.h:49
const std::vector< std::int32_t > & getPaddingAfter() const
Definition MaxPool2DOp.h:51
const std::vector< std::int32_t > & getWindowSize() const
Definition MaxPool2DOp.h:45
const std::vector< std::int32_t > & getStrides() const
Definition MaxPool2DOp.h:47
const luci_interpreter::RuntimeShape output_shape
static void run(const mir::TensorVariant &inputv, const mir::ops::MaxPool2DOp &op, mir::TensorVariant &result)
Definition MaxPool2D.cpp:37