aboutsummaryrefslogtreecommitdiff
path: root/src/core/CL/kernels/CLActivationLayerKernel.cpp
diff options
context:
space:
mode:
authorGeorgios Pinitas <georgios.pinitas@arm.com>2019-06-04 17:31:46 +0100
committerGeorgios Pinitas <georgios.pinitas@arm.com>2019-06-05 14:14:48 +0000
commit4b3fba1850fdf84ba3f9a0c98acf3de672330b34 (patch)
tree1b65639ec7387c474903583ff0927918c8c7d837 /src/core/CL/kernels/CLActivationLayerKernel.cpp
parentc625acd2a60a4fe34633c5cecef85c230933f772 (diff)
downloadComputeLibrary-4b3fba1850fdf84ba3f9a0c98acf3de672330b34.tar.gz
COMPMID-2372: Add support for QASYMM8 for Tanh
-Perform calculations in the floating point domain -Extends checks for Logistic as scale should be 1/256 and offset 0 Change-Id: I90ef4a042f053976936f5d28f8e09b54eec196a2 Signed-off-by: Georgios Pinitas <georgios.pinitas@arm.com> Reviewed-on: https://review.mlplatform.org/c/1287 Tested-by: Arm Jenkins <bsgcomp@arm.com> Reviewed-by: Michalis Spyrou <michalis.spyrou@arm.com> Comments-Addressed: Arm Jenkins <bsgcomp@arm.com>
Diffstat (limited to 'src/core/CL/kernels/CLActivationLayerKernel.cpp')
-rw-r--r--src/core/CL/kernels/CLActivationLayerKernel.cpp61
1 files changed, 40 insertions, 21 deletions
diff --git a/src/core/CL/kernels/CLActivationLayerKernel.cpp b/src/core/CL/kernels/CLActivationLayerKernel.cpp
index 65e6561b0a..34d1298d61 100644
--- a/src/core/CL/kernels/CLActivationLayerKernel.cpp
+++ b/src/core/CL/kernels/CLActivationLayerKernel.cpp
@@ -30,14 +30,14 @@
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/IAccessWindow.h"
#include "arm_compute/core/TensorInfo.h"
+#include "arm_compute/core/Types.h"
#include "arm_compute/core/Utils.h"
#include "arm_compute/core/Window.h"
-
-#include "arm_compute/core/CL/CLHelpers.h"
-#include "arm_compute/core/Types.h"
+#include "arm_compute/core/utils/helpers/float_ops.h"
#include "support/ToolchainSupport.h"
#include <cmath>
+#include <set>
using namespace arm_compute;
@@ -47,11 +47,23 @@ Status validate_arguments(const ITensorInfo *input, const ITensorInfo *output, c
{
ARM_COMPUTE_RETURN_ERROR_ON_F16_UNSUPPORTED(input);
ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::U8, DataType::QASYMM8, DataType::F16, DataType::F32);
- ARM_COMPUTE_RETURN_ERROR_ON_MSG((input->data_type() == DataType::QASYMM8) && (act_info.activation() != ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU)
- && (act_info.activation() != ActivationLayerInfo::ActivationFunction::BOUNDED_RELU)
- && (act_info.activation() != ActivationLayerInfo::ActivationFunction::RELU)
- && (act_info.activation() != ActivationLayerInfo::ActivationFunction::LOGISTIC),
- "For QASYMM8 only logistic, relu, lower bounded relu and lower-upper bounded relu are supported");
+
+ static std::set<ActivationLayerInfo::ActivationFunction> qs8_supported_activations =
+ {
+ ActivationLayerInfo::ActivationFunction::RELU,
+ ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU,
+ ActivationLayerInfo::ActivationFunction::BOUNDED_RELU,
+ ActivationLayerInfo::ActivationFunction::LOGISTIC,
+ ActivationLayerInfo::ActivationFunction::TANH
+ };
+ const DataType data_type = input->data_type();
+ const QuantizationInfo &oq_info = (output != nullptr) ? output->quantization_info() : input->quantization_info();
+ const ActivationLayerInfo::ActivationFunction f_act = act_info.activation();
+
+ ARM_COMPUTE_RETURN_ERROR_ON_MSG(is_data_type_quantized_asymmetric(data_type) && (qs8_supported_activations.count(f_act) == 0),
+ "For QASYMM8 only tanh, logistic, relu and lower/upper bounded relu are supported");
+ ARM_COMPUTE_RETURN_ERROR_ON(is_data_type_quantized_asymmetric(data_type) && (f_act == ActivationLayerInfo::ActivationFunction::TANH) && (oq_info != QuantizationInfo(1.f / 128.f, 128)));
+ ARM_COMPUTE_RETURN_ERROR_ON(is_data_type_quantized_asymmetric(data_type) && (f_act == ActivationLayerInfo::ActivationFunction::LOGISTIC) && (oq_info != QuantizationInfo(1.f / 256.f, 0)));
// Checks performed when output is configured
if((output != nullptr) && (output->total_size() != 0))
@@ -122,7 +134,10 @@ void CLActivationLayerKernel::configure(ICLTensor *input, ICLTensor *output, Act
int a_const_int = 0;
int b_const_int = 0;
- const bool is_quantized_asymmetric = is_data_type_quantized_asymmetric(dt);
+ const ActivationLayerInfo::ActivationFunction f_act = act_info.activation();
+ const bool is_quantized_asymmetric = is_data_type_quantized_asymmetric(dt);
+ const bool perform_activation_in_float = (f_act == ActivationLayerInfo::ActivationFunction::LOGISTIC) || (f_act == ActivationLayerInfo::ActivationFunction::TANH);
+
// Create quantized version of constants a, b if needed
if(is_quantized_asymmetric)
{
@@ -131,18 +146,29 @@ void CLActivationLayerKernel::configure(ICLTensor *input, ICLTensor *output, Act
b_const_int = quantize_qasymm8(b_const, iq_info);
}
- const bool is_logistic_activation_quantized = is_quantized_asymmetric && act_info.activation() == ActivationLayerInfo::ActivationFunction::LOGISTIC;
// Set build options
CLBuildOptions build_opts;
- build_opts.add_option_if(!is_logistic_activation_quantized, "-DACT=" + lower_string(string_from_activation_func(act_info.activation())));
+ build_opts.add_option_if(perform_activation_in_float, "-DFLOAT_DOMAIN");
+ build_opts.add_option_if(_run_in_place, "-DIN_PLACE");
+ build_opts.add_option(("-DACT=" + lower_string(string_from_activation_func(f_act))));
build_opts.add_option(("-DDATA_TYPE=" + get_cl_type_from_data_type(dt)));
build_opts.add_option(("-DVEC_SIZE=" + support::cpp11::to_string(num_elems_processed_per_iteration)));
- if(is_quantized_asymmetric)
+ // Set A, B constants in build options
+ if(is_quantized_asymmetric && !perform_activation_in_float)
{
build_opts.add_option(("-DA_VAL=" + support::cpp11::to_string(a_const_int)));
build_opts.add_option(("-DB_VAL=" + support::cpp11::to_string(b_const_int)));
+ }
+ else
+ {
+ build_opts.add_option(("-DA_VAL=" + float_to_string_with_full_precision(a_const)));
+ build_opts.add_option(("-DB_VAL=" + float_to_string_with_full_precision(b_const)));
+ }
+ // Set quantization info build options
+ if(is_quantized_asymmetric)
+ {
const UniformQuantizationInfo iq_info = input->info()->quantization_info().uniform();
// Quantized value of 0 corresponds to the offset o1
@@ -151,7 +177,7 @@ void CLActivationLayerKernel::configure(ICLTensor *input, ICLTensor *output, Act
build_opts.add_option(("-DO1_VAL=" + support::cpp11::to_string(iq_info.offset)));
// Set scale and offset of the input and output if they have different quantization info
- if(is_quantized_asymmetric && output != nullptr)
+ if(output != nullptr)
{
const UniformQuantizationInfo oq_info = output->info()->quantization_info().uniform();
@@ -162,19 +188,12 @@ void CLActivationLayerKernel::configure(ICLTensor *input, ICLTensor *output, Act
}
}
}
- else
- {
- build_opts.add_option(("-DA_VAL=" + float_to_string_with_full_precision(a_const)));
- build_opts.add_option(("-DB_VAL=" + float_to_string_with_full_precision(b_const)));
- }
-
- build_opts.add_option_if(_run_in_place, "-DIN_PLACE");
// Create kernel
std::string kernel_name = std::string("activation_layer");
if(is_quantized_asymmetric)
{
- kernel_name += is_logistic_activation_quantized ? std::string("_logistic_qa8") : std::string("_qa8");
+ kernel_name += perform_activation_in_float ? std::string("_qa8_f32") : std::string("_qa8");
}
_kernel = static_cast<cl::Kernel>(CLKernelLibrary::get().create_kernel(kernel_name, build_opts.options()));