aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSang-Hoon Park <sang-hoon.park@arm.com>2020-01-08 16:02:47 +0000
committerMichele Di Giorgio <michele.digiorgio@arm.com>2020-01-14 14:26:14 +0000
commit4715cf9da26c4e914b9528f736e77d6773285169 (patch)
tree5143cfe1355e14dbc6d2314898c7a60601354277
parent8ef5706e520c25b451f1923f34ea8b7e96aa0742 (diff)
downloadComputeLibrary-4715cf9da26c4e914b9528f736e77d6773285169.tar.gz
COMPMID-2760: add support for QASYMM8_SIGNED to CLGEMMConvolutionLayer
Signed-off-by: Sang-Hoon Park <sang-hoon.park@arm.com> Change-Id: I55ab81d0f96c78af0396652cacf6640fc98ef3c2 Reviewed-on: https://review.mlplatform.org/c/2584 Reviewed-by: Michele Di Giorgio <michele.digiorgio@arm.com> Comments-Addressed: Arm Jenkins <bsgcomp@arm.com> Tested-by: Arm Jenkins <bsgcomp@arm.com>
-rw-r--r--arm_compute/core/Utils.h10
-rw-r--r--src/core/Utils.cpp15
-rw-r--r--src/runtime/CL/functions/CLGEMMConvolutionLayer.cpp14
-rw-r--r--src/runtime/NEON/functions/NEGEMMConvolutionLayer.cpp16
-rw-r--r--tests/validation/CL/ConvolutionLayer.cpp17
5 files changed, 47 insertions, 25 deletions
diff --git a/arm_compute/core/Utils.h b/arm_compute/core/Utils.h
index 3a8f6b319f..a2c18bb205 100644
--- a/arm_compute/core/Utils.h
+++ b/arm_compute/core/Utils.h
@@ -977,6 +977,16 @@ QuantizationInfo get_softmax_output_quantization_info(DataType input_type, bool
*/
float calculate_resize_ratio(size_t input_size, size_t output_size, bool align_corners = false);
+/** Returns a pair of minimum and maximum values for a quantized activation
+ *
+ * @param[in] act_info The information for activation
+ * @param[in] data_type The used data type
+ * @param[in] oq_info The output quantization information
+ *
+ * @return The pair with minimum and maximum values
+ */
+std::pair<int32_t, int32_t> get_quantized_activation_min_max(ActivationLayerInfo act_info, DataType data_type, UniformQuantizationInfo oq_info);
+
/** Convert a tensor format into a string.
*
* @param[in] format @ref Format to be translated to string.
diff --git a/src/core/Utils.cpp b/src/core/Utils.cpp
index 30e5b66540..f930804ce3 100644
--- a/src/core/Utils.cpp
+++ b/src/core/Utils.cpp
@@ -471,6 +471,21 @@ float arm_compute::calculate_resize_ratio(size_t input_size, size_t output_size,
return static_cast<float>(in) / static_cast<float>(out);
}
+std::pair<int32_t, int32_t> arm_compute::get_quantized_activation_min_max(ActivationLayerInfo act_info, DataType data_type, UniformQuantizationInfo oq_info)
+{
+ const bool is_qasymm8_signed = is_data_type_quantized_asymmetric_signed(data_type);
+ const auto a = act_info.a();
+ const auto b = act_info.b();
+ const int a_int = is_qasymm8_signed ? quantize_qasymm8_signed(a, oq_info) : quantize_qasymm8(a, oq_info);
+ const int b_int = is_qasymm8_signed ? quantize_qasymm8_signed(b, oq_info) : quantize_qasymm8(b, oq_info);
+ const auto type_max_value = std::get<1>(get_min_max(data_type)).get<int32_t>();
+
+ const int32_t min_activation = act_info.activation() != ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU ? oq_info.offset : b_int;
+ const int32_t max_activation = act_info.activation() == ActivationLayerInfo::ActivationFunction::RELU ? type_max_value : a_int;
+
+ return std::make_pair(min_activation, max_activation);
+}
+
#ifdef ARM_COMPUTE_ASSERTS_ENABLED
void arm_compute::print_consecutive_elements(std::ostream &s, DataType dt, const uint8_t *ptr, unsigned int n, int stream_width, const std::string &element_delim)
{
diff --git a/src/runtime/CL/functions/CLGEMMConvolutionLayer.cpp b/src/runtime/CL/functions/CLGEMMConvolutionLayer.cpp
index dbb68619db..682812b1c8 100644
--- a/src/runtime/CL/functions/CLGEMMConvolutionLayer.cpp
+++ b/src/runtime/CL/functions/CLGEMMConvolutionLayer.cpp
@@ -345,11 +345,7 @@ void CLGEMMConvolutionLayer::configure(const ICLTensor *input, const ICLTensor *
{
if(supported_acts.count(act_info.activation()) != 0)
{
- const int a_const_int = quantize_qasymm8(act_info.a(), output_quant_info);
- const int b_const_int = quantize_qasymm8(act_info.b(), output_quant_info);
-
- min_activation = act_info.activation() != ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU ? output_quant_info.offset : b_const_int;
- max_activation = act_info.activation() == ActivationLayerInfo::ActivationFunction::RELU ? 255 : a_const_int;
+ std::tie(min_activation, max_activation) = get_quantized_activation_min_max(act_info, data_type, output_quant_info);
}
else
{
@@ -402,7 +398,7 @@ Status CLGEMMConvolutionLayer::validate(const ITensorInfo *input, const ITensorI
{
ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, weights, output);
ARM_COMPUTE_RETURN_ERROR_ON_MSG(weights_info.are_reshaped(), "Weights already reshaped are not supported!");
- ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QASYMM8, DataType::F16, DataType::F32);
+ ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED, DataType::F16, DataType::F32);
const bool is_quantized_per_channel = is_data_type_quantized_per_channel(weights->data_type());
if(is_quantized_per_channel)
@@ -559,11 +555,7 @@ Status CLGEMMConvolutionLayer::validate(const ITensorInfo *input, const ITensorI
{
if(supported_acts.count(act_info.activation()) != 0)
{
- const int a_const_int = quantize_qasymm8(act_info.a(), output_quant_info);
- const int b_const_int = quantize_qasymm8(act_info.b(), output_quant_info);
-
- min_activation = act_info.activation() != ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU ? output_quant_info.offset : b_const_int;
- max_activation = act_info.activation() == ActivationLayerInfo::ActivationFunction::RELU ? 255 : a_const_int;
+ std::tie(min_activation, max_activation) = get_quantized_activation_min_max(act_info, data_type, output_quant_info);
}
else
{
diff --git a/src/runtime/NEON/functions/NEGEMMConvolutionLayer.cpp b/src/runtime/NEON/functions/NEGEMMConvolutionLayer.cpp
index 920917a58b..5701d60208 100644
--- a/src/runtime/NEON/functions/NEGEMMConvolutionLayer.cpp
+++ b/src/runtime/NEON/functions/NEGEMMConvolutionLayer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -140,12 +140,7 @@ void NEGEMMConvolutionLayer::configure_mm(const ITensor *input, const ITensor *w
if(supported_acts.count(act_info.activation()) != 0)
{
- const bool is_quantized_signed = is_data_type_quantized_asymmetric_signed(data_type);
- const int a_const_int = is_quantized_signed ? quantize_qasymm8_signed(act_info.a(), uoqinfo) : quantize_qasymm8(act_info.a(), uoqinfo);
- const int b_const_int = is_quantized_signed ? quantize_qasymm8_signed(act_info.b(), uoqinfo) : quantize_qasymm8(act_info.b(), uoqinfo);
-
- min_activation = act_info.activation() != ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU ? uoqinfo.offset : b_const_int;
- max_activation = act_info.activation() == ActivationLayerInfo::ActivationFunction::RELU ? max_activation : a_const_int;
+ std::tie(min_activation, max_activation) = get_quantized_activation_min_max(act_info, data_type, uoqinfo);
}
GEMMLowpOutputStageInfo output_info;
@@ -203,12 +198,7 @@ Status NEGEMMConvolutionLayer::validate_mm(const ITensorInfo *input, const ITens
};
if(is_activation_enabled && supported_acts.count(act_info.activation()) != 0)
{
- const bool is_quantized_signed = is_data_type_quantized_asymmetric_signed(data_type);
- const int a_const_int = is_quantized_signed ? quantize_qasymm8_signed(act_info.a(), uoqinfo) : quantize_qasymm8(act_info.a(), uoqinfo);
- const int b_const_int = is_quantized_signed ? quantize_qasymm8_signed(act_info.b(), uoqinfo) : quantize_qasymm8(act_info.b(), uoqinfo);
-
- min_activation = act_info.activation() != ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU ? uoqinfo.offset : b_const_int;
- max_activation = act_info.activation() == ActivationLayerInfo::ActivationFunction::RELU ? max_activation : a_const_int;
+ std::tie(min_activation, max_activation) = get_quantized_activation_min_max(act_info, data_type, uoqinfo);
}
GEMMLowpOutputStageInfo output_info;
diff --git a/tests/validation/CL/ConvolutionLayer.cpp b/tests/validation/CL/ConvolutionLayer.cpp
index 5ee5d849c3..130af572ff 100644
--- a/tests/validation/CL/ConvolutionLayer.cpp
+++ b/tests/validation/CL/ConvolutionLayer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 ARM Limited.
+ * Copyright (c) 2017-2020 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -57,6 +57,7 @@ const auto CNNDataTypes = framework::dataset::make("DataType",
DataType::F16,
DataType::F32,
DataType::QASYMM8,
+ DataType::QASYMM8_SIGNED,
});
/** Grouped CNN data types */
@@ -319,6 +320,20 @@ FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMConvolutionLayerQuantizedFixture<uint8_t>
validate(CLAccessor(_target), _reference, tolerance_qasymm8);
}
TEST_SUITE_END() // QASYMM8
+TEST_SUITE(QASYMM8_SIGNED)
+
+FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMConvolutionLayerQuantizedFixture<int8_t>, framework::DatasetMode::PRECOMMIT,
+ combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerReducedDataset(),
+ framework::dataset::make("ReshapeWeights", { true })),
+ framework::dataset::make("DataType", DataType::QASYMM8_SIGNED)),
+ framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
+ QuantizationData),
+ QuantizedActivationFunctionsSmallDataset))
+{
+ // Validate output
+ validate(CLAccessor(_target), _reference, tolerance_qasymm8);
+}
+TEST_SUITE_END() // QASYMM8_SIGNED
TEST_SUITE(QSYMM8_PER_CHANNEL)
FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMConvolutionLayerQuantizedPerChannelFixture<uint8_t>, framework::DatasetMode::PRECOMMIT,