diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/CL/CLKernels.h | 1 | ||||
-rw-r--r-- | src/core/CL/kernels/CLElementwiseOperationKernel.h | 256 | ||||
-rw-r--r-- | src/core/KernelTypes.h | 5 | ||||
-rw-r--r-- | src/core/gpu/cl/kernels/ClElementwiseKernel.cpp (renamed from src/core/CL/kernels/CLElementwiseOperationKernel.cpp) | 325 | ||||
-rw-r--r-- | src/core/gpu/cl/kernels/ClElementwiseKernel.h | 219 | ||||
-rw-r--r-- | src/runtime/CL/functions/CLElementwiseOperations.cpp | 64 | ||||
-rw-r--r-- | src/runtime/CL/functions/CLLogicalAnd.cpp | 10 | ||||
-rw-r--r-- | src/runtime/CL/functions/CLLogicalOr.cpp | 10 | ||||
-rw-r--r-- | src/runtime/CL/functions/CLPReluLayer.cpp | 8 | ||||
-rw-r--r-- | src/runtime/NEON/functions/NELogical.cpp | 12 | ||||
-rw-r--r-- | src/runtime/gpu/cl/operators/ClAdd.cpp | 47 | ||||
-rw-r--r-- | src/runtime/gpu/cl/operators/ClAdd.h | 100 |
12 files changed, 566 insertions, 491 deletions
diff --git a/src/core/CL/CLKernels.h b/src/core/CL/CLKernels.h index 76bc5271b4..916cf456c1 100644 --- a/src/core/CL/CLKernels.h +++ b/src/core/CL/CLKernels.h @@ -57,7 +57,6 @@ #include "src/core/CL/kernels/CLDilateKernel.h" #include "src/core/CL/kernels/CLDirectConvolutionLayerKernel.h" #include "src/core/CL/kernels/CLElementWiseUnaryLayerKernel.h" -#include "src/core/CL/kernels/CLElementwiseOperationKernel.h" #include "src/core/CL/kernels/CLErodeKernel.h" #include "src/core/CL/kernels/CLFFTDigitReverseKernel.h" #include "src/core/CL/kernels/CLFFTRadixStageKernel.h" diff --git a/src/core/CL/kernels/CLElementwiseOperationKernel.h b/src/core/CL/kernels/CLElementwiseOperationKernel.h deleted file mode 100644 index dd04a03ead..0000000000 --- a/src/core/CL/kernels/CLElementwiseOperationKernel.h +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2018-2020 Arm Limited. - * - * SPDX-License-Identifier: MIT - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef ARM_COMPUTE_CLELEMENTWISEOPERATIONKERNEL_H -#define ARM_COMPUTE_CLELEMENTWISEOPERATIONKERNEL_H - -#include "arm_compute/core/Types.h" -#include "src/core/CL/ICLKernel.h" -#include "src/core/KernelTypes.h" - -namespace arm_compute -{ -class ICLTensor; - -/** Interface for an element-wise operation kernel - * - * Element-wise operation is computed by: - * @f[ output(x,y) = OP(input1(x,y), input2(x,y))@f] - * - */ -class CLElementwiseOperationKernel : public ICLKernel -{ -public: - /** Default constructor */ - CLElementwiseOperationKernel(); - /** Prevent instances of this class from being copied (As this class contains pointers) */ - CLElementwiseOperationKernel(const CLElementwiseOperationKernel &) = delete; - /** Prevent instances of this class from being copied (As this class contains pointers) */ - CLElementwiseOperationKernel &operator=(const CLElementwiseOperationKernel &) = delete; - /** Allow instances of this class to be moved */ - CLElementwiseOperationKernel(CLElementwiseOperationKernel &&) = default; - /** Allow instances of this class to be moved */ - CLElementwiseOperationKernel &operator=(CLElementwiseOperationKernel &&) = default; - /** Default destructor */ - ~CLElementwiseOperationKernel() = default; - - // Inherited methods overridden: - void run_op(ITensorPack &tensors, const Window &window, cl::CommandQueue &queue) override; - -protected: - /** The name of the operation */ - virtual std::string name() = 0; - - /** Initialise the kernel's output. - * - * @param[in] input1 First tensor input info. Data types supported: U8/S8/QASYMM8/QASYMM8_SIGNED/U16/S16/F16/U32/S32/F32. - * @param[in] input2 Second tensor input info. Data types supported: Same as @p input1. - * @param[in] output Output tensor info. Data types supported: Same as @p input1. - * - * @return a pair of Status and Window - */ - virtual std::pair<Status, Window> validate_and_configure_window(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output) = 0; - - /** Generate the build options for the specific kernel - * - * @reutrn a CLBuildOptions struct - */ - virtual CLBuildOptions generate_build_options(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) = 0; - - /** Generate the identifier for tuning - * - * @reutrn a string - */ - virtual std::string generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &input1, const ITensorInfo &output) = 0; - - /** Commmon configure function for element-wise operators with no additional options (e.g., Div, Min, Max, SquaredDiff) - * - */ - void configure_common(ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output); - /** Commmon configure function for element-wise operators with no additional options (e.g., Div, Min, Max, SquaredDiff) - * - */ - void configure_common(const CLCompileContext &compile_context, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output); - - ActivationLayerInfo _act_info; - -private: - const ITensorInfo *_input1; /**< Source tensor info 1 */ - const ITensorInfo *_input2; /**< Source tensor info 2 */ - ITensorInfo *_output; /**< Destination tensor info */ -}; - -class CLLogicalBinaryKernel : public CLElementwiseOperationKernel -{ -public: - /** Default constructor */ - CLLogicalBinaryKernel() = default; - /** Prevent instances of this class from being copied (As this class contains pointers) */ - CLLogicalBinaryKernel(const CLLogicalBinaryKernel &) = delete; - /** Prevent instances of this class from being copied (As this class contains pointers) */ - CLLogicalBinaryKernel &operator=(const CLLogicalBinaryKernel &) = delete; - /** Allow instances of this class to be moved */ - CLLogicalBinaryKernel(CLLogicalBinaryKernel &&) = default; - /** Allow instances of this class to be moved */ - CLLogicalBinaryKernel &operator=(CLLogicalBinaryKernel &&) = default; - /** Default destructor */ - ~CLLogicalBinaryKernel() = default; - /** Function to configure kernel - * - * @param[in] compile_context The compile context to be used. - * @param[in] op Logical binary operation to be executed. - * @param[in] input1 First tensor input info. Data types supported: U8. - * @param[in] input2 Second tensor input info. Data types supported: same as @p input1. - * @param[in] output Output tensor info. Data types supported: same as @p input1. - */ - void configure(const CLCompileContext &compile_context, kernels::LogicalOperation op, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output); - /** Static function to check if the given configuration is valid for this kernel - * - * @param[in] op Logical binary operation to be executed. - * @param[in] input1 First tensor input info. Data types supported: U8. - * @param[in] input2 Second tensor input info. Data types supported: same as @p input1. - * @param[in] output Output tensor info. Data types supported: same as @p input1. - */ - static Status validate(kernels::LogicalOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output); - -private: - // Inherited methods overridden: - std::string name() override; - std::pair<Status, Window> validate_and_configure_window(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output) override; - CLBuildOptions generate_build_options(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) override; - std::string generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &input1, const ITensorInfo &output) override; - - kernels::LogicalOperation _op{ kernels::LogicalOperation::Unknown }; -}; - -/** Addition operation */ -class CLSaturatedArithmeticOperationKernel : public CLElementwiseOperationKernel -{ -public: - CLSaturatedArithmeticOperationKernel() - : CLElementwiseOperationKernel(), _policy(), _op() - { - } - - /** Static function to check if given info will lead to a valid configuration of @ref CLSaturatedArithmeticOperationKernel - * - * @param[in] op Arithmetic operation to be executed. - * @param[in] input1 First tensor input info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/F16/S32/F32. - * @param[in] input2 Second tensor input info. Data types supported: Same as @p input1. - * @param[in] output Output tensor info. Data types supported: Same as @p input1. - * @param[in] policy Policy to use to handle overflow. - * @param[in] act_info (Optional) Activation layer information in case of a fused activation. - */ - void configure(ArithmeticOperation op, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, const ConvertPolicy &policy, const ActivationLayerInfo &act_info = ActivationLayerInfo()); - /** Static function to check if given info will lead to a valid configuration of @ref CLSaturatedArithmeticOperationKernel - * - * @param[in] compile_context The compile context to be used. - * @param[in] op Arithmetic operation to be executed. - * @param[in] input1 First tensor input info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/F16/S32/F32. - * @param[in] input2 Second tensor input info. Data types supported: Same as @p input1. - * @param[in] output Output tensor info. Data types supported: Same as @p input1. - * @param[in] policy Policy to use to handle overflow. - * @param[in] act_info (Optional) Activation layer information in case of a fused activation. - */ - void configure(const CLCompileContext &compile_context, ArithmeticOperation op, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, const ConvertPolicy &policy, - const ActivationLayerInfo &act_info = ActivationLayerInfo()); - - /** Static function to check if given info will lead to a valid configuration of @ref CLSaturatedArithmeticOperationKernel - * - * @param[in] op Arithmetic operation to be executed. - * @param[in] input1 First tensor input info info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/F16/S32/F32. - * @param[in] input2 Second tensor input info info. Data types supported: Same as @p input1. - * @param[in] output Output tensor info info. Data types supported: Same as @p input1. - * @param[in] policy Policy to use to handle overflow. - * @param[in] act_info (Optional) Activation layer information in case of a fused activation. - * - * @return a Status - */ - static Status validate(ArithmeticOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ConvertPolicy &policy, - const ActivationLayerInfo &act_info = ActivationLayerInfo()); - -protected: - // Inherited methods overridden: - std::string name() override; - std::pair<Status, Window> validate_and_configure_window(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output) override; - CLBuildOptions generate_build_options(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) override; - std::string generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &input1, const ITensorInfo &output) override; - -private: - ConvertPolicy _policy; - ArithmeticOperation _op; -}; - -class CLArithmeticOperationKernel : public CLElementwiseOperationKernel -{ -public: - CLArithmeticOperationKernel() - : CLElementwiseOperationKernel(), _op() - { - } - - /** Static function to check if given info will lead to a valid configuration of @ref CLArithmeticOperationKernel - * - * @param[in] op Arithmetic operation to be executed. - * @param[in] input1 First tensor input info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/F16/S32/F32. - * @param[in] input2 Second tensor input info. Data types supported: Same as @p input1. - * @param[in] output Output tensor info. Data types supported: Same as @p input1. - * @param[in] act_info (Optional) Activation layer information in case of a fused activation. - */ - void configure(ArithmeticOperation op, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, const ActivationLayerInfo &act_info = ActivationLayerInfo()); - /** Static function to check if given info will lead to a valid configuration of @ref CLArithmeticOperationKernel - * - * @param[in] compile_context The compile context to be used. - * @param[in] op Arithmetic operation to be executed. - * @param[in] input1 First tensor input info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/F16/S32/F32. - * @param[in] input2 Second tensor input info. Data types supported: Same as @p input1. - * @param[in] output Output tensor info. Data types supported: Same as @p input1. - * @param[in] act_info (Optional) Activation layer information in case of a fused activation. - */ - void configure(const CLCompileContext &compile_context, ArithmeticOperation op, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, - const ActivationLayerInfo &act_info = ActivationLayerInfo()); - - /** Static function to check if given info will lead to a valid configuration of @ref CLArithmeticOperationKernel - * - * @param[in] op Arithmetic operation to be executed. - * @param[in] input1 First tensor input info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/F16/S32/F32. - * @param[in] input2 Second tensor input info. Data types supported: Same as @p input1. - * @param[in] output Output tensor info. Data types supported: Same as @p input1. - * @param[in] act_info (Optional) Activation layer information in case of a fused activation. - * - * @return a Status - */ - static Status validate(ArithmeticOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info = ActivationLayerInfo()); - -protected: - // Inherited methods overridden: - std::string name() override; - std::pair<Status, Window> validate_and_configure_window(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output) override; - CLBuildOptions generate_build_options(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) override; - std::string generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &input1, const ITensorInfo &output) override; - -private: - ArithmeticOperation _op; -}; -} // namespace arm_compute -#endif /* ARM_COMPUTE_CLELEMENTWISEOPERATIONKERNEL_H */ diff --git a/src/core/KernelTypes.h b/src/core/KernelTypes.h index 12e6bc90ae..a32f5db93c 100644 --- a/src/core/KernelTypes.h +++ b/src/core/KernelTypes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Arm Limited. + * Copyright (c) 2020-2021 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -26,8 +26,6 @@ namespace arm_compute { -namespace kernels -{ /** List of supported logical operations */ enum class LogicalOperation { @@ -36,6 +34,5 @@ enum class LogicalOperation Or, /**< Logical Or || */ Not, /**< Logical Not ! */ }; -} // namespace kernels } // namespace arm_compute #endif /* ARM_COMPUTE_KERNEL_TYPES_H */ diff --git a/src/core/CL/kernels/CLElementwiseOperationKernel.cpp b/src/core/gpu/cl/kernels/ClElementwiseKernel.cpp index 7c1d940494..7d204b1348 100644 --- a/src/core/CL/kernels/CLElementwiseOperationKernel.cpp +++ b/src/core/gpu/cl/kernels/ClElementwiseKernel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020 Arm Limited. + * Copyright (c) 2018-2021 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "src/core/CL/kernels/CLElementwiseOperationKernel.h" +#include "src/core/gpu/cl/kernels/ClElementwiseKernel.h" #include "arm_compute/core/CL/CLHelpers.h" #include "arm_compute/core/CL/ICLTensor.h" @@ -35,6 +35,10 @@ namespace arm_compute { +namespace opencl +{ +namespace kernels +{ namespace { constexpr unsigned int vector_size_byte_opencl = 16; @@ -57,91 +61,91 @@ std::map<ArithmeticOperation, std::string> supported_sat_arithmetic_ops = { ArithmeticOperation::SUB, "SUB" }, }; -std::string generate_id_for_tuning_common(const std::string &kernel_name, const ITensorInfo &input1, const ITensorInfo &output) +std::string generate_id_for_tuning_common(const std::string &kernel_name, const ITensorInfo &src1, const ITensorInfo &dst) { std::string config_id; // Set config_id for enabling LWS tuning config_id = kernel_name; config_id += "_"; - config_id += lower_string(string_from_data_type(input1.data_type())); + config_id += lower_string(string_from_data_type(src1.data_type())); config_id += "_"; - config_id += support::cpp11::to_string(output.dimension(0)); + config_id += support::cpp11::to_string(dst.dimension(0)); config_id += "_"; - config_id += support::cpp11::to_string(output.dimension(1)); + config_id += support::cpp11::to_string(dst.dimension(1)); return config_id; } -Status validate_arguments_with_float_only_supported_rules(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) +Status validate_arguments_with_float_only_supported_rules(const ITensorInfo &src1, const ITensorInfo &src2, const ITensorInfo &dst) { - ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(&input1, &input2, &output); - ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(&input1); - ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input1, 1, DataType::F16, DataType::F32); - ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&input1, &input2); + ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(&src1, &src2, &dst); + ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(&src1); + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&src1, 1, DataType::F16, DataType::F32); + ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&src1, &src2); - const TensorShape out_shape = TensorShape::broadcast_shape(input1.tensor_shape(), input2.tensor_shape()); + const TensorShape out_shape = TensorShape::broadcast_shape(src1.tensor_shape(), src2.tensor_shape()); ARM_COMPUTE_RETURN_ERROR_ON_MSG(out_shape.total_size() == 0, "Inputs are not broadcast compatible"); - // Validate in case of configured output - if(output.total_size() > 0) + // Validate in case of configured dst + if(dst.total_size() > 0) { - ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&output, 1, DataType::F16, DataType::F32); - ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&input1, &output); - ARM_COMPUTE_RETURN_ERROR_ON_MSG(detail::have_different_dimensions(out_shape, output.tensor_shape(), 0), - "Wrong shape for output"); + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&dst, 1, DataType::F16, DataType::F32); + ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&src1, &dst); + ARM_COMPUTE_RETURN_ERROR_ON_MSG(detail::have_different_dimensions(out_shape, dst.tensor_shape(), 0), + "Wrong shape for dst"); } return Status{}; } -Status validate_arguments_with_arithmetic_rules(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) +Status validate_arguments_with_arithmetic_rules(const ITensorInfo &src1, const ITensorInfo &src2, const ITensorInfo &dst) { - ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(&input1); - ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input1, 1, DataType::U8, DataType::QASYMM8, DataType::QASYMM8_SIGNED, + ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(&src1); + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&src1, 1, DataType::U8, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::S16, DataType::QSYMM16, DataType::F16, DataType::S32, DataType::F32); - ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(&input2); - ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input2, 1, DataType::U8, DataType::QASYMM8, DataType::QASYMM8_SIGNED, + ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(&src2); + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&src2, 1, DataType::U8, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::S16, DataType::QSYMM16, DataType::F16, DataType::S32, DataType::F32); - const bool is_quantized = is_data_type_quantized(input1.data_type()) || is_data_type_quantized(input2.data_type()); + const bool is_quantized = is_data_type_quantized(src1.data_type()) || is_data_type_quantized(src2.data_type()); if(is_quantized) { - ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&input1, &input2); + ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&src1, &src2); - if(is_data_type_quantized_symmetric(input1.data_type())) + if(is_data_type_quantized_symmetric(src1.data_type())) { - const int32_t in1_offset = input1.quantization_info().uniform().offset; - const int32_t in2_offset = input2.quantization_info().uniform().offset; + const int32_t in1_offset = src1.quantization_info().uniform().offset; + const int32_t in2_offset = src2.quantization_info().uniform().offset; ARM_COMPUTE_RETURN_ERROR_ON_MSG(in1_offset != 0, "For quantized symmetric, offset must be zero"); ARM_COMPUTE_RETURN_ERROR_ON_MSG(in2_offset != 0, "For quantized symmetric, offset must be zero"); } } - const TensorShape out_shape = TensorShape::broadcast_shape(input1.tensor_shape(), input2.tensor_shape()); + const TensorShape out_shape = TensorShape::broadcast_shape(src1.tensor_shape(), src2.tensor_shape()); ARM_COMPUTE_RETURN_ERROR_ON_MSG(out_shape.total_size() == 0, "Inputs are not broadcast compatible"); - // Validate in case of configured output - if(output.total_size() > 0) + // Validate in case of configured dst + if(dst.total_size() > 0) { - ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(&output); - ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&output, 1, DataType::U8, DataType::QASYMM8, DataType::QASYMM8_SIGNED, + ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(&dst); + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&dst, 1, DataType::U8, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::S16, DataType::QSYMM16, DataType::F16, DataType::S32, DataType::F32); - ARM_COMPUTE_RETURN_ERROR_ON_MSG((output.data_type() == DataType::U8) && ((input1.data_type() != DataType::U8) || (input2.data_type() != DataType::U8)), - "Output can only be U8 if both inputs are U8"); - ARM_COMPUTE_RETURN_ERROR_ON_MSG(detail::have_different_dimensions(out_shape, output.tensor_shape(), 0), - "Wrong shape for output"); + ARM_COMPUTE_RETURN_ERROR_ON_MSG((dst.data_type() == DataType::U8) && ((src1.data_type() != DataType::U8) || (src2.data_type() != DataType::U8)), + "dst can only be U8 if both inputs are U8"); + ARM_COMPUTE_RETURN_ERROR_ON_MSG(detail::have_different_dimensions(out_shape, dst.tensor_shape(), 0), + "Wrong shape for dst"); if(is_quantized) { - ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&input1, &output); + ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&src1, &dst); - if(is_data_type_quantized_symmetric(output.data_type())) + if(is_data_type_quantized_symmetric(dst.data_type())) { - const int32_t offset = output.quantization_info().uniform().offset; + const int32_t offset = dst.quantization_info().uniform().offset; ARM_COMPUTE_RETURN_ERROR_ON_MSG(offset != 0, "For quantized symmetric, offset must be zero"); } } @@ -149,25 +153,25 @@ Status validate_arguments_with_arithmetic_rules(const ITensorInfo &input1, const return Status{}; } -CLBuildOptions generate_build_options_with_arithmetic_rules(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output, const std::string &operation_string) +CLBuildOptions generate_build_options_with_arithmetic_rules(const ITensorInfo &src1, const ITensorInfo &src2, const ITensorInfo &dst, const std::string &operation_string) { CLBuildOptions build_opts; - const unsigned int num_elems_processed_per_iteration = adjust_vec_size(vector_size_byte_opencl / output.element_size(), output.dimension(0)); + const unsigned int num_elems_processed_per_iteration = adjust_vec_size(vector_size_byte_opencl / dst.element_size(), dst.dimension(0)); - build_opts.add_option("-DDATA_TYPE_IN1=" + get_cl_type_from_data_type(input1.data_type())); - build_opts.add_option("-DDATA_TYPE_IN2=" + get_cl_type_from_data_type(input2.data_type())); - build_opts.add_option("-DDATA_TYPE_OUT=" + get_cl_type_from_data_type(output.data_type())); - build_opts.add_option("-DVEC_SIZE_IN1=" + support::cpp11::to_string(input1.dimension(0) == 1 ? 1 : num_elems_processed_per_iteration)); - build_opts.add_option("-DVEC_SIZE_IN2=" + support::cpp11::to_string(input2.dimension(0) == 1 ? 1 : num_elems_processed_per_iteration)); + build_opts.add_option("-DDATA_TYPE_IN1=" + get_cl_type_from_data_type(src1.data_type())); + build_opts.add_option("-DDATA_TYPE_IN2=" + get_cl_type_from_data_type(src2.data_type())); + build_opts.add_option("-DDATA_TYPE_OUT=" + get_cl_type_from_data_type(dst.data_type())); + build_opts.add_option("-DVEC_SIZE_IN1=" + support::cpp11::to_string(src1.dimension(0) == 1 ? 1 : num_elems_processed_per_iteration)); + build_opts.add_option("-DVEC_SIZE_IN2=" + support::cpp11::to_string(src2.dimension(0) == 1 ? 1 : num_elems_processed_per_iteration)); build_opts.add_option("-DVEC_SIZE_OUT=" + support::cpp11::to_string(num_elems_processed_per_iteration)); - build_opts.add_option("-DVEC_SIZE_LEFTOVER=" + support::cpp11::to_string(output.dimension(0) % num_elems_processed_per_iteration)); + build_opts.add_option("-DVEC_SIZE_LEFTOVER=" + support::cpp11::to_string(dst.dimension(0) % num_elems_processed_per_iteration)); build_opts.add_option("-DOP=" + operation_string); - if(is_data_type_quantized(input1.data_type())) + if(is_data_type_quantized(src1.data_type())) { - const UniformQuantizationInfo iq1info = input1.quantization_info().uniform(); - const UniformQuantizationInfo iq2info = input2.quantization_info().uniform(); - const UniformQuantizationInfo oqinfo = output.quantization_info().uniform(); + const UniformQuantizationInfo iq1info = src1.quantization_info().uniform(); + const UniformQuantizationInfo iq2info = src2.quantization_info().uniform(); + const UniformQuantizationInfo oqinfo = dst.quantization_info().uniform(); build_opts.add_option("-DOFFSET_IN1=" + support::cpp11::to_string(iq1info.offset)); build_opts.add_option("-DOFFSET_IN2=" + support::cpp11::to_string(iq2info.offset)); @@ -179,97 +183,92 @@ CLBuildOptions generate_build_options_with_arithmetic_rules(const ITensorInfo &i return build_opts; } -std::pair<Status, Window> configure_window_arithmetic_common(ITensorInfo &output) +std::pair<Status, Window> configure_window_arithmetic_common(ITensorInfo &dst) { - const unsigned int num_elems_processed_per_iteration = adjust_vec_size(vector_size_byte_opencl / output.element_size(), output.dimension(0)); - Window win = calculate_max_window(output, Steps(num_elems_processed_per_iteration)); + const unsigned int num_elems_processed_per_iteration = adjust_vec_size(vector_size_byte_opencl / dst.element_size(), dst.dimension(0)); + Window win = calculate_max_window(dst, Steps(num_elems_processed_per_iteration)); return std::make_pair(Status{}, win); } -std::pair<Status, Window> validate_and_configure_window_for_arithmetic_operators(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output) +std::pair<Status, Window> validate_and_configure_window_for_arithmetic_operators(ITensorInfo &src1, ITensorInfo &src2, ITensorInfo &dst) { - const std::pair<TensorShape, ValidRegion> broadcast_pair = ITensorInfo::broadcast_shape_and_valid_region(input1, input2); + const std::pair<TensorShape, ValidRegion> broadcast_pair = ITensorInfo::broadcast_shape_and_valid_region(src1, src2); const TensorShape &out_shape = broadcast_pair.first; - set_shape_if_empty(output, out_shape); + set_shape_if_empty(dst, out_shape); - if(input1.data_type() == DataType::S16 || input2.data_type() == DataType::S16) + if(src1.data_type() == DataType::S16 || src2.data_type() == DataType::S16) { - set_format_if_unknown(output, Format::S16); + set_format_if_unknown(dst, Format::S16); } - else if(input1.data_type() == DataType::F16 || input2.data_type() == DataType::F16) + else if(src1.data_type() == DataType::F16 || src2.data_type() == DataType::F16) { - set_format_if_unknown(output, Format::F16); + set_format_if_unknown(dst, Format::F16); } - else if(input1.data_type() == DataType::F32 || input2.data_type() == DataType::F32) + else if(src1.data_type() == DataType::F32 || src2.data_type() == DataType::F32) { - set_format_if_unknown(output, Format::F32); + set_format_if_unknown(dst, Format::F32); } - else if(input1.data_type() == DataType::QASYMM8 || input2.data_type() == DataType::QASYMM8) + else if(src1.data_type() == DataType::QASYMM8 || src2.data_type() == DataType::QASYMM8) { - set_data_type_if_unknown(output, DataType::QASYMM8); + set_data_type_if_unknown(dst, DataType::QASYMM8); } - else if(input1.data_type() == DataType::QASYMM8_SIGNED || input2.data_type() == DataType::QASYMM8_SIGNED) + else if(src1.data_type() == DataType::QASYMM8_SIGNED || src2.data_type() == DataType::QASYMM8_SIGNED) { - set_data_type_if_unknown(output, DataType::QASYMM8_SIGNED); + set_data_type_if_unknown(dst, DataType::QASYMM8_SIGNED); } - else if(input1.data_type() == DataType::QSYMM16 || input2.data_type() == DataType::QSYMM16) + else if(src1.data_type() == DataType::QSYMM16 || src2.data_type() == DataType::QSYMM16) { - set_data_type_if_unknown(output, DataType::QSYMM16); + set_data_type_if_unknown(dst, DataType::QSYMM16); } - return configure_window_arithmetic_common(output); + return configure_window_arithmetic_common(dst); } -std::pair<Status, Window> validate_and_configure_window_for_logical_binary_operators(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output) +std::pair<Status, Window> validate_and_configure_window_for_logical_binary_operators(ITensorInfo &src1, ITensorInfo &src2, ITensorInfo &dst) { - const std::pair<TensorShape, ValidRegion> broadcast_pair = ITensorInfo::broadcast_shape_and_valid_region(input1, input2); + const std::pair<TensorShape, ValidRegion> broadcast_pair = ITensorInfo::broadcast_shape_and_valid_region(src1, src2); const TensorShape &out_shape = broadcast_pair.first; - set_shape_if_empty(output, out_shape); - set_data_type_if_unknown(output, DataType::U8); + set_shape_if_empty(dst, out_shape); + set_data_type_if_unknown(dst, DataType::U8); // The arithmetic utility functions can be share - return configure_window_arithmetic_common(output); + return configure_window_arithmetic_common(dst); } -std::pair<Status, Window> validate_and_configure_window_for_division(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output) +std::pair<Status, Window> validate_and_configure_window_for_division(ITensorInfo &src1, ITensorInfo &src2, ITensorInfo &dst) { - const std::pair<TensorShape, ValidRegion> broadcast_pair = ITensorInfo::broadcast_shape_and_valid_region(input1, input2); + const std::pair<TensorShape, ValidRegion> broadcast_pair = ITensorInfo::broadcast_shape_and_valid_region(src1, src2); const TensorShape &out_shape = broadcast_pair.first; - auto_init_if_empty(output, out_shape, 1, input1.data_type()); - return configure_window_arithmetic_common(output); + auto_init_if_empty(dst, out_shape, 1, src1.data_type()); + return configure_window_arithmetic_common(dst); } } // namespace -CLElementwiseOperationKernel::CLElementwiseOperationKernel() - : _act_info(), _input1(nullptr), _input2(nullptr), _output(nullptr) +void ClElementwiseKernel::configure_common(ITensorInfo *src1, ITensorInfo *src2, ITensorInfo *dst) { + configure_common(CLKernelLibrary::get().get_compile_context(), src1, src2, dst); } -void CLElementwiseOperationKernel::configure_common(ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output) -{ - configure_common(CLKernelLibrary::get().get_compile_context(), input1, input2, output); -} - -void CLElementwiseOperationKernel::configure_common(const CLCompileContext &compile_context, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output) +void ClElementwiseKernel::configure_common(const ClCompileContext &compile_context, ITensorInfo *src1, ITensorInfo *src2, ITensorInfo *dst) { // Configure kernel window - auto win_config = validate_and_configure_window(*input1, *input2, *output); + auto win_config = validate_and_configure_window(*src1, *src2, *dst); ARM_COMPUTE_ERROR_THROW_ON(win_config.first); - _input1 = input1; - _input2 = input2; - _output = output; + _src1 = src1; + _src2 = src2; + _dst = dst; std::string kernel_name = "elementwise_operation_" + name(); - if(is_data_type_quantized(input1->data_type())) + if(is_data_type_quantized(src1->data_type())) { kernel_name += "_quantized"; } // Set kernel build options - CLBuildOptions build_opts = generate_build_options(*input1, *input2, *output); + CLBuildOptions build_opts = generate_build_options(*src1, *src2, *dst); if(_act_info.enabled()) { build_opts.add_option("-DACTIVATION_TYPE=" + lower_string(string_from_activation_func(_act_info.activation()))); @@ -282,10 +281,10 @@ void CLElementwiseOperationKernel::configure_common(const CLCompileContext &comp ICLKernel::configure_internal(win_config.second); - _config_id = generate_id_for_tuning(kernel_name, *input1, *output); + _config_id = generate_id_for_tuning(kernel_name, *src1, *dst); } -void CLElementwiseOperationKernel::run_op(ITensorPack &tensors, const Window &window, cl::CommandQueue &queue) +void ClElementwiseKernel::run_op(ITensorPack &tensors, const Window &window, ::cl::CommandQueue &queue) { ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this); ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(ICLKernel::window(), window); @@ -315,57 +314,57 @@ void CLElementwiseOperationKernel::run_op(ITensorPack &tensors, const Window &wi const TensorShape &in_shape1_collapsed = has_collapsed ? in_shape1.collapsed_from(Window::DimZ) : in_shape1; const TensorShape &in_shape2_collapsed = has_collapsed ? in_shape2.collapsed_from(Window::DimZ) : in_shape2; - Window slice = collapsed.first_slice_window_3D(); - Window slice_input1 = slice.broadcast_if_dimension_le_one(in_shape1_collapsed); - Window slice_input2 = slice.broadcast_if_dimension_le_one(in_shape2_collapsed); + Window slice = collapsed.first_slice_window_3D(); + Window slice_src1 = slice.broadcast_if_dimension_le_one(in_shape1_collapsed); + Window slice_src2 = slice.broadcast_if_dimension_le_one(in_shape2_collapsed); do { unsigned int idx = 0; - add_3D_tensor_argument(idx, src_0, slice_input1); - add_3D_tensor_argument(idx, src_1, slice_input2); + add_3D_tensor_argument(idx, src_0, slice_src1); + add_3D_tensor_argument(idx, src_1, slice_src2); add_3D_tensor_argument(idx, dst, slice); enqueue(queue, *this, slice, lws_hint()); - ARM_COMPUTE_UNUSED(collapsed.slide_window_slice_3D(slice_input1)); - ARM_COMPUTE_UNUSED(collapsed.slide_window_slice_3D(slice_input2)); + ARM_COMPUTE_UNUSED(collapsed.slide_window_slice_3D(slice_src1)); + ARM_COMPUTE_UNUSED(collapsed.slide_window_slice_3D(slice_src2)); } while(collapsed.slide_window_slice_3D(slice)); } /** Logical binary */ -void CLLogicalBinaryKernel::configure(const CLCompileContext &compile_context, kernels::LogicalOperation op, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output) +void ClLogicalBinaryKernel::configure(const ClCompileContext &compile_context, LogicalOperation op, ITensorInfo *src1, ITensorInfo *src2, ITensorInfo *dst) { - ARM_COMPUTE_ERROR_ON_NULLPTR(input1, input2, output); - ARM_COMPUTE_ERROR_THROW_ON(CLLogicalBinaryKernel::validate(op, input1, input2, output)); + ARM_COMPUTE_ERROR_ON_NULLPTR(src1, src2, dst); + ARM_COMPUTE_ERROR_THROW_ON(ClLogicalBinaryKernel::validate(op, src1, src2, dst)); _op = op; - configure_common(compile_context, input1, input2, output); + configure_common(compile_context, src1, src2, dst); } -Status CLLogicalBinaryKernel::validate(kernels::LogicalOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output) +Status ClLogicalBinaryKernel::validate(LogicalOperation op, const ITensorInfo *src1, const ITensorInfo *src2, const ITensorInfo *dst) { ARM_COMPUTE_UNUSED(op); - ARM_COMPUTE_ASSERT(op != kernels::LogicalOperation::Unknown && op != kernels::LogicalOperation::Not); - ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output); + ARM_COMPUTE_ASSERT(op != LogicalOperation::Unknown && op != LogicalOperation::Not); + ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src1, src2, dst); - ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input1, 1, DataType::U8); - ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input1, input2); + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(src1, 1, DataType::U8); + ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(src1, src2); - ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments_with_arithmetic_rules(*input1, *input2, *output)); - ARM_COMPUTE_RETURN_ON_ERROR(validate_and_configure_window_for_logical_binary_operators(*input1->clone(), *input2->clone(), *output->clone()).first); + ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments_with_arithmetic_rules(*src1, *src2, *dst)); + ARM_COMPUTE_RETURN_ON_ERROR(validate_and_configure_window_for_logical_binary_operators(*src1->clone(), *src2->clone(), *dst->clone()).first); return Status{}; } -std::string CLLogicalBinaryKernel::name() +std::string ClLogicalBinaryKernel::name() { switch(_op) { - case kernels::LogicalOperation::And: + case LogicalOperation::And: return "AND"; - case kernels::LogicalOperation::Or: + case LogicalOperation::Or: return "OR"; - case kernels::LogicalOperation::Not: + case LogicalOperation::Not: /* fall through */ default: ARM_COMPUTE_ASSERT(true); @@ -373,36 +372,29 @@ std::string CLLogicalBinaryKernel::name() return ""; } -std::pair<Status, Window> CLLogicalBinaryKernel::validate_and_configure_window(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output) +std::pair<Status, Window> ClLogicalBinaryKernel::validate_and_configure_window(ITensorInfo &src1, ITensorInfo &src2, ITensorInfo &dst) { - return validate_and_configure_window_for_logical_binary_operators(input1, input2, output); + return validate_and_configure_window_for_logical_binary_operators(src1, src2, dst); } -CLBuildOptions CLLogicalBinaryKernel::generate_build_options(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) +CLBuildOptions ClLogicalBinaryKernel::generate_build_options(const ITensorInfo &src1, const ITensorInfo &src2, const ITensorInfo &dst) { // The arithmetic utility functions can be share - return generate_build_options_with_arithmetic_rules(input1, input2, output, name()); + return generate_build_options_with_arithmetic_rules(src1, src2, dst, name()); } -std::string CLLogicalBinaryKernel::generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &input1, const ITensorInfo &output) +std::string ClLogicalBinaryKernel::generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &src1, const ITensorInfo &dst) { - return generate_id_for_tuning_common(kernel_name, input1, output); + return generate_id_for_tuning_common(kernel_name, src1, dst); } /** Arithmetic operations with saturation*/ - -void CLSaturatedArithmeticOperationKernel::configure(ArithmeticOperation op, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, const ConvertPolicy &policy, - const ActivationLayerInfo &act_info) -{ - configure(CLKernelLibrary::get().get_compile_context(), op, input1, input2, output, policy, act_info); -} - -void CLSaturatedArithmeticOperationKernel::configure(const CLCompileContext &compile_context, ArithmeticOperation op, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, - const ConvertPolicy &policy, - const ActivationLayerInfo &act_info) +void ClSaturatedArithmeticKernel::configure(const ClCompileContext &compile_context, ArithmeticOperation op, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, + const ConvertPolicy &policy, + const ActivationLayerInfo &act_info) { ARM_COMPUTE_ERROR_ON_NULLPTR(input1, input2, output); - ARM_COMPUTE_ERROR_THROW_ON(CLSaturatedArithmeticOperationKernel::validate(op, input1, input2, output, policy, act_info)); + ARM_COMPUTE_ERROR_THROW_ON(ClSaturatedArithmeticKernel::validate(op, input1, input2, output, policy, act_info)); auto padding_info = get_padding_info({ input1, input2, output }); _policy = policy; @@ -412,8 +404,8 @@ void CLSaturatedArithmeticOperationKernel::configure(const CLCompileContext &com ARM_COMPUTE_ERROR_ON(has_padding_changed(padding_info)); } -Status CLSaturatedArithmeticOperationKernel::validate(ArithmeticOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ConvertPolicy &policy, - const ActivationLayerInfo &act_info) +Status ClSaturatedArithmeticKernel::validate(ArithmeticOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ConvertPolicy &policy, + const ActivationLayerInfo &act_info) { ARM_COMPUTE_UNUSED(op, policy); ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output); @@ -424,19 +416,20 @@ Status CLSaturatedArithmeticOperationKernel::validate(ArithmeticOperation op, co return Status{}; } -std::pair<Status, Window> CLSaturatedArithmeticOperationKernel::validate_and_configure_window(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output) +std::pair<Status, Window> ClSaturatedArithmeticKernel::validate_and_configure_window(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output) { return validate_and_configure_window_for_arithmetic_operators(input1, input2, output); } -CLBuildOptions CLSaturatedArithmeticOperationKernel::generate_build_options(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) +CLBuildOptions ClSaturatedArithmeticKernel::generate_build_options(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) { const bool has_float_out = is_data_type_float(output.data_type()); auto build_options = generate_build_options_with_arithmetic_rules(input1, input2, output, name()); build_options.add_option((_policy == ConvertPolicy::WRAP || has_float_out) ? "-DWRAP" : "-DSATURATE"); return build_options; } -std::string CLSaturatedArithmeticOperationKernel::generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &input1, const ITensorInfo &output) + +std::string ClSaturatedArithmeticKernel::generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &input1, const ITensorInfo &output) { auto config_id = generate_id_for_tuning_common(kernel_name, input1, output); config_id += (_policy == ConvertPolicy::WRAP) ? "_wrap_" : "_saturate_"; @@ -444,73 +437,69 @@ std::string CLSaturatedArithmeticOperationKernel::generate_id_for_tuning(const s return config_id; } -std::string CLSaturatedArithmeticOperationKernel::name() +std::string ClSaturatedArithmeticKernel::name() { return supported_sat_arithmetic_ops[_op]; } /** Arithmetic operations*/ - -void CLArithmeticOperationKernel::configure(ArithmeticOperation op, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, const ActivationLayerInfo &act_info) -{ - configure(CLKernelLibrary::get().get_compile_context(), op, input1, input2, output, act_info); -} - -void CLArithmeticOperationKernel::configure(const CLCompileContext &compile_context, ArithmeticOperation op, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, - const ActivationLayerInfo &act_info) +void ClArithmeticKernel::configure(const ClCompileContext &compile_context, ArithmeticOperation op, ITensorInfo *src1, ITensorInfo *src2, ITensorInfo *dst, + const ActivationLayerInfo &act_info) { - ARM_COMPUTE_ERROR_ON_NULLPTR(input1, input2, output); - ARM_COMPUTE_ERROR_THROW_ON(CLArithmeticOperationKernel::validate(op, input1, input2, output, act_info)); - auto padding_info = get_padding_info({ input1, input2, output }); + ARM_COMPUTE_ERROR_ON_NULLPTR(src1, src2, dst); + ARM_COMPUTE_ERROR_THROW_ON(ClArithmeticKernel::validate(op, src1, src2, dst, act_info)); + auto padding_info = get_padding_info({ src1, src2, dst }); _op = op; _act_info = act_info; - configure_common(compile_context, input1, input2, output); + configure_common(compile_context, src1, src2, dst); ARM_COMPUTE_ERROR_ON(has_padding_changed(padding_info)); } -Status CLArithmeticOperationKernel::validate(ArithmeticOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info) +Status ClArithmeticKernel::validate(ArithmeticOperation op, const ITensorInfo *src1, const ITensorInfo *src2, const ITensorInfo *dst, const ActivationLayerInfo &act_info) { - ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output); + ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src1, src2, dst); if(op == ArithmeticOperation::DIV || op == ArithmeticOperation::POWER) { // Division and Power operators don't support integer arithmetic - ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments_with_float_only_supported_rules(*input1, *input2, *output)); - ARM_COMPUTE_RETURN_ON_ERROR(validate_and_configure_window_for_division(*input1->clone(), *input2->clone(), *output->clone()).first); + ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments_with_float_only_supported_rules(*src1, *src2, *dst)); + ARM_COMPUTE_RETURN_ON_ERROR(validate_and_configure_window_for_division(*src1->clone(), *src2->clone(), *dst->clone()).first); } else { - ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments_with_arithmetic_rules(*input1, *input2, *output)); - ARM_COMPUTE_RETURN_ON_ERROR(validate_and_configure_window_for_arithmetic_operators(*input1->clone(), *input2->clone(), *output->clone()).first); + ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments_with_arithmetic_rules(*src1, *src2, *dst)); + ARM_COMPUTE_RETURN_ON_ERROR(validate_and_configure_window_for_arithmetic_operators(*src1->clone(), *src2->clone(), *dst->clone()).first); } - ARM_COMPUTE_RETURN_ERROR_ON(act_info.enabled() && !is_data_type_float(output->data_type())); + ARM_COMPUTE_RETURN_ERROR_ON(act_info.enabled() && !is_data_type_float(dst->data_type())); return Status{}; } -std::pair<Status, Window> CLArithmeticOperationKernel::validate_and_configure_window(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output) +std::pair<Status, Window> ClArithmeticKernel::validate_and_configure_window(ITensorInfo &src1, ITensorInfo &src2, ITensorInfo &dst) { if(_op == ArithmeticOperation::DIV || _op == ArithmeticOperation::POWER) { // Division and Power operators don't support integer arithmetic - return validate_and_configure_window_for_division(input1, input2, output); + return validate_and_configure_window_for_division(src1, src2, dst); } else { - return validate_and_configure_window_for_arithmetic_operators(input1, input2, output); + return validate_and_configure_window_for_arithmetic_operators(src1, src2, dst); } } -CLBuildOptions CLArithmeticOperationKernel::generate_build_options(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) +CLBuildOptions ClArithmeticKernel::generate_build_options(const ITensorInfo &src1, const ITensorInfo &src2, const ITensorInfo &dst) { - return generate_build_options_with_arithmetic_rules(input1, input2, output, name()); + return generate_build_options_with_arithmetic_rules(src1, src2, dst, name()); } -std::string CLArithmeticOperationKernel::generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &input1, const ITensorInfo &output) +std::string ClArithmeticKernel::generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &src1, const ITensorInfo &dst) { - return generate_id_for_tuning_common(kernel_name, input1, output); + return generate_id_for_tuning_common(kernel_name, src1, dst); } -std::string CLArithmeticOperationKernel::name() +std::string ClArithmeticKernel::name() { return supported_arithmetic_ops[_op]; } +} // namespace kernels +} // namespace opencl } // namespace arm_compute diff --git a/src/core/gpu/cl/kernels/ClElementwiseKernel.h b/src/core/gpu/cl/kernels/ClElementwiseKernel.h new file mode 100644 index 0000000000..4ed8ae73ab --- /dev/null +++ b/src/core/gpu/cl/kernels/ClElementwiseKernel.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2018-2021 Arm Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef ARM_COMPUTE_CL_ELEMENTWISE_KERNEL_H +#define ARM_COMPUTE_CL_ELEMENTWISE_KERNEL_H + +#include "src/core/KernelTypes.h" +#include "src/core/common/Macros.h" +#include "src/core/gpu/cl/ClCompileContext.h" +#include "src/core/gpu/cl/IClKernel.h" + +namespace arm_compute +{ +namespace opencl +{ +namespace kernels +{ +/** Interface for an element-wise operation kernel + * + * Element-wise operation is computed by: + * @f[ dst(x,y) = OP(src1(x,y), src2(x,y))@f] + * + */ +class ClElementwiseKernel : public IClKernel +{ +public: + /** Default constructor */ + ClElementwiseKernel() = default; + ARM_COMPUTE_DISALLOW_COPY_ALLOW_MOVE(ClElementwiseKernel); + + // Inherited methods overridden: + void run_op(ITensorPack &tensors, const Window &window, ::cl::CommandQueue &queue) override; + +protected: + /** The name of the operation */ + virtual std::string name() = 0; + + /** Configure kernel for a given list of arguments + * + * @param[in] src1 First source tensor info. Data types supported: U8/S8/QASYMM8/QASYMM8_SIGNED/U16/S16/F16/U32/S32/F32. + * @param[in] src2 Second source tensor info. Data types supported: same as @p src1. + * @param[in] dst Destination tensor info. Data types supported: same as @p src1. + * + * @return a pair of Status and Window + */ + virtual std::pair<Status, Window> validate_and_configure_window(ITensorInfo &src1, ITensorInfo &src2, ITensorInfo &dst) = 0; + + /** Generate the build options for the specific kernel + * + * @reutrn a CLBuildOptions struct + */ + virtual CLBuildOptions generate_build_options(const ITensorInfo &src1, const ITensorInfo &src2, const ITensorInfo &dst) = 0; + + /** Generate the identifier for tuning + * + * @reutrn a string + */ + virtual std::string generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &src1, const ITensorInfo &dst) = 0; + + /** Commmon configure function for element-wise operators with no additional options (e.g., Div, Min, Max, SquaredDiff) + * + */ + void configure_common(ITensorInfo *src1, ITensorInfo *src2, ITensorInfo *dst); + /** Commmon configure function for element-wise operators with no additional options (e.g., Div, Min, Max, SquaredDiff) + * + */ + void configure_common(const ClCompileContext &compile_context, ITensorInfo *src1, ITensorInfo *src2, ITensorInfo *dst); + + ActivationLayerInfo _act_info{}; + +private: + const ITensorInfo *_src1{ nullptr }; /**< Source tensor info 1 */ + const ITensorInfo *_src2{ nullptr }; /**< Source tensor info 2 */ + ITensorInfo *_dst{ nullptr }; /**< Destination tensor info */ +}; + +class ClLogicalBinaryKernel : public ClElementwiseKernel +{ +public: + /** Default constructor */ + ClLogicalBinaryKernel() = default; + ARM_COMPUTE_DISALLOW_COPY_ALLOW_MOVE(ClLogicalBinaryKernel); + /** Function to configure kernel + * + * @param[in] compile_context The compile context to be used. + * @param[in] op Logical binary operation to be executed. + * @param[in] src1 First source tensor info. Data types supported: U8. + * @param[in] src2 Second source tensor info. Data types supported: same as @p src1. + * @param[in] dst Destination tensor info. Data types supported: same as @p src1. + */ + void configure(const ClCompileContext &compile_context, LogicalOperation op, ITensorInfo *src1, ITensorInfo *src2, ITensorInfo *dst); + /** Static function to check if the given configuration is valid for this kernel + * + * @param[in] op Logical binary operation to be executed. + * @param[in] src1 First source tensor info. Data types supported: U8. + * @param[in] src2 Second source tensor info. Data types supported: same as @p src1. + * @param[in] dst Destination tensor info. Data types supported: same as @p src1. + */ + static Status validate(LogicalOperation op, const ITensorInfo *src1, const ITensorInfo *src2, const ITensorInfo *dst); + +private: + // Inherited methods overridden: + std::string name() override; + std::pair<Status, Window> validate_and_configure_window(ITensorInfo &src1, ITensorInfo &src2, ITensorInfo &dst) override; + CLBuildOptions generate_build_options(const ITensorInfo &src1, const ITensorInfo &src2, const ITensorInfo &dst) override; + std::string generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &src1, const ITensorInfo &dst) override; + + LogicalOperation _op{ LogicalOperation::Unknown }; +}; + +/** Addition operation */ +class ClSaturatedArithmeticKernel : public ClElementwiseKernel +{ +public: + ClSaturatedArithmeticKernel() = default; + ARM_COMPUTE_DISALLOW_COPY_ALLOW_MOVE(ClSaturatedArithmeticKernel); + /** Static function to check if given info will lead to a valid configuration of @ref ClSaturatedArithmeticKernel + * + * @param[in] compile_context The compile context to be used. + * @param[in] op Arithmetic operation to be executed. + * @param[in] input1 First tensor input info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/F16/S32/F32. + * @param[in] input2 Second tensor input info. Data types supported: Same as @p input1. + * @param[in] output Output tensor info. Data types supported: Same as @p input1. + * @param[in] policy Policy to use to handle overflow. + * @param[in] act_info (Optional) Activation layer information in case of a fused activation. + */ + void configure(const ClCompileContext &compile_context, ArithmeticOperation op, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, const ConvertPolicy &policy, + const ActivationLayerInfo &act_info = ActivationLayerInfo()); + + /** Static function to check if given info will lead to a valid configuration of @ref ClSaturatedArithmeticKernel + * + * @param[in] op Arithmetic operation to be executed. + * @param[in] input1 First tensor input info info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/F16/S32/F32. + * @param[in] input2 Second tensor input info info. Data types supported: Same as @p input1. + * @param[in] output Output tensor info info. Data types supported: Same as @p input1. + * @param[in] policy Policy to use to handle overflow. + * @param[in] act_info (Optional) Activation layer information in case of a fused activation. + * + * @return a Status + */ + static Status validate(ArithmeticOperation op, const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ConvertPolicy &policy, + const ActivationLayerInfo &act_info = ActivationLayerInfo()); + +protected: + // Inherited methods overridden: + std::string name() override; + std::pair<Status, Window> validate_and_configure_window(ITensorInfo &input1, ITensorInfo &input2, ITensorInfo &output) override; + CLBuildOptions generate_build_options(const ITensorInfo &input1, const ITensorInfo &input2, const ITensorInfo &output) override; + std::string generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &input1, const ITensorInfo &output) override; + +private: + ConvertPolicy _policy{}; + ArithmeticOperation _op{}; +}; + +class ClArithmeticKernel : public ClElementwiseKernel +{ +public: + ClArithmeticKernel() = default; + ARM_COMPUTE_DISALLOW_COPY_ALLOW_MOVE(ClArithmeticKernel); + + /** Static function to check if given info will lead to a valid configuration of @ref ClArithmeticKernel + * + * @param[in] compile_context The compile context to be used. + * @param[in] op Arithmetic operation to be executed. + * @param[in] src1 First source tensor info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/F16/S32/F32. + * @param[in] src2 Second source tensor info. Data types supported: same as @p src1. + * @param[in] dst Destination tensor info. Data types supported: same as @p src1. + * @param[in] act_info (Optional) Activation layer information in case of a fused activation. + */ + void configure(const ClCompileContext &compile_context, ArithmeticOperation op, ITensorInfo *src1, ITensorInfo *src2, ITensorInfo *dst, + const ActivationLayerInfo &act_info = ActivationLayerInfo()); + + /** Static function to check if given info will lead to a valid configuration of @ref ClArithmeticKernel + * + * @param[in] op Arithmetic operation to be executed. + * @param[in] src1 First source tensor info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/F16/S32/F32. + * @param[in] src2 Second source tensor info. Data types supported: same as @p src1. + * @param[in] dst Destination tensor info. Data types supported: same as @p src1. + * @param[in] act_info (Optional) Activation layer information in case of a fused activation. + * + * @return a Status + */ + static Status validate(ArithmeticOperation op, const ITensorInfo *src1, const ITensorInfo *src2, const ITensorInfo *dst, const ActivationLayerInfo &act_info = ActivationLayerInfo()); + +protected: + // Inherited methods overridden: + std::string name() override; + std::pair<Status, Window> validate_and_configure_window(ITensorInfo &src1, ITensorInfo &src2, ITensorInfo &dst) override; + CLBuildOptions generate_build_options(const ITensorInfo &src1, const ITensorInfo &src2, const ITensorInfo &dst) override; + std::string generate_id_for_tuning(const std::string &kernel_name, const ITensorInfo &src1, const ITensorInfo &dst) override; + +private: + ArithmeticOperation _op{}; +}; +} // namespace kernels +} // namespace opencl +} // namespace arm_compute +#endif /* ARM_COMPUTE_CL_ELEMENTWISE_KERNEL_H */ diff --git a/src/runtime/CL/functions/CLElementwiseOperations.cpp b/src/runtime/CL/functions/CLElementwiseOperations.cpp index a72e957fe6..638990e472 100644 --- a/src/runtime/CL/functions/CLElementwiseOperations.cpp +++ b/src/runtime/CL/functions/CLElementwiseOperations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020 Arm Limited. + * Copyright (c) 2018-2021 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -25,7 +25,9 @@ #include "arm_compute/core/CL/ICLTensor.h" #include "arm_compute/runtime/CL/CLScheduler.h" -#include "src/core/CL/kernels/CLElementwiseOperationKernel.h" +#include "src/core/gpu/cl/kernels/ClElementwiseKernel.h" + +#include "src/runtime/gpu/cl/operators/ClAdd.h" #include <utility> @@ -33,34 +35,13 @@ namespace arm_compute { namespace experimental { -CLArithmeticAddition::CLArithmeticAddition() -{ -} - -void CLArithmeticAddition::configure(const CLCompileContext &compile_context, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, ConvertPolicy policy, const ActivationLayerInfo &act_info) -{ - auto k = std::make_unique<CLSaturatedArithmeticOperationKernel>(); - k->configure(compile_context, ArithmeticOperation::ADD, input1, input2, output, policy, act_info); - _kernel = std::move(k); -} - -Status CLArithmeticAddition::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, ConvertPolicy policy, const ActivationLayerInfo &act_info) -{ - return CLSaturatedArithmeticOperationKernel::validate(ArithmeticOperation::ADD, input1, input2, output, policy, act_info); -} - -void CLArithmeticAddition::run(ITensorPack &tensors) -{ - ICLOperator::run(tensors); -} - CLArithmeticSubtraction::CLArithmeticSubtraction() { } void CLArithmeticSubtraction::configure(const CLCompileContext &compile_context, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, ConvertPolicy policy, const ActivationLayerInfo &act_info) { - auto k = std::make_unique<CLSaturatedArithmeticOperationKernel>(); + auto k = std::make_unique<arm_compute::opencl::kernels::ClSaturatedArithmeticKernel>(); k->configure(compile_context, ArithmeticOperation::SUB, input1, input2, output, policy, act_info); _kernel = std::move(k); } @@ -68,7 +49,7 @@ void CLArithmeticSubtraction::configure(const CLCompileContext &compile_context, Status CLArithmeticSubtraction::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, ConvertPolicy policy, const ActivationLayerInfo &act_info) { ARM_COMPUTE_UNUSED(policy); - return CLSaturatedArithmeticOperationKernel::validate(ArithmeticOperation::SUB, input1, input2, output, policy, act_info); + return arm_compute::opencl::kernels::ClSaturatedArithmeticKernel::validate(ArithmeticOperation::SUB, input1, input2, output, policy, act_info); } void CLArithmeticSubtraction::run(ITensorPack &tensors) @@ -82,14 +63,14 @@ CLArithmeticDivision::CLArithmeticDivision() void CLArithmeticDivision::configure(const CLCompileContext &compile_context, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, const ActivationLayerInfo &act_info) { - auto k = std::make_unique<CLArithmeticOperationKernel>(); + auto k = std::make_unique<arm_compute::opencl::kernels::ClArithmeticKernel>(); k->configure(compile_context, ArithmeticOperation::DIV, input1, input2, output, act_info); _kernel = std::move(k); } Status CLArithmeticDivision::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info) { - return CLArithmeticOperationKernel::validate(ArithmeticOperation::DIV, input1, input2, output, act_info); + return arm_compute::opencl::kernels::ClArithmeticKernel::validate(ArithmeticOperation::DIV, input1, input2, output, act_info); } void CLArithmeticDivision::run(ITensorPack &tensors) @@ -103,14 +84,14 @@ CLElementwiseMax::CLElementwiseMax() void CLElementwiseMax::configure(const CLCompileContext &compile_context, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, const ActivationLayerInfo &act_info) { - auto k = std::make_unique<CLArithmeticOperationKernel>(); + auto k = std::make_unique<arm_compute::opencl::kernels::ClArithmeticKernel>(); k->configure(compile_context, ArithmeticOperation::MAX, input1, input2, output, act_info); _kernel = std::move(k); } Status CLElementwiseMax::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info) { - return CLArithmeticOperationKernel::validate(ArithmeticOperation::MAX, input1, input2, output, act_info); + return arm_compute::opencl::kernels::ClArithmeticKernel::validate(ArithmeticOperation::MAX, input1, input2, output, act_info); } void CLElementwiseMax::run(ITensorPack &tensors) @@ -124,14 +105,14 @@ CLElementwiseMin::CLElementwiseMin() void CLElementwiseMin::configure(const CLCompileContext &compile_context, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, const ActivationLayerInfo &act_info) { - auto k = std::make_unique<CLArithmeticOperationKernel>(); + auto k = std::make_unique<arm_compute::opencl::kernels::ClArithmeticKernel>(); k->configure(compile_context, ArithmeticOperation::MIN, input1, input2, output, act_info); _kernel = std::move(k); } Status CLElementwiseMin::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info) { - return CLArithmeticOperationKernel::validate(ArithmeticOperation::MIN, input1, input2, output, act_info); + return arm_compute::opencl::kernels::ClArithmeticKernel::validate(ArithmeticOperation::MIN, input1, input2, output, act_info); } void CLElementwiseMin::run(ITensorPack &tensors) @@ -145,14 +126,14 @@ CLElementwiseSquaredDiff::CLElementwiseSquaredDiff() void CLElementwiseSquaredDiff::configure(const CLCompileContext &compile_context, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, const ActivationLayerInfo &act_info) { - auto k = std::make_unique<CLArithmeticOperationKernel>(); + auto k = std::make_unique<arm_compute::opencl::kernels::ClArithmeticKernel>(); k->configure(compile_context, ArithmeticOperation::SQUARED_DIFF, input1, input2, output, act_info); _kernel = std::move(k); } Status CLElementwiseSquaredDiff::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info) { - return CLArithmeticOperationKernel::validate(ArithmeticOperation::SQUARED_DIFF, input1, input2, output, act_info); + return arm_compute::opencl::kernels::ClArithmeticKernel::validate(ArithmeticOperation::SQUARED_DIFF, input1, input2, output, act_info); } void CLElementwiseSquaredDiff::run(ITensorPack &tensors) @@ -166,14 +147,14 @@ CLElementwisePower::CLElementwisePower() void CLElementwisePower::configure(const CLCompileContext &compile_context, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output, const ActivationLayerInfo &act_info) { - auto k = std::make_unique<CLArithmeticOperationKernel>(); + auto k = std::make_unique<arm_compute::opencl::kernels::ClArithmeticKernel>(); k->configure(compile_context, ArithmeticOperation::POWER, input1, input2, output, act_info); _kernel = std::move(k); } Status CLElementwisePower::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, const ActivationLayerInfo &act_info) { - return CLArithmeticOperationKernel::validate(ArithmeticOperation::POWER, input1, input2, output, act_info); + return arm_compute::opencl::kernels::ClArithmeticKernel::validate(ArithmeticOperation::POWER, input1, input2, output, act_info); } void CLElementwisePower::run(ITensorPack &tensors) @@ -181,13 +162,12 @@ void CLElementwisePower::run(ITensorPack &tensors) ICLOperator::run(tensors); } } // namespace experimental - struct CLArithmeticAddition::Impl { - const ICLTensor *src_0{ nullptr }; - const ICLTensor *src_1{ nullptr }; - ICLTensor *dst{ nullptr }; - std::unique_ptr<experimental::CLArithmeticAddition> op{ nullptr }; + const ICLTensor *src_0{ nullptr }; + const ICLTensor *src_1{ nullptr }; + ICLTensor *dst{ nullptr }; + std::unique_ptr<opencl::ClAdd> op{ nullptr }; }; CLArithmeticAddition::CLArithmeticAddition() @@ -209,13 +189,13 @@ void CLArithmeticAddition::configure(const CLCompileContext &compile_context, co _impl->src_0 = input1; _impl->src_1 = input2; _impl->dst = output; - _impl->op = std::make_unique<experimental::CLArithmeticAddition>(); + _impl->op = std::make_unique<opencl::ClAdd>(); _impl->op->configure(compile_context, input1->info(), input2->info(), output->info(), policy, act_info); } Status CLArithmeticAddition::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output, ConvertPolicy policy, const ActivationLayerInfo &act_info) { - return experimental::CLArithmeticAddition::validate(input1, input2, output, policy, act_info); + return opencl::ClAdd::validate(input1, input2, output, policy, act_info); } void CLArithmeticAddition::run() diff --git a/src/runtime/CL/functions/CLLogicalAnd.cpp b/src/runtime/CL/functions/CLLogicalAnd.cpp index f1c53651c7..98c98abed5 100644 --- a/src/runtime/CL/functions/CLLogicalAnd.cpp +++ b/src/runtime/CL/functions/CLLogicalAnd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Arm Limited. + * Copyright (c) 2020-2021 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -23,7 +23,7 @@ */ #include "arm_compute/runtime/CL/functions/CLLogicalAnd.h" #include "arm_compute/core/CL/ICLTensor.h" -#include "src/core/CL/kernels/CLElementwiseOperationKernel.h" +#include "src/core/gpu/cl/kernels/ClElementwiseKernel.h" #include <utility> @@ -33,14 +33,14 @@ namespace experimental { void CLLogicalAnd::configure(const CLCompileContext &compile_context, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output) { - auto k = std::make_unique<CLLogicalBinaryKernel>(); - k->configure(compile_context, kernels::LogicalOperation::And, input1, input2, output); + auto k = std::make_unique<arm_compute::opencl::kernels::ClLogicalBinaryKernel>(); + k->configure(compile_context, LogicalOperation::And, input1, input2, output); _kernel = std::move(k); } Status CLLogicalAnd::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output) { - return CLLogicalBinaryKernel::validate(kernels::LogicalOperation::And, input1, input2, output); + return arm_compute::opencl::kernels::ClLogicalBinaryKernel::validate(LogicalOperation::And, input1, input2, output); } void CLLogicalAnd::run(ITensorPack &tensors) diff --git a/src/runtime/CL/functions/CLLogicalOr.cpp b/src/runtime/CL/functions/CLLogicalOr.cpp index 8c6087ed7d..897963ab50 100644 --- a/src/runtime/CL/functions/CLLogicalOr.cpp +++ b/src/runtime/CL/functions/CLLogicalOr.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Arm Limited. + * Copyright (c) 2020-2021 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -23,7 +23,7 @@ */ #include "arm_compute/runtime/CL/functions/CLLogicalOr.h" #include "arm_compute/core/CL/ICLTensor.h" -#include "src/core/CL/kernels/CLElementwiseOperationKernel.h" +#include "src/core/gpu/cl/kernels/ClElementwiseKernel.h" #include <utility> @@ -33,14 +33,14 @@ namespace experimental { void CLLogicalOr::configure(const CLCompileContext &compile_context, ITensorInfo *input1, ITensorInfo *input2, ITensorInfo *output) { - auto k = std::make_unique<CLLogicalBinaryKernel>(); - k->configure(compile_context, kernels::LogicalOperation::Or, input1, input2, output); + auto k = std::make_unique<arm_compute::opencl::kernels::ClLogicalBinaryKernel>(); + k->configure(compile_context, LogicalOperation::Or, input1, input2, output); _kernel = std::move(k); } Status CLLogicalOr::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output) { - return CLLogicalBinaryKernel::validate(kernels::LogicalOperation::Or, input1, input2, output); + return arm_compute::opencl::kernels::ClLogicalBinaryKernel::validate(LogicalOperation::Or, input1, input2, output); } void CLLogicalOr::run(ITensorPack &tensors) diff --git a/src/runtime/CL/functions/CLPReluLayer.cpp b/src/runtime/CL/functions/CLPReluLayer.cpp index 876b5de0f7..74286d46ca 100644 --- a/src/runtime/CL/functions/CLPReluLayer.cpp +++ b/src/runtime/CL/functions/CLPReluLayer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 Arm Limited. + * Copyright (c) 2019-2021 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "src/core/CL/kernels/CLElementwiseOperationKernel.h" +#include "src/core/gpu/cl/kernels/ClElementwiseKernel.h" #include "arm_compute/core/CL/ICLTensor.h" #include "arm_compute/runtime/CL/CLScheduler.h" @@ -37,14 +37,14 @@ CLPReluLayer::CLPReluLayer() void CLPReluLayer::configure(const CLCompileContext &compile_context, ITensorInfo *input, ITensorInfo *alpha, ITensorInfo *output) { - auto k = std::make_unique<CLArithmeticOperationKernel>(); + auto k = std::make_unique<arm_compute::opencl::kernels::ClArithmeticKernel>(); k->configure(compile_context, ArithmeticOperation::PRELU, input, alpha, output); _kernel = std::move(k); } Status CLPReluLayer::validate(const ITensorInfo *input, const ITensorInfo *alpha, const ITensorInfo *output) { - return CLArithmeticOperationKernel::validate(ArithmeticOperation::PRELU, input, alpha, output); + return arm_compute::opencl::kernels::ClArithmeticKernel::validate(ArithmeticOperation::PRELU, input, alpha, output); } void CLPReluLayer::run(ITensorPack &tensors) diff --git a/src/runtime/NEON/functions/NELogical.cpp b/src/runtime/NEON/functions/NELogical.cpp index 190998b042..674ba40fcd 100644 --- a/src/runtime/NEON/functions/NELogical.cpp +++ b/src/runtime/NEON/functions/NELogical.cpp @@ -50,7 +50,7 @@ void NELogicalAnd::configure(const ITensor *input1, const ITensor *input2, ITens ARM_COMPUTE_ERROR_ON_NULLPTR(input1, input2, output); _impl->kernel = std::make_unique<kernels::NELogicalKernel>(); - _impl->kernel->configure(input1->info(), input2->info(), output->info(), kernels::LogicalOperation::And); + _impl->kernel->configure(input1->info(), input2->info(), output->info(), LogicalOperation::And); _impl->pack = ITensorPack(); _impl->pack.add_tensor(TensorType::ACL_SRC_0, input1); @@ -60,7 +60,7 @@ void NELogicalAnd::configure(const ITensor *input1, const ITensor *input2, ITens Status NELogicalAnd::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output) { - return kernels::NELogicalKernel::validate(input1, input2, output, kernels::LogicalOperation::And); + return kernels::NELogicalKernel::validate(input1, input2, output, LogicalOperation::And); } void NELogicalAnd::run() @@ -83,7 +83,7 @@ void NELogicalOr::configure(const ITensor *input1, const ITensor *input2, ITenso ARM_COMPUTE_ERROR_ON_NULLPTR(input1, input2, output); _impl->kernel = std::make_unique<kernels::NELogicalKernel>(); - _impl->kernel->configure(input1->info(), input2->info(), output->info(), kernels::LogicalOperation::Or); + _impl->kernel->configure(input1->info(), input2->info(), output->info(), LogicalOperation::Or); _impl->pack = ITensorPack(); _impl->pack.add_tensor(TensorType::ACL_SRC_0, input1); @@ -93,7 +93,7 @@ void NELogicalOr::configure(const ITensor *input1, const ITensor *input2, ITenso Status NELogicalOr::validate(const ITensorInfo *input1, const ITensorInfo *input2, const ITensorInfo *output) { - return kernels::NELogicalKernel::validate(input1, input2, output, kernels::LogicalOperation::Or); + return kernels::NELogicalKernel::validate(input1, input2, output, LogicalOperation::Or); } void NELogicalOr::run() @@ -116,7 +116,7 @@ void NELogicalNot::configure(const ITensor *input, ITensor *output) ARM_COMPUTE_ERROR_ON_NULLPTR(input, output); _impl->kernel = std::make_unique<kernels::NELogicalKernel>(); - _impl->kernel->configure(input->info(), nullptr, output->info(), kernels::LogicalOperation::Not); + _impl->kernel->configure(input->info(), nullptr, output->info(), LogicalOperation::Not); _impl->pack = ITensorPack(); _impl->pack.add_tensor(TensorType::ACL_SRC_0, input); @@ -125,7 +125,7 @@ void NELogicalNot::configure(const ITensor *input, ITensor *output) Status NELogicalNot::validate(const ITensorInfo *input, const ITensorInfo *output) { - return kernels::NELogicalKernel::validate(input, nullptr, output, kernels::LogicalOperation::Not); + return kernels::NELogicalKernel::validate(input, nullptr, output, LogicalOperation::Not); } void NELogicalNot::run() diff --git a/src/runtime/gpu/cl/operators/ClAdd.cpp b/src/runtime/gpu/cl/operators/ClAdd.cpp new file mode 100644 index 0000000000..01f550f819 --- /dev/null +++ b/src/runtime/gpu/cl/operators/ClAdd.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Arm Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "src/runtime/gpu/cl/operators/ClAdd.h" + +#include "src/core/gpu/cl/ClCompileContext.h" +#include "src/core/gpu/cl/kernels/ClElementwiseKernel.h" + +namespace arm_compute +{ +namespace opencl +{ +void ClAdd::configure(const ClCompileContext &compile_context, ITensorInfo *src1, ITensorInfo *src2, ITensorInfo *dst, + ConvertPolicy policy, const ActivationLayerInfo &act_info) +{ + auto k = std::make_unique<kernels::ClSaturatedArithmeticKernel>(); + k->configure(compile_context, ArithmeticOperation::ADD, src1, src2, dst, policy, act_info); + _kernel = std::move(k); +} + +Status ClAdd::validate(const ITensorInfo *src1, const ITensorInfo *src2, const ITensorInfo *dst, + ConvertPolicy policy, const ActivationLayerInfo &act_info) +{ + return kernels::ClSaturatedArithmeticKernel::validate(ArithmeticOperation::ADD, src1, src2, dst, policy, act_info); +} +} // namespace opencl +} // namespace arm_compute diff --git a/src/runtime/gpu/cl/operators/ClAdd.h b/src/runtime/gpu/cl/operators/ClAdd.h new file mode 100644 index 0000000000..2854c16180 --- /dev/null +++ b/src/runtime/gpu/cl/operators/ClAdd.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2021 Arm Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef ARM_COMPUTE_CL_ADD_H +#define ARM_COMPUTE_CL_ADD_H + +#include "src/core/gpu/cl/ClCompileContext.h" +#include "src/runtime/gpu/cl/IClOperator.h" + +namespace arm_compute +{ +namespace opencl +{ +/** Basic function to run arithmetic addition + * + * @note The tensor data type for the inputs must be U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/S32/F16/F32. + * @note The function performs an arithmetic addition between two tensors. + */ +class ClAdd : public IClOperator +{ +public: + /** Default Constructor */ + ClAdd() = default; + /** Configure function for a given list of arguments. + * + * Valid configurations (src1,src2) -> dst : + * + * - (U8,U8) -> U8 + * - (U8,U8) -> S16 + * - (S16,U8) -> S16 + * - (U8,S16) -> S16 + * - (S16,S16) -> S16 + * - (S32,S32) -> S32 + * - (F16,F16) -> F16 + * - (F32,F32) -> F32 + * - (QASYMM8,QASYMM8) -> QASYMM8 + * - (QASYMM8_SIGNED,QASYMM8_SIGNED) -> QASYMM8_SIGNED + * - (QSYMM16,QSYMM16) -> QSYMM16 + * + * @param[in] compile_context The compile context to be used. + * @param[in, out] src1 First source tensor. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/S32/F16/F32. + * The source tensor is [in, out] because its TensorInfo might be modified inside the kernel in case of broadcasting of dimension 0. + * @param[in, out] src2 Second source tensor. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/S32/F16/F32. + * The source tensor is [in, out] because its TensorInfo might be modified inside the kernel in case of broadcasting of dimension 0. + * @param[out] dst Destination tensor. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/S32/F16/F32. + * @param[in] policy Policy to use to handle overflow. + * @param[in] act_info (Optional) Activation layer information in case of a fused activation. + */ + void configure(const ClCompileContext &compile_context, ITensorInfo *src1, ITensorInfo *src2, ITensorInfo *dst, ConvertPolicy policy, + const ActivationLayerInfo &act_info = ActivationLayerInfo()); + /** Static function to check if given info will lead to a valid configuration of @ref ClAdd + * + * Valid configurations (src1,src2) -> dst : + * + * - (U8,U8) -> U8 + * - (U8,U8) -> S16 + * - (S16,U8) -> S16 + * - (U8,S16) -> S16 + * - (S16,S16) -> S16 + * - (S32,S32) -> S32 + * - (F16,F16) -> F16 + * - (F32,F32) -> F32 + * - (QASYMM8,QASYMM8) -> QASYMM8 + * - (QASYMM8_SIGNED,QASYMM8_SIGNED) -> QASYMM8_SIGNED + * - (QSYMM16,QSYMM16) -> QSYMM16 + * + * @param[in] src1 First source tensor info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/S32/F16/F32. + * @param[in] src2 Second source tensor info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/S32/F16/F32. + * @param[in] dst Destination tensor info. Data types supported: U8/QASYMM8/QASYMM8_SIGNED/S16/QSYMM16/S32/F16/F32. + * @param[in] policy Policy to use to handle overflow. + * @param[in] act_info (Optional) Activation layer information in case of a fused activation. + * + * @return a status + */ + static Status validate(const ITensorInfo *src1, const ITensorInfo *src2, const ITensorInfo *dst, ConvertPolicy policy, + const ActivationLayerInfo &act_info = ActivationLayerInfo()); +}; +} // namespace opencl +} // namespace arm_compute +#endif /* ARM_COMPUTE_CL_ADD_H */ |