blob: 516a9b68c2d1531cbad38c2e486c22ed4790543c [file] [log] [blame]
Pablo Telloc9564cb2019-09-13 10:20:25 +01001/*
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +01002 * Copyright (c) 2019-2020 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/AccessWindowStatic.h"
31#include "src/core/CPP/Validate.h"
32#include "src/core/helpers/AutoConfiguration.h"
33#include "src/core/helpers/WindowHelpers.h"
Pablo Telloc9564cb2019-09-13 10:20:25 +010034
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +010035#include <arm_neon.h>
36
Pablo Telloc9564cb2019-09-13 10:20:25 +010037namespace arm_compute
38{
39namespace
40{
41Status validate_arguments(const ITensorInfo *anchors, const ITensorInfo *all_anchors, const ComputeAnchorsInfo &info)
42{
43 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(anchors, all_anchors);
44 ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(anchors);
45 ARM_COMPUTE_RETURN_ERROR_ON(anchors->dimension(0) != info.values_per_roi());
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +010046 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(anchors, DataType::QSYMM16, DataType::F16, DataType::F32);
Pablo Telloc9564cb2019-09-13 10:20:25 +010047 ARM_COMPUTE_RETURN_ERROR_ON(anchors->num_dimensions() > 2);
48 if(all_anchors->total_size() > 0)
49 {
50 const size_t feature_height = info.feat_height();
51 const size_t feature_width = info.feat_width();
52 const size_t num_anchors = anchors->dimension(1);
53 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(all_anchors, anchors);
54 ARM_COMPUTE_RETURN_ERROR_ON(all_anchors->num_dimensions() > 2);
55 ARM_COMPUTE_RETURN_ERROR_ON(all_anchors->dimension(0) != info.values_per_roi());
56 ARM_COMPUTE_RETURN_ERROR_ON(all_anchors->dimension(1) != feature_height * feature_width * num_anchors);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +010057
58 if(is_data_type_quantized(anchors->data_type()))
59 {
60 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(anchors, all_anchors);
61 }
Pablo Telloc9564cb2019-09-13 10:20:25 +010062 }
63 return Status{};
64}
65
66} // namespace
67
68NEComputeAllAnchorsKernel::NEComputeAllAnchorsKernel()
69 : _anchors(nullptr), _all_anchors(nullptr), _anchors_info(0.f, 0.f, 0.f)
70{
71}
72
73void NEComputeAllAnchorsKernel::configure(const ITensor *anchors, ITensor *all_anchors, const ComputeAnchorsInfo &info)
74{
75 ARM_COMPUTE_ERROR_ON_NULLPTR(anchors, all_anchors);
76 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(anchors->info(), all_anchors->info(), info));
77
78 // Metadata
79 const size_t num_anchors = anchors->info()->dimension(1);
80 const DataType data_type = anchors->info()->data_type();
81 const float width = info.feat_width();
82 const float height = info.feat_height();
83
84 // Initialize the output if empty
85 const TensorShape output_shape(info.values_per_roi(), width * height * num_anchors);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +010086 auto_init_if_empty(*all_anchors->info(), TensorInfo(output_shape, 1, data_type, anchors->info()->quantization_info()));
Pablo Telloc9564cb2019-09-13 10:20:25 +010087
88 // Set instance variables
89 _anchors = anchors;
90 _all_anchors = all_anchors;
91 _anchors_info = info;
92
93 Window win = calculate_max_window(*all_anchors->info(), Steps(info.values_per_roi()));
94
95 INEKernel::configure(win);
96}
97
98Status NEComputeAllAnchorsKernel::validate(const ITensorInfo *anchors, const ITensorInfo *all_anchors, const ComputeAnchorsInfo &info)
99{
100 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(anchors, all_anchors, info));
101 return Status{};
102}
103
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100104template <>
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100105void NEComputeAllAnchorsKernel::internal_run<int16_t>(const Window &window)
Pablo Telloc9564cb2019-09-13 10:20:25 +0100106{
Pablo Telloc9564cb2019-09-13 10:20:25 +0100107 Iterator all_anchors_it(_all_anchors, window);
108 Iterator anchors_it(_all_anchors, window);
109
110 const size_t num_anchors = _anchors->info()->dimension(1);
111 const float stride = 1.f / _anchors_info.spatial_scale();
112 const size_t feat_width = _anchors_info.feat_width();
113
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100114 const UniformQuantizationInfo qinfo = _anchors->info()->quantization_info().uniform();
115
Pablo Telloc9564cb2019-09-13 10:20:25 +0100116 execute_window_loop(window, [&](const Coordinates & id)
117 {
118 const size_t anchor_offset = id.y() % num_anchors;
119
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100120 const auto out_anchor_ptr = reinterpret_cast<int16_t *>(all_anchors_it.ptr());
121 const auto anchor_ptr = reinterpret_cast<int16_t *>(_anchors->ptr_to_element(Coordinates(0, anchor_offset)));
Pablo Telloc9564cb2019-09-13 10:20:25 +0100122
123 const size_t shift_idy = id.y() / num_anchors;
124 const float shiftx = (shift_idy % feat_width) * stride;
125 const float shifty = (shift_idy / feat_width) * stride;
126
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100127 const float new_anchor_x1 = dequantize_qsymm16(*anchor_ptr, qinfo.scale) + shiftx;
128 const float new_anchor_y1 = dequantize_qsymm16(*(1 + anchor_ptr), qinfo.scale) + shifty;
129 const float new_anchor_x2 = dequantize_qsymm16(*(2 + anchor_ptr), qinfo.scale) + shiftx;
130 const float new_anchor_y2 = dequantize_qsymm16(*(3 + anchor_ptr), qinfo.scale) + shifty;
131
132 *out_anchor_ptr = quantize_qsymm16(new_anchor_x1, qinfo.scale);
133 *(out_anchor_ptr + 1) = quantize_qsymm16(new_anchor_y1, qinfo.scale);
134 *(out_anchor_ptr + 2) = quantize_qsymm16(new_anchor_x2, qinfo.scale);
135 *(out_anchor_ptr + 3) = quantize_qsymm16(new_anchor_y2, qinfo.scale);
Pablo Telloc9564cb2019-09-13 10:20:25 +0100136 },
137 all_anchors_it);
138}
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100139
140template <typename T>
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100141void NEComputeAllAnchorsKernel::internal_run(const Window &window)
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100142{
143 Iterator all_anchors_it(_all_anchors, window);
144 Iterator anchors_it(_all_anchors, window);
145
146 const size_t num_anchors = _anchors->info()->dimension(1);
147 const T stride = 1.f / _anchors_info.spatial_scale();
148 const size_t feat_width = _anchors_info.feat_width();
149
150 execute_window_loop(window, [&](const Coordinates & id)
151 {
152 const size_t anchor_offset = id.y() % num_anchors;
153
154 const auto out_anchor_ptr = reinterpret_cast<T *>(all_anchors_it.ptr());
155 const auto anchor_ptr = reinterpret_cast<T *>(_anchors->ptr_to_element(Coordinates(0, anchor_offset)));
156
157 const size_t shift_idy = id.y() / num_anchors;
158 const T shiftx = (shift_idy % feat_width) * stride;
159 const T shifty = (shift_idy / feat_width) * stride;
160
161 *out_anchor_ptr = *anchor_ptr + shiftx;
162 *(out_anchor_ptr + 1) = *(1 + anchor_ptr) + shifty;
163 *(out_anchor_ptr + 2) = *(2 + anchor_ptr) + shiftx;
164 *(out_anchor_ptr + 3) = *(3 + anchor_ptr) + shifty;
165 },
166 all_anchors_it);
167}
168
169void NEComputeAllAnchorsKernel::run(const Window &window, const ThreadInfo &info)
170{
171 ARM_COMPUTE_UNUSED(info);
172 ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
173 ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(INEKernel::window(), window);
174
175 switch(_anchors->info()->data_type())
176 {
177 case DataType::QSYMM16:
178 {
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100179 internal_run<int16_t>(window);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100180 break;
181 }
182#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
183 case DataType::F16:
184 {
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100185 internal_run<float16_t>(window);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100186 break;
187 }
188#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
189 case DataType::F32:
190 {
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100191 internal_run<float>(window);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100192 break;
193 }
194 default:
195 {
196 ARM_COMPUTE_ERROR("Data type not supported");
197 }
198 }
199}
Pablo Telloc9564cb2019-09-13 10:20:25 +0100200} // namespace arm_compute