blob: c587e18850102ec77d39b1556b6530fb3cc3efd2 [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 */
Georgios Pinitas7891a732021-08-20 21:39:25 +010024#include "src/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 Park68dd25f2020-10-19 16:00:11 +010032#include "src/core/helpers/AutoConfiguration.h"
33#include "src/core/helpers/WindowHelpers.h"
Georgios Pinitas7891a732021-08-20 21:39:25 +010034#include "src/cpu/kernels/elementwise/neon/elementwise_unary_list.h"
35#include "src/cpu/kernels/elementwise/sve/elementwise_unary_list.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{
Georgios Pinitas5ee0d952021-07-05 07:21:28 +010046struct ElementwiseUnarySelectorData
47{
48 DataType dt;
49 const CPUInfo &ci;
50};
51using ElementwiseUnarySelector = std::add_pointer<bool(const ElementwiseUnarySelectorData &)>::type;
George Wort5a97b282018-12-21 16:21:04 +000052
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000053struct ElementwiseUnaryKernel
George Wort5a97b282018-12-21 16:21:04 +000054{
Sang-Hoon Park7249f152021-01-22 11:55:03 +000055 const char *name;
56 const ElementwiseUnarySelector is_selected;
57 CpuElementwiseUnaryKernel::ElementwiseUnaryUkernelPtr ukernel;
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000058};
59
60static const ElementwiseUnaryKernel available_kernels[] =
61{
Michalis Spyrou20fca522021-06-07 14:23:57 +010062#if defined(ARM_COMPUTE_ENABLE_SVE)
George Wort5a97b282018-12-21 16:21:04 +000063 {
Georgios Pinitas5ee0d952021-07-05 07:21:28 +010064 "sve_fp32_elementwise_unary",
65 [](const ElementwiseUnarySelectorData & data) { return data.dt == DataType::F32; },
Georgios Pinitas70eb53b2021-01-06 19:42:21 +000066 REGISTER_FP32_SVE(arm_compute::cpu::elementwise_sve_op<float>),
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000067 },
68 {
Georgios Pinitas5ee0d952021-07-05 07:21:28 +010069 "sve_fp16_elementwise_unary",
70 [](const ElementwiseUnarySelectorData & data) { return data.dt == DataType::F16; },
Georgios Pinitas70eb53b2021-01-06 19:42:21 +000071 REGISTER_FP16_SVE(arm_compute::cpu::elementwise_sve_op<__fp16>),
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000072 },
73 {
Georgios Pinitas5ee0d952021-07-05 07:21:28 +010074 "sve_s32_elementwise_unary",
75 [](const ElementwiseUnarySelectorData & data) { return data.dt == DataType::S32; },
Georgios Pinitas70eb53b2021-01-06 19:42:21 +000076 REGISTER_INTEGER_SVE(arm_compute::cpu::elementwise_sve_op<int32_t>),
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000077 },
Michalis Spyrou20fca522021-06-07 14:23:57 +010078#endif // defined(ARM_COMPUTE_ENABLE_SVE)
79#if defined(ARM_COMPUTE_ENABLE_NEON)
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000080 {
Georgios Pinitas5ee0d952021-07-05 07:21:28 +010081 "neon_fp32_elementwise_unary",
82 [](const ElementwiseUnarySelectorData & data) { return data.dt == DataType::F32; },
Georgios Pinitas70eb53b2021-01-06 19:42:21 +000083 REGISTER_FP32_NEON(arm_compute::cpu::elementwise_op<float>),
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000084 },
85#if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)
86 {
Georgios Pinitas5ee0d952021-07-05 07:21:28 +010087 "neon_fp16_elementwise_unary",
88 [](const ElementwiseUnarySelectorData & data) { return data.dt == DataType::F16; },
Georgios Pinitas70eb53b2021-01-06 19:42:21 +000089 REGISTER_FP32_NEON(arm_compute::cpu::elementwise_op<__fp16>),
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000090 },
91#endif // defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)
92 {
Georgios Pinitas5ee0d952021-07-05 07:21:28 +010093 "neon_s32_elementwise_unary",
94 [](const ElementwiseUnarySelectorData & data) { return data.dt == DataType::S32; },
Georgios Pinitas70eb53b2021-01-06 19:42:21 +000095 REGISTER_INTEGER_NEON(arm_compute::cpu::elementwise_op<int32_t>),
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000096 },
Michalis Spyrou20fca522021-06-07 14:23:57 +010097#endif // defined(ARM_COMPUTE_ENABLE_NEON)
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +000098};
99
100const ElementwiseUnaryKernel *get_implementation(DataType dt)
101{
102 for(const auto &uk : available_kernels)
103 {
Georgios Pinitas5ee0d952021-07-05 07:21:28 +0100104 if(uk.is_selected({ dt, CPUInfo::get() }))
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +0000105 {
106 return &uk;
107 }
George Wort5a97b282018-12-21 16:21:04 +0000108 }
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +0000109 return nullptr;
George Wort5a97b282018-12-21 16:21:04 +0000110}
Michalis Spyrou18e20ff2020-05-06 17:03:59 +0100111} // namespace
George Wort5a97b282018-12-21 16:21:04 +0000112
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000113void CpuElementwiseUnaryKernel::configure(ElementWiseUnary op, const ITensorInfo &src, ITensorInfo &dst)
George Wort5a97b282018-12-21 16:21:04 +0000114{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000115 ARM_COMPUTE_ERROR_THROW_ON(validate(op, src, dst));
Georgios Pinitas5ee0d952021-07-05 07:21:28 +0100116 const auto uk = get_implementation(src.data_type());
117 ARM_COMPUTE_ERROR_ON(uk == nullptr || uk->ukernel == nullptr);
George Wort5a97b282018-12-21 16:21:04 +0000118
Georgios Pinitas5ee0d952021-07-05 07:21:28 +0100119 _op = op;
120 _run_method = uk->ukernel;
121 _name = std::string("CpuElementwiseUnaryKernel").append("/").append(uk->name);
George Wort5a97b282018-12-21 16:21:04 +0000122
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000123 // If input shape is dynamic, expect a configured window and dst at run-time.
124 if(src.is_dynamic())
125 {
126 return;
127 }
128
Sang-Hoon Parkd0b7b4b2021-03-09 10:47:30 +0000129 auto shape_and_window = compute_output_shape_and_window(src.tensor_shape());
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000130 auto_init_if_empty(dst, shape_and_window.first, 1, src.data_type());
131 ICpuKernel::configure(shape_and_window.second);
George Wort5a97b282018-12-21 16:21:04 +0000132}
133
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000134Status CpuElementwiseUnaryKernel::validate(ElementWiseUnary op, const ITensorInfo &src, const ITensorInfo &dst)
George Wort5a97b282018-12-21 16:21:04 +0000135{
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000136 ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(&src);
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +0000137
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000138 const auto *uk = get_implementation(src.data_type());
Sang-Hoon Parkaf1870b2020-12-08 18:50:56 +0000139 ARM_COMPUTE_RETURN_ERROR_ON(uk == nullptr || uk->ukernel == nullptr);
140
Michalis Spyrou18e20ff2020-05-06 17:03:59 +0100141 switch(op)
142 {
143 case ElementWiseUnary::EXP:
144 case ElementWiseUnary::RSQRT:
145 case ElementWiseUnary::LOG:
146 case ElementWiseUnary::ROUND:
147 case ElementWiseUnary::SIN:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000148 ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&src, 1, DataType::F16, DataType::F32);
Michalis Spyrou18e20ff2020-05-06 17:03:59 +0100149 break;
150 case ElementWiseUnary::NEG:
151 case ElementWiseUnary::ABS:
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000152 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 +0100153 break;
154 default:
155 ARM_COMPUTE_ERROR("ElementWiseUnary operation not supported");
156 }
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000157 // Validate in case of configured dst
158 if(dst.total_size() > 0)
Michalis Spyrou18e20ff2020-05-06 17:03:59 +0100159 {
Sang-Hoon Park668ccdc2021-02-03 10:32:59 +0000160 ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&src, &dst);
Michalis Spyrou18e20ff2020-05-06 17:03:59 +0100161 }
162
George Wort5a97b282018-12-21 16:21:04 +0000163 return Status{};
164}
165
Sang-Hoon Park7249f152021-01-22 11:55:03 +0000166void CpuElementwiseUnaryKernel::run_op(ITensorPack &tensors, const Window &window, const ThreadInfo &info)
George Wort5a97b282018-12-21 16:21:04 +0000167{
168 ARM_COMPUTE_UNUSED(info);
Sang-Hoon Park7249f152021-01-22 11:55:03 +0000169
Georgios Pinitas5ee0d952021-07-05 07:21:28 +0100170 auto src = tensors.get_const_tensor(TensorType::ACL_SRC);
171 auto dst = tensors.get_tensor(TensorType::ACL_DST);
172
173 _run_method(src, dst, window, _op);
George Wort5a97b282018-12-21 16:21:04 +0000174}
Georgios Pinitas2eb5d162021-07-02 09:01:49 +0100175
176const char *CpuElementwiseUnaryKernel::name() const
177{
Georgios Pinitas5ee0d952021-07-05 07:21:28 +0100178 return _name.c_str();
Georgios Pinitas2eb5d162021-07-02 09:01:49 +0100179}
Sang-Hoon Park7249f152021-01-22 11:55:03 +0000180} // namespace kernels
181} // namespace cpu
George Wort5a97b282018-12-21 16:21:04 +0000182} // namespace arm_compute