blob: 802aebb52645aa7dcfdad2ca4e218cf3baa8a5c0 [file] [log] [blame]
Pablo Tellod75f9e92019-08-23 16:26:26 +01001/*
Dana Zlotnik9ae5a4e2022-01-03 16:22:47 +02002 * Copyright (c) 2019-2022 Arm Limited.
Pablo Tellod75f9e92019-08-23 16:26:26 +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/NEROIAlignLayerKernel.h"
Pablo Tellod75f9e92019-08-23 16:26:26 +010025
Pablo Tellod75f9e92019-08-23 16:26:26 +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"
30#include "arm_compute/core/utils/misc/ShapeCalculator.h"
31#include "arm_compute/core/utils/misc/Utility.h"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010032#include "src/core/CPP/Validate.h"
Dana Zlotnik9ae5a4e2022-01-03 16:22:47 +020033#include "src/core/common/Registrars.h"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010034#include "src/core/helpers/AutoConfiguration.h"
35#include "src/core/helpers/WindowHelpers.h"
Dana Zlotnik9ae5a4e2022-01-03 16:22:47 +020036#include "src/cpu/kernels/roialign/list.h"
Pablo Tellod75f9e92019-08-23 16:26:26 +010037
38#include <arm_neon.h>
39
40using namespace arm_compute::misc::shape_calculator;
41
42namespace arm_compute
43{
44namespace
45{
Dana Zlotnik9ae5a4e2022-01-03 16:22:47 +020046struct ROIAlignSelectorData
47{
48 DataType dt;
49};
50
51using ROIAlignSelctorPtr = std::add_pointer<bool(const ROIAlignSelectorData &data)>::type;
52using ROIAlignUKernelPtr = std::add_pointer<void(const ITensor *input, ITensor *output, const ITensor *rois, ROIPoolingLayerInfo pool_info, const Window &window, const ThreadInfo &info)>::type;
53
54struct ROIAlignKernel
55{
56 const char *name;
57 const ROIAlignSelctorPtr is_selected;
58 ROIAlignUKernelPtr ukernel;
59};
60
61static const ROIAlignKernel available_kernels[] =
62{
63 {
64 "fp32_neon_roialign",
65 [](const ROIAlignSelectorData & data) { return data.dt == DataType::F32; },
66 REGISTER_FP32_NEON(arm_compute::cpu::neon_fp32_roialign)
67 },
68#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
69 {
70 "fp16_neon_roialign",
71 [](const ROIAlignSelectorData & data) { return data.dt == DataType::F16; },
72 REGISTER_FP16_NEON(arm_compute::cpu::neon_fp16_roialign)
73 },
74#endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
75#if defined(ARM_COMPUTE_ENABLE_NEON)
76 {
77 "qu8_neon_roialign",
78 [](const ROIAlignSelectorData & data) { return data.dt == DataType::QASYMM8; },
79 REGISTER_QASYMM8_NEON(arm_compute::cpu::neon_qu8_roialign)
80 },
81 {
82 "qs8_neon_roialign",
83 [](const ROIAlignSelectorData & data) { return data.dt == DataType::QASYMM8_SIGNED; },
84 REGISTER_QASYMM8_SIGNED_NEON(arm_compute::cpu::neon_qs8_roialign)
85 },
86#endif //defined(ARM_COMPUTE_ENABLE_NEON)
87};
88
89/** Micro-kernel selector
90 *
91 * @param[in] data Selection data passed to help pick the appropriate micro-kernel
92 *
93 * @return A matching micro-kernel else nullptr
94 */
95const ROIAlignKernel *get_implementation(const ROIAlignSelectorData &data)
96{
97 for(const auto &uk : available_kernels)
98 {
99 if(uk.is_selected(data))
100 {
101 return &uk;
102 }
103 }
104 return nullptr;
105}
106
Pablo Tellod75f9e92019-08-23 16:26:26 +0100107Status validate_arguments(const ITensorInfo *input, const ITensorInfo *rois, ITensorInfo *output, const ROIPoolingLayerInfo &pool_info)
108{
109 ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, rois, output);
Pablo Tellod75f9e92019-08-23 16:26:26 +0100110 ARM_COMPUTE_RETURN_ERROR_ON(rois->dimension(0) != 5);
111 ARM_COMPUTE_RETURN_ERROR_ON(rois->num_dimensions() > 2);
Sheri Zhang3327def2020-09-22 15:51:37 +0100112 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::F32, DataType::F16);
Pablo Tellod75f9e92019-08-23 16:26:26 +0100113 ARM_COMPUTE_RETURN_ERROR_ON_DATA_LAYOUT_NOT_IN(input, DataLayout::NHWC, DataLayout::NCHW);
114 ARM_COMPUTE_RETURN_ERROR_ON((pool_info.pooled_width() == 0) || (pool_info.pooled_height() == 0));
115 ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(input);
116
117 if(output->total_size() != 0)
118 {
119 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output);
120 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(input, output);
121 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DIMENSIONS(compute_roi_align_shape(*input, *rois, pool_info), output->tensor_shape());
122 }
Pablo Telloebe2e8c2019-08-23 16:26:26 +0100123
Sheri Zhang3327def2020-09-22 15:51:37 +0100124 if(input->data_type() == DataType::QASYMM8 || input->data_type() == DataType::QASYMM8_SIGNED)
Pablo Telloebe2e8c2019-08-23 16:26:26 +0100125 {
126 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(rois, 1, DataType::QASYMM16);
127
128 const UniformQuantizationInfo rois_qinfo = rois->quantization_info().uniform();
129 ARM_COMPUTE_RETURN_ERROR_ON(rois_qinfo.scale != 0.125f);
130 ARM_COMPUTE_RETURN_ERROR_ON(rois_qinfo.offset != 0);
131 }
132 else
133 {
134 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, rois);
135 }
136
Pablo Tellod75f9e92019-08-23 16:26:26 +0100137 return Status{};
138}
Pablo Tellod75f9e92019-08-23 16:26:26 +0100139} // namespace
140
141NEROIAlignLayerKernel::NEROIAlignLayerKernel()
142 : _input(nullptr), _output(nullptr), _rois(nullptr), _pool_info(0, 0, 0.f)
143{
144}
145
146void NEROIAlignLayerKernel::configure(const ITensor *input, const ITensor *rois, ITensor *output, const ROIPoolingLayerInfo &pool_info)
147{
148 ARM_COMPUTE_ERROR_ON_NULLPTR(input, output, rois);
149 ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(input->info(), rois->info(), output->info(), pool_info));
Manuel Bottini16bd6dd2020-06-01 14:40:54 +0100150 // Output auto inizialitation if not yet initialized
151 const TensorShape output_shape = compute_roi_align_shape(*input->info(), *rois->info(), pool_info);
152 auto_init_if_empty((*output->info()), output_shape, 1, input->info()->data_type(), input->info()->quantization_info());
153 output->info()->set_data_layout(input->info()->data_layout());
154
Pablo Tellod75f9e92019-08-23 16:26:26 +0100155 // Configure kernel window
Manuel Bottini16bd6dd2020-06-01 14:40:54 +0100156 const unsigned int num_rois = rois->info()->dimension(1);
157 Window window;
158 window.set(Window::DimX, Window::Dimension(0, num_rois));
159 window.set(Window::DimY, Window::Dimension(0, 1));
160
Pablo Tellod75f9e92019-08-23 16:26:26 +0100161 // Set instance variables
162 _input = input;
163 _rois = rois;
164 _output = output;
165 _pool_info = pool_info;
166
Manuel Bottini16bd6dd2020-06-01 14:40:54 +0100167 INEKernel::configure(window);
Pablo Tellod75f9e92019-08-23 16:26:26 +0100168}
169
170Status NEROIAlignLayerKernel::validate(const ITensorInfo *input, const ITensorInfo *rois, ITensorInfo *output, const ROIPoolingLayerInfo &pool_info)
171{
172 ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(input, rois, output, pool_info));
173 return Status{};
174}
175
Pablo Tellod75f9e92019-08-23 16:26:26 +0100176void NEROIAlignLayerKernel::run(const Window &window, const ThreadInfo &info)
177{
Sheri Zhang3327def2020-09-22 15:51:37 +0100178 const DataLayout data_layout = _input->info()->data_layout();
179 if(data_layout == DataLayout::NCHW || data_layout == DataLayout::NHWC)
Pablo Tellod75f9e92019-08-23 16:26:26 +0100180 {
Dana Zlotnik9ae5a4e2022-01-03 16:22:47 +0200181 const auto *uk = get_implementation(ROIAlignSelectorData{ _input->info()->data_type() });
182 ARM_COMPUTE_ERROR_ON(uk == nullptr || uk->ukernel == nullptr);
183
184 uk->ukernel(_input, _output, _rois, _pool_info, window, info);
Pablo Tellod75f9e92019-08-23 16:26:26 +0100185 }
186 else
187 {
188 ARM_COMPUTE_ERROR("Invalid layout");
189 }
190}
Pablo Tellod75f9e92019-08-23 16:26:26 +0100191} // namespace arm_compute