blob: 940ccabe652047da74716430c2dfffb984667034 [file] [log] [blame]
Pablo Telloc9564cb2019-09-13 10:20:25 +01001/*
2 * Copyright (c) 2019 ARM Limited.
3 *
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 */
24#include "arm_compute/core/NEON/kernels/NEGenerateProposalsLayerKernel.h"
25
26#include "arm_compute/core/AccessWindowStatic.h"
27#include "arm_compute/core/CPP/Validate.h"
28#include "arm_compute/core/Helpers.h"
29#include "arm_compute/core/TensorInfo.h"
30#include "arm_compute/core/Utils.h"
31#include "arm_compute/core/Window.h"
32
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +010033#include <arm_neon.h>
34
Pablo Telloc9564cb2019-09-13 10:20:25 +010035namespace arm_compute
36{
37namespace
38{
39Status validate_arguments(const ITensorInfo *anchors, const ITensorInfo *all_anchors, const ComputeAnchorsInfo &info)
40{
41 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(anchors, all_anchors);
42 ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(anchors);
43 ARM_COMPUTE_RETURN_ERROR_ON(anchors->dimension(0) != info.values_per_roi());
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +010044 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(anchors, DataType::QSYMM16, DataType::F16, DataType::F32);
Pablo Telloc9564cb2019-09-13 10:20:25 +010045 ARM_COMPUTE_RETURN_ERROR_ON(anchors->num_dimensions() > 2);
46 if(all_anchors->total_size() > 0)
47 {
48 const size_t feature_height = info.feat_height();
49 const size_t feature_width = info.feat_width();
50 const size_t num_anchors = anchors->dimension(1);
51 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(all_anchors, anchors);
52 ARM_COMPUTE_RETURN_ERROR_ON(all_anchors->num_dimensions() > 2);
53 ARM_COMPUTE_RETURN_ERROR_ON(all_anchors->dimension(0) != info.values_per_roi());
54 ARM_COMPUTE_RETURN_ERROR_ON(all_anchors->dimension(1) != feature_height * feature_width * num_anchors);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +010055
56 if(is_data_type_quantized(anchors->data_type()))
57 {
58 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_QUANTIZATION_INFO(anchors, all_anchors);
59 }
Pablo Telloc9564cb2019-09-13 10:20:25 +010060 }
61 return Status{};
62}
63
64} // namespace
65
66NEComputeAllAnchorsKernel::NEComputeAllAnchorsKernel()
67 : _anchors(nullptr), _all_anchors(nullptr), _anchors_info(0.f, 0.f, 0.f)
68{
69}
70
71void NEComputeAllAnchorsKernel::configure(const ITensor *anchors, ITensor *all_anchors, const ComputeAnchorsInfo &info)
72{
73 ARM_COMPUTE_ERROR_ON_NULLPTR(anchors, all_anchors);
74 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(anchors->info(), all_anchors->info(), info));
75
76 // Metadata
77 const size_t num_anchors = anchors->info()->dimension(1);
78 const DataType data_type = anchors->info()->data_type();
79 const float width = info.feat_width();
80 const float height = info.feat_height();
81
82 // Initialize the output if empty
83 const TensorShape output_shape(info.values_per_roi(), width * height * num_anchors);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +010084 auto_init_if_empty(*all_anchors->info(), TensorInfo(output_shape, 1, data_type, anchors->info()->quantization_info()));
Pablo Telloc9564cb2019-09-13 10:20:25 +010085
86 // Set instance variables
87 _anchors = anchors;
88 _all_anchors = all_anchors;
89 _anchors_info = info;
90
91 Window win = calculate_max_window(*all_anchors->info(), Steps(info.values_per_roi()));
92
93 INEKernel::configure(win);
94}
95
96Status NEComputeAllAnchorsKernel::validate(const ITensorInfo *anchors, const ITensorInfo *all_anchors, const ComputeAnchorsInfo &info)
97{
98 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(anchors, all_anchors, info));
99 return Status{};
100}
101
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100102template <>
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100103void NEComputeAllAnchorsKernel::internal_run<int16_t>(const Window &window)
Pablo Telloc9564cb2019-09-13 10:20:25 +0100104{
Pablo Telloc9564cb2019-09-13 10:20:25 +0100105 Iterator all_anchors_it(_all_anchors, window);
106 Iterator anchors_it(_all_anchors, window);
107
108 const size_t num_anchors = _anchors->info()->dimension(1);
109 const float stride = 1.f / _anchors_info.spatial_scale();
110 const size_t feat_width = _anchors_info.feat_width();
111
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100112 const UniformQuantizationInfo qinfo = _anchors->info()->quantization_info().uniform();
113
Pablo Telloc9564cb2019-09-13 10:20:25 +0100114 execute_window_loop(window, [&](const Coordinates & id)
115 {
116 const size_t anchor_offset = id.y() % num_anchors;
117
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100118 const auto out_anchor_ptr = reinterpret_cast<int16_t *>(all_anchors_it.ptr());
119 const auto anchor_ptr = reinterpret_cast<int16_t *>(_anchors->ptr_to_element(Coordinates(0, anchor_offset)));
Pablo Telloc9564cb2019-09-13 10:20:25 +0100120
121 const size_t shift_idy = id.y() / num_anchors;
122 const float shiftx = (shift_idy % feat_width) * stride;
123 const float shifty = (shift_idy / feat_width) * stride;
124
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100125 const float new_anchor_x1 = dequantize_qsymm16(*anchor_ptr, qinfo.scale) + shiftx;
126 const float new_anchor_y1 = dequantize_qsymm16(*(1 + anchor_ptr), qinfo.scale) + shifty;
127 const float new_anchor_x2 = dequantize_qsymm16(*(2 + anchor_ptr), qinfo.scale) + shiftx;
128 const float new_anchor_y2 = dequantize_qsymm16(*(3 + anchor_ptr), qinfo.scale) + shifty;
129
130 *out_anchor_ptr = quantize_qsymm16(new_anchor_x1, qinfo.scale);
131 *(out_anchor_ptr + 1) = quantize_qsymm16(new_anchor_y1, qinfo.scale);
132 *(out_anchor_ptr + 2) = quantize_qsymm16(new_anchor_x2, qinfo.scale);
133 *(out_anchor_ptr + 3) = quantize_qsymm16(new_anchor_y2, qinfo.scale);
Pablo Telloc9564cb2019-09-13 10:20:25 +0100134 },
135 all_anchors_it);
136}
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100137
138template <typename T>
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100139void NEComputeAllAnchorsKernel::internal_run(const Window &window)
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100140{
141 Iterator all_anchors_it(_all_anchors, window);
142 Iterator anchors_it(_all_anchors, window);
143
144 const size_t num_anchors = _anchors->info()->dimension(1);
145 const T stride = 1.f / _anchors_info.spatial_scale();
146 const size_t feat_width = _anchors_info.feat_width();
147
148 execute_window_loop(window, [&](const Coordinates & id)
149 {
150 const size_t anchor_offset = id.y() % num_anchors;
151
152 const auto out_anchor_ptr = reinterpret_cast<T *>(all_anchors_it.ptr());
153 const auto anchor_ptr = reinterpret_cast<T *>(_anchors->ptr_to_element(Coordinates(0, anchor_offset)));
154
155 const size_t shift_idy = id.y() / num_anchors;
156 const T shiftx = (shift_idy % feat_width) * stride;
157 const T shifty = (shift_idy / feat_width) * stride;
158
159 *out_anchor_ptr = *anchor_ptr + shiftx;
160 *(out_anchor_ptr + 1) = *(1 + anchor_ptr) + shifty;
161 *(out_anchor_ptr + 2) = *(2 + anchor_ptr) + shiftx;
162 *(out_anchor_ptr + 3) = *(3 + anchor_ptr) + shifty;
163 },
164 all_anchors_it);
165}
166
167void NEComputeAllAnchorsKernel::run(const Window &window, const ThreadInfo &info)
168{
169 ARM_COMPUTE_UNUSED(info);
170 ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
171 ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(INEKernel::window(), window);
172
173 switch(_anchors->info()->data_type())
174 {
175 case DataType::QSYMM16:
176 {
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100177 internal_run<int16_t>(window);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100178 break;
179 }
180#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
181 case DataType::F16:
182 {
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100183 internal_run<float16_t>(window);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100184 break;
185 }
186#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
187 case DataType::F32:
188 {
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100189 internal_run<float>(window);
Michele Di Giorgio58c71ef2019-09-30 15:03:21 +0100190 break;
191 }
192 default:
193 {
194 ARM_COMPUTE_ERROR("Data type not supported");
195 }
196 }
197}
Pablo Telloc9564cb2019-09-13 10:20:25 +0100198} // namespace arm_compute