diff options
author | Usama Arif <usama.arif@arm.com> | 2019-05-10 12:06:28 +0100 |
---|---|---|
committer | Usama Arif <usama.arif@arm.com> | 2019-05-13 09:01:24 +0000 |
commit | f6e475c9a092bc6e0fb53f484fbf2832183a9c44 (patch) | |
tree | a6a5f1cd6b48a8615fd942639d2b52c61d5c46be /src/core/NEON | |
parent | bcfd09a14a61bb8457555c61e7c5697b1f901ddb (diff) | |
download | ComputeLibrary-f6e475c9a092bc6e0fb53f484fbf2832183a9c44.tar.gz |
COMPMID-2268: Implement NEG for NEON.
Change-Id: I90c023dbea8ea12e9af677294ba576b2bfcc02a4
Signed-off-by: Usama Arif <usama.arif@arm.com>
Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/184216
Tested-by: bsgcomp <bsgcomp@arm.com>
Comments-Addressed: bsgcomp <bsgcomp@arm.com>
Reviewed-by: Pablo Tello <pablo.tello@arm.com>
Reviewed-on: https://review.mlplatform.org/c/1099
Tested-by: Arm Jenkins <bsgcomp@arm.com>
Reviewed-by: Pablo Marquez <pablo.tello@arm.com>
Comments-Addressed: Arm Jenkins <bsgcomp@arm.com>
Diffstat (limited to 'src/core/NEON')
-rw-r--r-- | src/core/NEON/kernels/NEElementwiseUnaryKernel.cpp | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/src/core/NEON/kernels/NEElementwiseUnaryKernel.cpp b/src/core/NEON/kernels/NEElementwiseUnaryKernel.cpp index 34696d872a..d62b165727 100644 --- a/src/core/NEON/kernels/NEElementwiseUnaryKernel.cpp +++ b/src/core/NEON/kernels/NEElementwiseUnaryKernel.cpp @@ -55,12 +55,15 @@ inline ScalarType elementwise_op_scalar(const ScalarType &a) return 1 / sqrt(a); case ElementWiseUnary::EXP: return std::exp(a); + case ElementWiseUnary::NEG: + return -a; default: ARM_COMPUTE_ERROR("NOT_SUPPORTED!"); } } -template <ElementWiseUnary op, typename VectorType> +/* Elementwise operations that are supported for float */ +template <ElementWiseUnary op, bool is_float, typename VectorType, typename std::enable_if<is_float, int>::type = 0> inline VectorType elementwise_op(const VectorType &a) { switch(op) @@ -69,12 +72,27 @@ inline VectorType elementwise_op(const VectorType &a) return wrapper::vinvsqrt(a); case ElementWiseUnary::EXP: return wrapper::vexpq(a); + case ElementWiseUnary::NEG: + return wrapper::vneg(a); default: ARM_COMPUTE_ERROR("NOT_SUPPORTED!"); } } -template <ElementWiseUnary op, typename ScalarType> +/* Elementwise operations that are supported for non floats */ +template <ElementWiseUnary op, bool is_float, typename VectorType, typename std::enable_if<!is_float, int>::type = 0> +inline VectorType elementwise_op(const VectorType &a) +{ + switch(op) + { + case ElementWiseUnary::NEG: + return wrapper::vneg(a); + default: + ARM_COMPUTE_ERROR("NOT_SUPPORTED!"); + } +} + +template <ElementWiseUnary op, typename ScalarType, bool is_float> void elementwise_op(const ITensor *in, ITensor *out, const Window &window) { const int window_step_x = 16 / sizeof(ScalarType); @@ -95,7 +113,7 @@ void elementwise_op(const ITensor *in, ITensor *out, const Window &window) int x = window_start_x; for(; x <= window_end_x - window_step_x; x += window_step_x) { - wrapper::vstore(output_ptr + x, elementwise_op<op>(wrapper::vloadq(input_ptr + x))); + wrapper::vstore(output_ptr + x, elementwise_op<op, is_float>(wrapper::vloadq(input_ptr + x))); } for(; x < window_end_x; ++x) { @@ -115,10 +133,11 @@ configure_func(const ITensor *input, ITensor *output) static std::map<std::string, NEElementwiseUnaryKernel::ElementwiseUnaryFunction *> map_function = { - { "op_F32_F32", &elementwise_op<op, float> } + { "op_F32_F32", &elementwise_op<op, float, true> }, + { "op_S32_S32", &elementwise_op<op, int32_t, false> }, }; #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC - map_function["op_F16_F16"] = &elementwise_op<op, float16_t>; + map_function["op_F16_F16"] = &elementwise_op<op, float16_t, true>; #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */ auto it = map_function.find(function_to_call); @@ -142,7 +161,7 @@ NEElementwiseUnaryKernel::NEElementwiseUnaryKernel() void NEElementwiseUnaryKernel::configure(ElementWiseUnary op, const ITensor *input, ITensor *output) { - ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input->info(), *output->info())); + ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(op, *input->info(), *output->info())); ARM_COMPUTE_ERROR_ON_NULLPTR(input, output); // Configure kernel window @@ -168,16 +187,29 @@ void NEElementwiseUnaryKernel::configure(ElementWiseUnary op, const ITensor *inp case ElementWiseUnary::EXP: _function = configure_func<ElementWiseUnary::EXP>(input, output); break; + case ElementWiseUnary::NEG: + _function = configure_func<ElementWiseUnary::NEG>(input, output); + break; default: ARM_COMPUTE_ERROR("NOT_SUPPORTED!"); } } -Status NEElementwiseUnaryKernel::validate_arguments(const ITensorInfo &input, const ITensorInfo &output) +Status NEElementwiseUnaryKernel::validate_arguments(ElementWiseUnary op, const ITensorInfo &input, const ITensorInfo &output) { ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(&input); - ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input, 1, DataType::F16, DataType::F32); - + switch(op) + { + case ElementWiseUnary::EXP: + case ElementWiseUnary::RSQRT: + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input, 1, DataType::F16, DataType::F32); + break; + case ElementWiseUnary::NEG: + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input, 1, DataType::F16, DataType::F32, DataType::S32); + break; + default: + ARM_COMPUTE_ERROR("NOT_SUPPORTED!"); + } // Validate in case of configured output if(output.total_size() > 0) { @@ -189,9 +221,8 @@ Status NEElementwiseUnaryKernel::validate_arguments(const ITensorInfo &input, co Status NEElementwiseUnaryKernel::validate(ElementWiseUnary op, const ITensorInfo *input, const ITensorInfo *output) { - ARM_COMPUTE_UNUSED(op); ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, output); - ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*input, *output)); + ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(op, *input, *output)); return Status{}; } |