blob: 56e3297e733ea0fe80072ac4a780f38fc72f6613 [file] [log] [blame]
George Wort5a97b282018-12-21 16:21:04 +00001/*
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +00002 * Copyright (c) 2018-2021 Arm Limited.
George Wort5a97b282018-12-21 16:21:04 +00003 *
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 */
Sang-Hoon Park7249f152021-01-22 11:55:03 +000024#include "src/core/cpu/kernels/CpuElementwiseUnaryKernel.h"
George Wort5a97b282018-12-21 16:21:04 +000025
George Wort5a97b282018-12-21 16:21:04 +000026#include "arm_compute/core/Error.h"
27#include "arm_compute/core/Helpers.h"
George Wort5a97b282018-12-21 16:21:04 +000028#include "arm_compute/core/ITensor.h"
George Wort5a97b282018-12-21 16:21:04 +000029#include "arm_compute/core/Validate.h"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010030#include "src/core/CPP/Validate.h"
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000031#include "src/core/common/Registrars.h"
Sang-Hoon Park7249f152021-01-22 11:55:03 +000032#include "src/core/cpu/kernels/elementwise/neon/elementwise_unary_list.h"
33#include "src/core/cpu/kernels/elementwise/sve/elementwise_unary_list.h"
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010034#include "src/core/helpers/AutoConfiguration.h"
35#include "src/core/helpers/WindowHelpers.h"
Michalis Spyroue6bcb5b2019-06-07 11:47:16 +010036#include "support/ToolchainSupport.h"
George Wort5a97b282018-12-21 16:21:04 +000037
George Wort5a97b282018-12-21 16:21:04 +000038namespace arm_compute
39{
Sang-Hoon Park7249f152021-01-22 11:55:03 +000040namespace cpu
41{
42namespace kernels
43{
George Wort5a97b282018-12-21 16:21:04 +000044namespace
45{
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000046using ElementwiseUnarySelector = std::add_pointer<bool(DataType)>::type;
George Wort5a97b282018-12-21 16:21:04 +000047
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000048struct ElementwiseUnaryKernel
George Wort5a97b282018-12-21 16:21:04 +000049{
Sang-Hoon Park7249f152021-01-22 11:55:03 +000050 const char *name;
51 const ElementwiseUnarySelector is_selected;
52 CpuElementwiseUnaryKernel::ElementwiseUnaryUkernelPtr ukernel;
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000053};
54
55static const ElementwiseUnaryKernel available_kernels[] =
56{
Michalis Spyrou20fca522021-06-07 14:23:57 +010057#if defined(ARM_COMPUTE_ENABLE_SVE)
George Wort5a97b282018-12-21 16:21:04 +000058 {
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000059 "fp32_sve_elementwise_unary",
60 [](DataType dt) { return dt == DataType::F32; },
Georgios Pinitas70eb53b2021-01-06 19:42:21 +000061 REGISTER_FP32_SVE(arm_compute::cpu::elementwise_sve_op<float>),
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000062 },
63 {
64 "fp16_sve_elementwise_unary",
65 [](DataType dt) { return dt == DataType::F16; },
Georgios Pinitas70eb53b2021-01-06 19:42:21 +000066 REGISTER_FP16_SVE(arm_compute::cpu::elementwise_sve_op<__fp16>),
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000067 },
68 {
69 "s32_sve_elementwise_unary",
70 [](DataType dt) { return dt == DataType::S32; },
Georgios Pinitas70eb53b2021-01-06 19:42:21 +000071 REGISTER_INTEGER_SVE(arm_compute::cpu::elementwise_sve_op<int32_t>),
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000072 },
Michalis Spyrou20fca522021-06-07 14:23:57 +010073#endif // defined(ARM_COMPUTE_ENABLE_SVE)
74#if defined(ARM_COMPUTE_ENABLE_NEON)
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000075 {
76 "fp32_neon_elementwise_unary",
77 [](DataType dt) { return dt == DataType::F32; },
Georgios Pinitas70eb53b2021-01-06 19:42:21 +000078 REGISTER_FP32_NEON(arm_compute::cpu::elementwise_op<float>),
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000079 },
80#if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)
81 {
82 "fp16_neon_elementwise_unary",
83 [](DataType dt) { return dt == DataType::F16; },
Georgios Pinitas70eb53b2021-01-06 19:42:21 +000084 REGISTER_FP32_NEON(arm_compute::cpu::elementwise_op<__fp16>),
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000085 },
86#endif // defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)
87 {
88 "s32_neon_elementwise_unary",
89 [](DataType dt) { return dt == DataType::S32; },
Georgios Pinitas70eb53b2021-01-06 19:42:21 +000090 REGISTER_INTEGER_NEON(arm_compute::cpu::elementwise_op<int32_t>),
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000091 },
Michalis Spyrou20fca522021-06-07 14:23:57 +010092#endif // defined(ARM_COMPUTE_ENABLE_NEON)
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000093};
94
95const ElementwiseUnaryKernel *get_implementation(DataType dt)
96{
97 for(const auto &uk : available_kernels)
98 {
99 if(uk.is_selected(dt))
100 {
101 return &uk;
102 }
George Wort5a97b282018-12-21 16:21:04 +0000103 }
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +0000104 return nullptr;
George Wort5a97b282018-12-21 16:21:04 +0000105}
Michalis Spyrou18e20ff2020-05-06 17:03:59 +0100106} // namespace
George Wort5a97b282018-12-21 16:21:04 +0000107
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000108void CpuElementwiseUnaryKernel::configure(ElementWiseUnary op, const ITensorInfo &src, ITensorInfo &dst)
George Wort5a97b282018-12-21 16:21:04 +0000109{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000110 ARM_COMPUTE_ERROR_THROW_ON(validate(op, src, dst));
George Wort5a97b282018-12-21 16:21:04 +0000111
Sang-Hoon Park7249f152021-01-22 11:55:03 +0000112 _op = op;
George Wort5a97b282018-12-21 16:21:04 +0000113
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000114 // If input shape is dynamic, expect a configured window and dst at run-time.
115 if(src.is_dynamic())
116 {
117 return;
118 }
119
Sang-Hoon Parkd0b7b4b2021-03-09 10:47:30 +0000120 auto shape_and_window = compute_output_shape_and_window(src.tensor_shape());
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000121 auto_init_if_empty(dst, shape_and_window.first, 1, src.data_type());
122 ICpuKernel::configure(shape_and_window.second);
George Wort5a97b282018-12-21 16:21:04 +0000123}
124
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000125Status CpuElementwiseUnaryKernel::validate(ElementWiseUnary op, const ITensorInfo &src, const ITensorInfo &dst)
George Wort5a97b282018-12-21 16:21:04 +0000126{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000127 ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(&src);
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +0000128
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000129 const auto *uk = get_implementation(src.data_type());
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +0000130 ARM_COMPUTE_RETURN_ERROR_ON(uk == nullptr || uk->ukernel == nullptr);
131
Michalis Spyrou18e20ff2020-05-06 17:03:59 +0100132 switch(op)
133 {
134 case ElementWiseUnary::EXP:
135 case ElementWiseUnary::RSQRT:
136 case ElementWiseUnary::LOG:
137 case ElementWiseUnary::ROUND:
138 case ElementWiseUnary::SIN:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000139 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&src, 1, DataType::F16, DataType::F32);
Michalis Spyrou18e20ff2020-05-06 17:03:59 +0100140 break;
141 case ElementWiseUnary::NEG:
142 case ElementWiseUnary::ABS:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000143 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&src, 1, DataType::F16, DataType::F32, DataType::S32);
Michalis Spyrou18e20ff2020-05-06 17:03:59 +0100144 break;
145 default:
146 ARM_COMPUTE_ERROR("ElementWiseUnary operation not supported");
147 }
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000148 // Validate in case of configured dst
149 if(dst.total_size() > 0)
Michalis Spyrou18e20ff2020-05-06 17:03:59 +0100150 {
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000151 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&src, &dst);
Michalis Spyrou18e20ff2020-05-06 17:03:59 +0100152 }
153
George Wort5a97b282018-12-21 16:21:04 +0000154 return Status{};
155}
156
Sang-Hoon Park7249f152021-01-22 11:55:03 +0000157void CpuElementwiseUnaryKernel::run_op(ITensorPack &tensors, const Window &window, const ThreadInfo &info)
George Wort5a97b282018-12-21 16:21:04 +0000158{
159 ARM_COMPUTE_UNUSED(info);
Sang-Hoon Park7249f152021-01-22 11:55:03 +0000160
161 auto src = tensors.get_const_tensor(TensorType::ACL_SRC);
162 auto dst = tensors.get_tensor(TensorType::ACL_DST);
163 auto func = get_implementation(src->info()->data_type())->ukernel;
164 ARM_COMPUTE_ERROR_ON(func == nullptr);
165 func(src, dst, window, _op);
George Wort5a97b282018-12-21 16:21:04 +0000166}
Georgios Pinitas2eb5d162021-07-02 09:01:49 +0100167
168const char *CpuElementwiseUnaryKernel::name() const
169{
170 return "CpuElementwiseUnaryKernel";
171}
Sang-Hoon Park7249f152021-01-22 11:55:03 +0000172} // namespace kernels
173} // namespace cpu
George Wort5a97b282018-12-21 16:21:04 +0000174} // namespace arm_compute