blob: 56aed0ca2580b746338360572937157c5b543d83 [file] [log] [blame]
Pablo Telloc9564cb2019-09-13 10:20:25 +01001/*
Michele Di Giorgio142e4ca2021-04-14 16:50:03 +01002 * Copyright (c) 2019-2021 Arm Limited.
Pablo Telloc9564cb2019-09-13 10:20:25 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
Michalis Spyrouebcebf12020-10-21 00:04:14 +010024#include "src/core/NEON/kernels/NEGenerateProposalsLayerKernel.h"
Pablo Telloc9564cb2019-09-13 10:20:25 +010025
Pablo Telloc9564cb2019-09-13 10:20:25 +010026#include "arm_compute/core/Helpers.h"
27#include "arm_compute/core/TensorInfo.h"
28#include "arm_compute/core/Utils.h"
29#include "arm_compute/core/Window.h"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010030#include "src/core/CPP/Validate.h"
31#include "src/core/helpers/AutoConfiguration.h"
32#include "src/core/helpers/WindowHelpers.h"
Pablo Telloc9564cb2019-09-13 10:20:25 +010033
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +010034#include <arm_neon.h>
35
Pablo Telloc9564cb2019-09-13 10:20:25 +010036namespace arm_compute
37{
38namespace
39{
40Status validate_arguments(const ITensorInfo *anchors, const ITensorInfo *all_anchors, const ComputeAnchorsInfo &info)
41{
42 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(anchors, all_anchors);
43 ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(anchors);
44 ARM_COMPUTE_RETURN_ERROR_ON(anchors->dimension(0) != info.values_per_roi());
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +010045 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(anchors, DataType::QSYMM16, DataType::F16, DataType::F32);
Pablo Telloc9564cb2019-09-13 10:20:25 +010046 ARM_COMPUTE_RETURN_ERROR_ON(anchors->num_dimensions() > 2);
47 if(all_anchors->total_size() > 0)
48 {
49 const size_t feature_height = info.feat_height();
50 const size_t feature_width = info.feat_width();
51 const size_t num_anchors = anchors->dimension(1);
52 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(all_anchors, anchors);
53 ARM_COMPUTE_RETURN_ERROR_ON(all_anchors->num_dimensions() > 2);
54 ARM_COMPUTE_RETURN_ERROR_ON(all_anchors->dimension(0) != info.values_per_roi());
55 ARM_COMPUTE_RETURN_ERROR_ON(all_anchors->dimension(1) != feature_height * feature_width * num_anchors);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +010056
57 if(is_data_type_quantized(anchors->data_type()))
58 {
59 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(anchors, all_anchors);
60 }
Pablo Telloc9564cb2019-09-13 10:20:25 +010061 }
62 return Status{};
63}
64
65} // namespace
66
67NEComputeAllAnchorsKernel::NEComputeAllAnchorsKernel()
68 : _anchors(nullptr), _all_anchors(nullptr), _anchors_info(0.f, 0.f, 0.f)
69{
70}
71
72void NEComputeAllAnchorsKernel::configure(const ITensor *anchors, ITensor *all_anchors, const ComputeAnchorsInfo &info)
73{
74 ARM_COMPUTE_ERROR_ON_NULLPTR(anchors, all_anchors);
75 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(anchors->info(), all_anchors->info(), info));
76
77 // Metadata
78 const size_t num_anchors = anchors->info()->dimension(1);
79 const DataType data_type = anchors->info()->data_type();
80 const float width = info.feat_width();
81 const float height = info.feat_height();
82
83 // Initialize the output if empty
84 const TensorShape output_shape(info.values_per_roi(), width * height * num_anchors);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +010085 auto_init_if_empty(*all_anchors->info(), TensorInfo(output_shape, 1, data_type, anchors->info()->quantization_info()));
Pablo Telloc9564cb2019-09-13 10:20:25 +010086
87 // Set instance variables
88 _anchors = anchors;
89 _all_anchors = all_anchors;
90 _anchors_info = info;
91
92 Window win = calculate_max_window(*all_anchors->info(), Steps(info.values_per_roi()));
93
94 INEKernel::configure(win);
95}
96
97Status NEComputeAllAnchorsKernel::validate(const ITensorInfo *anchors, const ITensorInfo *all_anchors, const ComputeAnchorsInfo &info)
98{
99 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(anchors, all_anchors, info));
100 return Status{};
101}
102
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100103template <>
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100104void NEComputeAllAnchorsKernel::internal_run<int16_t>(const Window &window)
Pablo Telloc9564cb2019-09-13 10:20:25 +0100105{
Pablo Telloc9564cb2019-09-13 10:20:25 +0100106 Iterator all_anchors_it(_all_anchors, window);
107 Iterator anchors_it(_all_anchors, window);
108
109 const size_t num_anchors = _anchors->info()->dimension(1);
110 const float stride = 1.f / _anchors_info.spatial_scale();
111 const size_t feat_width = _anchors_info.feat_width();
112
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100113 const UniformQuantizationInfo qinfo = _anchors->info()->quantization_info().uniform();
114
Pablo Telloc9564cb2019-09-13 10:20:25 +0100115 execute_window_loop(window, [&](const Coordinates & id)
116 {
117 const size_t anchor_offset = id.y() % num_anchors;
118
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100119 const auto out_anchor_ptr = reinterpret_cast<int16_t *>(all_anchors_it.ptr());
120 const auto anchor_ptr = reinterpret_cast<int16_t *>(_anchors->ptr_to_element(Coordinates(0, anchor_offset)));
Pablo Telloc9564cb2019-09-13 10:20:25 +0100121
122 const size_t shift_idy = id.y() / num_anchors;
123 const float shiftx = (shift_idy % feat_width) * stride;
124 const float shifty = (shift_idy / feat_width) * stride;
125
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100126 const float new_anchor_x1 = dequantize_qsymm16(*anchor_ptr, qinfo.scale) + shiftx;
127 const float new_anchor_y1 = dequantize_qsymm16(*(1 + anchor_ptr), qinfo.scale) + shifty;
128 const float new_anchor_x2 = dequantize_qsymm16(*(2 + anchor_ptr), qinfo.scale) + shiftx;
129 const float new_anchor_y2 = dequantize_qsymm16(*(3 + anchor_ptr), qinfo.scale) + shifty;
130
131 *out_anchor_ptr = quantize_qsymm16(new_anchor_x1, qinfo.scale);
132 *(out_anchor_ptr + 1) = quantize_qsymm16(new_anchor_y1, qinfo.scale);
133 *(out_anchor_ptr + 2) = quantize_qsymm16(new_anchor_x2, qinfo.scale);
134 *(out_anchor_ptr + 3) = quantize_qsymm16(new_anchor_y2, qinfo.scale);
Pablo Telloc9564cb2019-09-13 10:20:25 +0100135 },
136 all_anchors_it);
137}
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100138
139template <typename T>
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100140void NEComputeAllAnchorsKernel::internal_run(const Window &window)
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100141{
142 Iterator all_anchors_it(_all_anchors, window);
143 Iterator anchors_it(_all_anchors, window);
144
145 const size_t num_anchors = _anchors->info()->dimension(1);
146 const T stride = 1.f / _anchors_info.spatial_scale();
147 const size_t feat_width = _anchors_info.feat_width();
148
149 execute_window_loop(window, [&](const Coordinates & id)
150 {
151 const size_t anchor_offset = id.y() % num_anchors;
152
153 const auto out_anchor_ptr = reinterpret_cast<T *>(all_anchors_it.ptr());
154 const auto anchor_ptr = reinterpret_cast<T *>(_anchors->ptr_to_element(Coordinates(0, anchor_offset)));
155
156 const size_t shift_idy = id.y() / num_anchors;
157 const T shiftx = (shift_idy % feat_width) * stride;
158 const T shifty = (shift_idy / feat_width) * stride;
159
160 *out_anchor_ptr = *anchor_ptr + shiftx;
161 *(out_anchor_ptr + 1) = *(1 + anchor_ptr) + shifty;
162 *(out_anchor_ptr + 2) = *(2 + anchor_ptr) + shiftx;
163 *(out_anchor_ptr + 3) = *(3 + anchor_ptr) + shifty;
164 },
165 all_anchors_it);
166}
167
168void NEComputeAllAnchorsKernel::run(const Window &window, const ThreadInfo &info)
169{
170 ARM_COMPUTE_UNUSED(info);
171 ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
172 ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(INEKernel::window(), window);
173
174 switch(_anchors->info()->data_type())
175 {
176 case DataType::QSYMM16:
177 {
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100178 internal_run<int16_t>(window);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100179 break;
180 }
181#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
182 case DataType::F16:
183 {
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100184 internal_run<float16_t>(window);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100185 break;
186 }
187#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
188 case DataType::F32:
189 {
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100190 internal_run<float>(window);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100191 break;
192 }
193 default:
194 {
195 ARM_COMPUTE_ERROR("Data type not supported");
196 }
197 }
198}
Pablo Telloc9564cb2019-09-13 10:20:25 +0100199} // namespace arm_compute