aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorGeorgios Pinitas <georgios.pinitas@arm.com>2019-05-21 13:32:43 +0100
committerGeorgios Pinitas <georgios.pinitas@arm.com>2019-06-03 14:51:29 +0000
commit4c5469b192665c94118a8a558787cb9cec2d0765 (patch)
tree168aa969de8243bdbb1f25247dd9f54d037ae32c /tests
parent43a129e94df41f9ac8bc78b702da5a387ada0494 (diff)
downloadComputeLibrary-4c5469b192665c94118a8a558787cb9cec2d0765.tar.gz
COMPMID-2225: Add interface support for new quantized data types.
Add support for: -QSYMM8, 8-bit quantized symmetric -QSYMM8_PER_CHANNEL, 8-bit quantized symmetric with per channel quantization Change-Id: I00c4ff98e44af37419470af61419ee95d0de2463 Signed-off-by: Georgios Pinitas <georgios.pinitas@arm.com> Reviewed-on: https://review.mlplatform.org/c/1236 Tested-by: Arm Jenkins <bsgcomp@arm.com> Reviewed-by: Gian Marco Iodice <gianmarco.iodice@arm.com> Comments-Addressed: Arm Jenkins <bsgcomp@arm.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/Utils.h2
-rw-r--r--tests/validate_examples/graph_convolution.cpp39
-rw-r--r--tests/validate_examples/graph_depthwiseconvolution.cpp37
-rw-r--r--tests/validate_examples/graph_fully_connected.cpp25
-rw-r--r--tests/validate_examples/graph_validate_utils.h9
-rw-r--r--tests/validation/CL/UNIT/TensorAllocator.cpp42
-rw-r--r--tests/validation/Helpers.cpp16
-rw-r--r--tests/validation/UNIT/TensorInfo.cpp64
-rw-r--r--tests/validation/fixtures/NormalizePlanarYUVLayerFixture.h4
-rw-r--r--tests/validation/fixtures/RangeFixture.h6
-rw-r--r--tests/validation/reference/ConcatenateLayer.cpp9
-rw-r--r--tests/validation/reference/Convolution3d.h22
-rw-r--r--tests/validation/reference/DeconvolutionLayer.cpp2
-rw-r--r--tests/validation/reference/DepthConcatenateLayer.cpp20
-rw-r--r--tests/validation/reference/DepthwiseConvolutionLayer.cpp27
-rw-r--r--tests/validation/reference/DepthwiseConvolutionLayer.h2
-rw-r--r--tests/validation/reference/DequantizationLayer.cpp6
-rw-r--r--tests/validation/reference/FullyConnectedLayer.cpp16
-rw-r--r--tests/validation/reference/Im2Col.cpp6
-rw-r--r--tests/validation/reference/QuantizationLayer.cpp11
-rw-r--r--tests/validation/reference/QuantizationLayer.h2
-rw-r--r--tests/validation/reference/Scale.cpp6
22 files changed, 245 insertions, 128 deletions
diff --git a/tests/Utils.h b/tests/Utils.h
index 7c55a3ef50..d6e4a88e77 100644
--- a/tests/Utils.h
+++ b/tests/Utils.h
@@ -355,6 +355,8 @@ void store_value_with_data_type(void *ptr, T value, DataType data_type)
*reinterpret_cast<uint8_t *>(ptr) = value;
break;
case DataType::S8:
+ case DataType::QSYMM8:
+ case DataType::QSYMM8_PER_CHANNEL:
*reinterpret_cast<int8_t *>(ptr) = value;
break;
case DataType::U16:
diff --git a/tests/validate_examples/graph_convolution.cpp b/tests/validate_examples/graph_convolution.cpp
index b17cb2efdd..1ab6691e57 100644
--- a/tests/validate_examples/graph_convolution.cpp
+++ b/tests/validate_examples/graph_convolution.cpp
@@ -158,30 +158,27 @@ public:
*/
void consume_parameters(ExampleParams &common_params)
{
- common_params.input.width = width->value();
- common_params.input.height = height->value();
- common_params.input.fm = channels->value();
- common_params.input.batch = batch->value();
- common_params.input.quant_info.scale = scale->value();
- common_params.input.quant_info.offset = offset->value();
- common_params.input.npy = input_npy->value();
- common_params.input.range_low = input_range_low->value();
- common_params.input.range_high = input_range_high->value();
-
- common_params.weights.width = weights_width->value();
- common_params.weights.height = weights_height->value();
- common_params.weights.fm = OFM->value();
- common_params.weights.npy = weights_npy->value();
- common_params.weights.quant_info.scale = weights_scale->value();
- common_params.weights.quant_info.offset = weights_offset->value();
- common_params.weights.range_low = weights_range_low->value();
- common_params.weights.range_high = weights_range_high->value();
+ common_params.input.width = width->value();
+ common_params.input.height = height->value();
+ common_params.input.fm = channels->value();
+ common_params.input.batch = batch->value();
+ common_params.input.quant_info = QuantizationInfo(scale->value(), offset->value());
+ common_params.input.npy = input_npy->value();
+ common_params.input.range_low = input_range_low->value();
+ common_params.input.range_high = input_range_high->value();
+
+ common_params.weights.width = weights_width->value();
+ common_params.weights.height = weights_height->value();
+ common_params.weights.fm = OFM->value();
+ common_params.weights.npy = weights_npy->value();
+ common_params.weights.quant_info = QuantizationInfo(weights_scale->value(), weights_offset->value());
+ common_params.weights.range_low = weights_range_low->value();
+ common_params.weights.range_high = weights_range_high->value();
common_params.bias.npy = bias_npy->value();
- common_params.output.quant_info.scale = output_scale->value();
- common_params.output.quant_info.offset = output_offset->value();
- common_params.output.npy = output_npy->value();
+ common_params.output.quant_info = QuantizationInfo(output_scale->value(), output_offset->value());
+ common_params.output.npy = output_npy->value();
common_params.convolution.padding_mode = padding_mode->value();
common_params.convolution.padding_top = padding_top->value();
diff --git a/tests/validate_examples/graph_depthwiseconvolution.cpp b/tests/validate_examples/graph_depthwiseconvolution.cpp
index 1f5627a10d..3ea33e1deb 100644
--- a/tests/validate_examples/graph_depthwiseconvolution.cpp
+++ b/tests/validate_examples/graph_depthwiseconvolution.cpp
@@ -158,29 +158,26 @@ public:
*/
void consume_parameters(ExampleParams &common_params)
{
- common_params.input.width = width->value();
- common_params.input.height = height->value();
- common_params.input.fm = channels->value();
- common_params.input.batch = batch->value();
- common_params.input.quant_info.scale = scale->value();
- common_params.input.quant_info.offset = offset->value();
- common_params.input.npy = input_npy->value();
- common_params.input.range_low = input_range_low->value();
- common_params.input.range_high = input_range_high->value();
-
- common_params.weights.width = weights_width->value();
- common_params.weights.height = weights_height->value();
- common_params.weights.npy = weights_npy->value();
- common_params.weights.range_low = weights_range_low->value();
- common_params.weights.range_high = weights_range_high->value();
- common_params.weights.quant_info.scale = weights_scale->value();
- common_params.weights.quant_info.offset = weights_offset->value();
+ common_params.input.width = width->value();
+ common_params.input.height = height->value();
+ common_params.input.fm = channels->value();
+ common_params.input.batch = batch->value();
+ common_params.input.quant_info = QuantizationInfo(scale->value(), offset->value());
+ common_params.input.npy = input_npy->value();
+ common_params.input.range_low = input_range_low->value();
+ common_params.input.range_high = input_range_high->value();
+
+ common_params.weights.width = weights_width->value();
+ common_params.weights.height = weights_height->value();
+ common_params.weights.npy = weights_npy->value();
+ common_params.weights.range_low = weights_range_low->value();
+ common_params.weights.range_high = weights_range_high->value();
+ common_params.weights.quant_info = QuantizationInfo(weights_scale->value(), weights_offset->value());
common_params.bias.npy = bias_npy->value();
- common_params.output.quant_info.scale = output_scale->value();
- common_params.output.quant_info.offset = output_offset->value();
- common_params.output.npy = output_npy->value();
+ common_params.output.quant_info = QuantizationInfo(output_scale->value(), output_offset->value());
+ common_params.output.npy = output_npy->value();
common_params.convolution.padding_mode = padding_mode->value();
common_params.convolution.padding_top = padding_top->value();
diff --git a/tests/validate_examples/graph_fully_connected.cpp b/tests/validate_examples/graph_fully_connected.cpp
index dfa15edd6d..645fa8b124 100644
--- a/tests/validate_examples/graph_fully_connected.cpp
+++ b/tests/validate_examples/graph_fully_connected.cpp
@@ -102,20 +102,17 @@ public:
*/
void consume_parameters(ExampleParams &common_params)
{
- common_params.input.width = width->value();
- common_params.input.batch = batch->value();
- common_params.input.quant_info.scale = input_scale->value();
- common_params.input.quant_info.offset = input_offset->value();
- common_params.input.range_low = input_range_low->value();
- common_params.input.range_high = input_range_high->value();
-
- common_params.weights.quant_info.scale = weights_scale->value();
- common_params.weights.quant_info.offset = weights_offset->value();
- common_params.weights.range_low = weights_range_low->value();
- common_params.weights.range_high = weights_range_high->value();
-
- common_params.output.quant_info.scale = output_scale->value();
- common_params.output.quant_info.offset = output_offset->value();
+ common_params.input.width = width->value();
+ common_params.input.batch = batch->value();
+ common_params.input.quant_info = QuantizationInfo(input_scale->value(), input_offset->value());
+ common_params.input.range_low = input_range_low->value();
+ common_params.input.range_high = input_range_high->value();
+
+ common_params.weights.quant_info = QuantizationInfo(weights_scale->value(), weights_offset->value());
+ common_params.weights.range_low = weights_range_low->value();
+ common_params.weights.range_high = weights_range_high->value();
+
+ common_params.output.quant_info = QuantizationInfo(output_scale->value(), output_offset->value());
common_params.data_type = data_type->value();
common_params.fully_connected.num_outputs = num_outputs->value();
diff --git a/tests/validate_examples/graph_validate_utils.h b/tests/validate_examples/graph_validate_utils.h
index 485d3c1409..13cc4fa683 100644
--- a/tests/validate_examples/graph_validate_utils.h
+++ b/tests/validate_examples/graph_validate_utils.h
@@ -453,16 +453,17 @@ public:
{
ARM_COMPUTE_ERROR_ON(tensor.data_type() != arm_compute::DataType::QASYMM8);
- std::mt19937 gen(seed);
+ const UniformQuantizationInfo qinfo = tensor.quantization_info().uniform();
- uint8_t qasymm8_low = tensor.quantization_info().quantize(low, RoundingPolicy::TO_NEAREST_UP);
- uint8_t qasymm8_high = tensor.quantization_info().quantize(high, RoundingPolicy::TO_NEAREST_UP);
+ uint8_t qasymm8_low = quantize_qasymm8(low, qinfo);
+ uint8_t qasymm8_high = quantize_qasymm8(high, qinfo);
+ std::mt19937 gen(seed);
std::uniform_int_distribution<uint8_t> distribution(qasymm8_low, qasymm8_high);
for(int i = 0; i < tensor.num_elements(); ++i)
{
- tensor[i] = tensor.quantization_info().quantize(distribution(gen), RoundingPolicy::TO_NEAREST_UP);
+ tensor[i] = quantize_qasymm8(distribution(gen), qinfo);
}
}
/** Fill S32 tensor with Random values.
diff --git a/tests/validation/CL/UNIT/TensorAllocator.cpp b/tests/validation/CL/UNIT/TensorAllocator.cpp
index e5b37d8387..4b8e105240 100644
--- a/tests/validation/CL/UNIT/TensorAllocator.cpp
+++ b/tests/validation/CL/UNIT/TensorAllocator.cpp
@@ -66,6 +66,7 @@ TEST_SUITE(CL)
TEST_SUITE(UNIT)
TEST_SUITE(TensorAllocator)
+/** Validates import memory interface when importing cl buffer objects */
TEST_CASE(ImportMemoryBuffer, framework::DatasetMode::ALL)
{
// Init tensor info
@@ -106,6 +107,7 @@ TEST_CASE(ImportMemoryBuffer, framework::DatasetMode::ALL)
ARM_COMPUTE_EXPECT(t4.cl_buffer().get() != buf.get(), framework::LogLevel::ERRORS);
}
+/** Validates import memory interface when importing malloced memory */
TEST_CASE(ImportMemoryMalloc, framework::DatasetMode::ALL)
{
// Check if import extension is supported
@@ -168,6 +170,7 @@ TEST_CASE(ImportMemoryMalloc, framework::DatasetMode::ALL)
}
#if !defined(BARE_METAL)
+/** Validates import memory interface when importing memory mapped objects */
TEST_CASE(ImportMemoryMappedFile, framework::DatasetMode::ALL)
{
// Check if import extension is supported
@@ -235,6 +238,45 @@ TEST_CASE(ImportMemoryMappedFile, framework::DatasetMode::ALL)
}
#endif // !defined(BARE_METAL)
+/** Validates symmetric per channel quantization */
+TEST_CASE(Symm8PerChannelQuantizationInfo, framework::DatasetMode::ALL)
+{
+ // Create tensor
+ CLTensor tensor;
+ const std::vector<float> scale = { 0.25f, 1.4f, 3.2f, 2.3f, 4.7f };
+ const TensorInfo info(TensorShape(32U, 16U), 1, DataType::QSYMM8_PER_CHANNEL, QuantizationInfo(scale));
+ tensor.allocator()->init(info);
+
+ // Check quantization information
+ ARM_COMPUTE_EXPECT(!tensor.info()->quantization_info().empty(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(!tensor.info()->quantization_info().scale.empty(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(tensor.info()->quantization_info().scale.size() == scale.size(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(tensor.info()->quantization_info().offset.empty(), framework::LogLevel::ERRORS);
+
+ CLQuantization quantization = tensor.quantization();
+ ARM_COMPUTE_ASSERT(quantization.scale != nullptr);
+ ARM_COMPUTE_ASSERT(quantization.offset != nullptr);
+
+ // Check OpenCL quantization arrays before allocating
+ ARM_COMPUTE_EXPECT(quantization.scale->max_num_values() == 0, framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(quantization.offset->max_num_values() == 0, framework::LogLevel::ERRORS);
+
+ // Check OpenCL quantization arrays after allocating
+ tensor.allocator()->allocate();
+ ARM_COMPUTE_EXPECT(quantization.scale->max_num_values() == scale.size(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(quantization.offset->max_num_values() == 0, framework::LogLevel::ERRORS);
+
+ // Validate that the scale values are the same
+ auto cl_scale_buffer = quantization.scale->cl_buffer();
+ void *mapped_ptr = CLScheduler::get().queue().enqueueMapBuffer(cl_scale_buffer, CL_TRUE, CL_MAP_READ, 0, scale.size());
+ auto cl_scale_ptr = static_cast<float *>(mapped_ptr);
+ for(unsigned int i = 0; i < scale.size(); ++i)
+ {
+ ARM_COMPUTE_EXPECT(cl_scale_ptr[i] == scale[i], framework::LogLevel::ERRORS);
+ }
+ CLScheduler::get().queue().enqueueUnmapMemObject(cl_scale_buffer, mapped_ptr);
+}
+
TEST_SUITE_END() // TensorAllocator
TEST_SUITE_END() // UNIT
TEST_SUITE_END() // CL
diff --git a/tests/validation/Helpers.cpp b/tests/validation/Helpers.cpp
index 71a674b515..31d6bfae07 100644
--- a/tests/validation/Helpers.cpp
+++ b/tests/validation/Helpers.cpp
@@ -110,22 +110,24 @@ CannyEdgeParameters canny_edge_parameters()
SimpleTensor<float> convert_from_asymmetric(const SimpleTensor<uint8_t> &src)
{
- const QuantizationInfo &quantization_info = src.quantization_info();
- SimpleTensor<float> dst{ src.shape(), DataType::F32, 1, QuantizationInfo(), src.data_layout() };
+ const UniformQuantizationInfo &quantization_info = src.quantization_info().uniform();
+ SimpleTensor<float> dst{ src.shape(), DataType::F32, 1, QuantizationInfo(), src.data_layout() };
for(int i = 0; i < src.num_elements(); ++i)
{
- dst[i] = quantization_info.dequantize(src[i]);
+ dst[i] = dequantize_qasymm8(src[i], quantization_info);
}
return dst;
}
SimpleTensor<uint8_t> convert_to_asymmetric(const SimpleTensor<float> &src, const QuantizationInfo &quantization_info)
{
- SimpleTensor<uint8_t> dst{ src.shape(), DataType::QASYMM8, 1, quantization_info };
+ SimpleTensor<uint8_t> dst{ src.shape(), DataType::QASYMM8, 1, quantization_info };
+ const UniformQuantizationInfo &qinfo = quantization_info.uniform();
+
for(int i = 0; i < src.num_elements(); ++i)
{
- dst[i] = quantization_info.quantize(src[i], RoundingPolicy::TO_NEAREST_UP);
+ dst[i] = quantize_qasymm8(src[i], qinfo);
}
return dst;
}
@@ -267,8 +269,8 @@ std::pair<int, int> get_quantized_bounds(const QuantizationInfo &quant_info, flo
{
ARM_COMPUTE_ERROR_ON_MSG(min > max, "min must be lower equal than max");
- const int min_bound = quant_info.quantize(min, RoundingPolicy::TO_NEAREST_UP);
- const int max_bound = quant_info.quantize(max, RoundingPolicy::TO_NEAREST_UP);
+ const int min_bound = quantize_qasymm8(min, quant_info.uniform());
+ const int max_bound = quantize_qasymm8(max, quant_info.uniform());
return std::pair<int, int> { min_bound, max_bound };
}
diff --git a/tests/validation/UNIT/TensorInfo.cpp b/tests/validation/UNIT/TensorInfo.cpp
index b78f656932..96d07da2b4 100644
--- a/tests/validation/UNIT/TensorInfo.cpp
+++ b/tests/validation/UNIT/TensorInfo.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -122,6 +122,68 @@ TEST_CASE(TensorInfoBuild, framework::DatasetMode::ALL)
ARM_COMPUTE_EXPECT(info.tensor_shape() == TensorShape(13U, 15U), framework::LogLevel::ERRORS);
}
+/** Validates empty quantization info */
+TEST_CASE(NoQuantizationInfo, framework::DatasetMode::ALL)
+{
+ // Create tensor info
+ const TensorInfo info(TensorShape(32U, 16U), 1, DataType::F32);
+
+ // Check quantization information
+ ARM_COMPUTE_EXPECT(info.quantization_info().empty(), framework::LogLevel::ERRORS);
+}
+
+/** Validates symmetric quantization info */
+TEST_CASE(SymmQuantizationInfo, framework::DatasetMode::ALL)
+{
+ // Create tensor info
+ const float scale = 0.25f;
+ const TensorInfo info(TensorShape(32U, 16U), 1, DataType::QSYMM8, QuantizationInfo(scale));
+
+ // Check quantization information
+ ARM_COMPUTE_EXPECT(!info.quantization_info().empty(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(!info.quantization_info().scale.empty(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(info.quantization_info().scale.size() == 1, framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(info.quantization_info().offset.empty(), framework::LogLevel::ERRORS);
+
+ UniformQuantizationInfo qinfo = info.quantization_info().uniform();
+ ARM_COMPUTE_EXPECT(qinfo.scale == scale, framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(qinfo.offset == 0.f, framework::LogLevel::ERRORS);
+}
+
+/** Validates asymmetric quantization info */
+TEST_CASE(AsymmQuantizationInfo, framework::DatasetMode::ALL)
+{
+ // Create tensor info
+ const float scale = 0.25f;
+ const int32_t offset = 126;
+ const TensorInfo info(TensorShape(32U, 16U), 1, DataType::QSYMM8, QuantizationInfo(scale, offset));
+
+ // Check quantization information
+ ARM_COMPUTE_EXPECT(!info.quantization_info().empty(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(!info.quantization_info().scale.empty(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(info.quantization_info().scale.size() == 1, framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(!info.quantization_info().offset.empty(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(info.quantization_info().offset.size() == 1, framework::LogLevel::ERRORS);
+
+ UniformQuantizationInfo qinfo = info.quantization_info().uniform();
+ ARM_COMPUTE_EXPECT(qinfo.scale == scale, framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(qinfo.offset == offset, framework::LogLevel::ERRORS);
+}
+
+/** Validates symmetric per channel quantization info */
+TEST_CASE(SymmPerChannelQuantizationInfo, framework::DatasetMode::ALL)
+{
+ // Create tensor info
+ const std::vector<float> scale = { 0.25f, 1.4f, 3.2f, 2.3f, 4.7f };
+ const TensorInfo info(TensorShape(32U, 16U), 1, DataType::QSYMM8_PER_CHANNEL, QuantizationInfo(scale));
+
+ // Check quantization information
+ ARM_COMPUTE_EXPECT(!info.quantization_info().empty(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(!info.quantization_info().scale.empty(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(info.quantization_info().scale.size() == scale.size(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(info.quantization_info().offset.empty(), framework::LogLevel::ERRORS);
+}
+
TEST_SUITE_END() // TensorInfoValidation
TEST_SUITE_END()
} // namespace validation
diff --git a/tests/validation/fixtures/NormalizePlanarYUVLayerFixture.h b/tests/validation/fixtures/NormalizePlanarYUVLayerFixture.h
index 93e4e64830..b46bd3c407 100644
--- a/tests/validation/fixtures/NormalizePlanarYUVLayerFixture.h
+++ b/tests/validation/fixtures/NormalizePlanarYUVLayerFixture.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -71,7 +71,7 @@ protected:
const QuantizationInfo quant_info = src_tensor.quantization_info();
std::pair<int, int> bounds = get_quantized_bounds(quant_info, -1.f, 1.0f);
std::uniform_int_distribution<> distribution(bounds.first, bounds.second);
- std::uniform_int_distribution<> distribution_std(quant_info.quantize(0.1f, RoundingPolicy::TO_NEAREST_UP), bounds.second);
+ std::uniform_int_distribution<> distribution_std(quantize_qasymm8(0.1f, quant_info.uniform()), bounds.second);
library->fill(src_tensor, distribution, 0);
library->fill(mean_tensor, distribution, 1);
library->fill(std_tensor, distribution_std, 2);
diff --git a/tests/validation/fixtures/RangeFixture.h b/tests/validation/fixtures/RangeFixture.h
index c192eee14f..4862069694 100644
--- a/tests/validation/fixtures/RangeFixture.h
+++ b/tests/validation/fixtures/RangeFixture.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 ARM Limited.
+ * Copyright (c) 2018-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -95,7 +95,9 @@ protected:
end += std::max(half(1.0f), static_cast<half>(distribution(gen))) * step;
return utility::clamp<float, half>(end);
case DataType::QASYMM8:
- return utility::clamp<float, uint8_t>(end + (float)distribution(gen) * step, qinfo_out.dequantize(0), qinfo_out.dequantize(std::numeric_limits<uint8_t>::max()));
+ return utility::clamp<float, uint8_t>(end + (float)distribution(gen) * step,
+ dequantize_qasymm8(0, qinfo_out.uniform()),
+ dequantize_qasymm8(std::numeric_limits<uint8_t>::max(), qinfo_out.uniform()));
default:
return 0;
}
diff --git a/tests/validation/reference/ConcatenateLayer.cpp b/tests/validation/reference/ConcatenateLayer.cpp
index af818a576c..6c90d74a0f 100644
--- a/tests/validation/reference/ConcatenateLayer.cpp
+++ b/tests/validation/reference/ConcatenateLayer.cpp
@@ -72,10 +72,13 @@ SimpleTensor<T> widthconcatenate_layer(const std::vector<SimpleTensor<T>> &srcs,
const int offset = u * height * depth + d * height + r;
if(src.data_type() == DataType::QASYMM8 && src.quantization_info() != dst.quantization_info())
{
- std::transform(src_ptr, src_ptr + width, dst_ptr + width_offset + offset * width_out, [src, dst](T t)
+ const UniformQuantizationInfo iq_info = src.quantization_info().uniform();
+ const UniformQuantizationInfo oq_info = dst.quantization_info().uniform();
+
+ std::transform(src_ptr, src_ptr + width, dst_ptr + width_offset + offset * width_out, [&](T t)
{
- const float dequantized_input = src.quantization_info().dequantize(t);
- return dst.quantization_info().quantize(dequantized_input, RoundingPolicy::TO_NEAREST_UP);
+ const float dequantized_input = dequantize_qasymm8(t, iq_info);
+ return quantize_qasymm8(dequantized_input, oq_info);
});
src_ptr += width;
}
diff --git a/tests/validation/reference/Convolution3d.h b/tests/validation/reference/Convolution3d.h
index 2e5fefd99a..30be25f504 100644
--- a/tests/validation/reference/Convolution3d.h
+++ b/tests/validation/reference/Convolution3d.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -9,14 +9,14 @@
* 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:
- *asymm_int_mult
+ *
* 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, asymm_int_multDAMAGES OR OTHER
+ * 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.
@@ -101,12 +101,16 @@ inline void convolution3d(const SimpleTensor<T> &in, const SimpleTensor<T> &weig
const TB *b_ptr = bias.data() + b_offset;
T *out_ptr = out.data() + o_offset;
- const int input_offset = -in.quantization_info().offset;
- const float input_scale = in.quantization_info().scale;
- const int weights_offset = -weights.quantization_info().offset;
- const float weights_scale = weights.quantization_info().scale;
- const int output_offset = out.quantization_info().offset;
- const float output_scale = out.quantization_info().scale;
+ const UniformQuantizationInfo iq_info = in.quantization_info().uniform();
+ const UniformQuantizationInfo wq_info = weights.quantization_info().uniform();
+ const UniformQuantizationInfo oq_info = out.quantization_info().uniform();
+
+ const int input_offset = -iq_info.offset;
+ const float input_scale = iq_info.scale;
+ const int weights_offset = -wq_info.offset;
+ const float weights_scale = wq_info.scale;
+ const int output_offset = oq_info.offset;
+ const float output_scale = oq_info.scale;
int output_multiplier = 0;
int output_shift = 0;
diff --git a/tests/validation/reference/DeconvolutionLayer.cpp b/tests/validation/reference/DeconvolutionLayer.cpp
index 916792479f..af59830722 100644
--- a/tests/validation/reference/DeconvolutionLayer.cpp
+++ b/tests/validation/reference/DeconvolutionLayer.cpp
@@ -68,7 +68,7 @@ SimpleTensor<T> deconvolution_layer(const SimpleTensor<T> &src, const SimpleTens
if(src.data_type() == DataType::QASYMM8)
{
- const uint8_t quantized_zero = src.quantization_info().offset;
+ const uint8_t quantized_zero = src.quantization_info().uniform().offset;
std::fill_n(scaled.data(), scaled.num_elements(), quantized_zero);
}
else
diff --git a/tests/validation/reference/DepthConcatenateLayer.cpp b/tests/validation/reference/DepthConcatenateLayer.cpp
index 22271a0d10..d6e6e78187 100644
--- a/tests/validation/reference/DepthConcatenateLayer.cpp
+++ b/tests/validation/reference/DepthConcatenateLayer.cpp
@@ -55,6 +55,7 @@ SimpleTensor<T> depthconcatenate_layer(const std::vector<SimpleTensor<T>> &srcs,
{
return tensor.quantization_info() != dst.quantization_info();
};
+
if(srcs[0].data_type() == DataType::QASYMM8 && std::any_of(srcs.cbegin(), srcs.cend(), have_different_quantization_info))
{
for(int b = 0; b < batches; ++b)
@@ -64,11 +65,14 @@ SimpleTensor<T> depthconcatenate_layer(const std::vector<SimpleTensor<T>> &srcs,
int slice = 0;
for(const auto &src : srcs)
{
- auto ptr_slice = static_cast<T *>(dst(Coordinates(0, 0, slice, b)));
- const auto num_elems_in_slice((dst.num_elements() / depth_out) * src.shape().z());
- std::transform(ptr_slice, ptr_slice + num_elems_in_slice, ptr_slice, [src, dst](T)
+ auto ptr_slice = static_cast<T *>(dst(Coordinates(0, 0, slice, b)));
+ const auto num_elems_in_slice((dst.num_elements() / depth_out) * src.shape().z());
+ const UniformQuantizationInfo iq_info = src.quantization_info().uniform();
+ const UniformQuantizationInfo oq_info = dst.quantization_info().uniform();
+
+ std::transform(ptr_slice, ptr_slice + num_elems_in_slice, ptr_slice, [&](T)
{
- return dst.quantization_info().quantize(src.quantization_info().dequantize(0), RoundingPolicy::TO_NEAREST_UP);
+ return quantize_qasymm8(dequantize_qasymm8(0, iq_info), oq_info);
});
slice += src.shape().z();
}
@@ -102,10 +106,12 @@ SimpleTensor<T> depthconcatenate_layer(const std::vector<SimpleTensor<T>> &srcs,
{
if(src.data_type() == DataType::QASYMM8 && src.quantization_info() != dst.quantization_info())
{
- std::transform(src_ptr, src_ptr + width, dst.data() + offset_to_first_element + d * out_stride_z + r * width_out, [src, dst](T t)
+ const UniformQuantizationInfo iq_info = src.quantization_info().uniform();
+ const UniformQuantizationInfo oq_info = dst.quantization_info().uniform();
+ std::transform(src_ptr, src_ptr + width, dst.data() + offset_to_first_element + d * out_stride_z + r * width_out, [&](T t)
{
- const float dequantized_input = src.quantization_info().dequantize(t);
- return dst.quantization_info().quantize(dequantized_input, RoundingPolicy::TO_NEAREST_UP);
+ const float dequantized_input = dequantize_qasymm8(t, iq_info);
+ return quantize_qasymm8(dequantized_input, oq_info);
});
src_ptr += width;
}
diff --git a/tests/validation/reference/DepthwiseConvolutionLayer.cpp b/tests/validation/reference/DepthwiseConvolutionLayer.cpp
index 90ecffbbca..2192d681b6 100644
--- a/tests/validation/reference/DepthwiseConvolutionLayer.cpp
+++ b/tests/validation/reference/DepthwiseConvolutionLayer.cpp
@@ -50,7 +50,7 @@ namespace reference
*/
template <typename T, typename TB>
SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &biases, const TensorShape &dst_shape, const PadStrideInfo &conv_info,
- unsigned int depth_multiplier, const Size2D &dilation, QuantizationInfo out_quant_info)
+ unsigned int depth_multiplier, const Size2D &dilation, const QuantizationInfo &out_quant_info)
{
ARM_COMPUTE_UNUSED(out_quant_info);
@@ -126,22 +126,19 @@ SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTe
template <>
SimpleTensor<uint8_t> depthwise_convolution(const SimpleTensor<uint8_t> &src, const SimpleTensor<uint8_t> &weights, const SimpleTensor<int32_t> &biases, const TensorShape &dst_shape,
- const PadStrideInfo &conv_info, unsigned int depth_multiplier, const Size2D &dilation, QuantizationInfo out_quant_info)
+ const PadStrideInfo &conv_info, unsigned int depth_multiplier, const Size2D &dilation, const QuantizationInfo &out_quant_info)
{
// if no explicit quantization has been set you the same as src
- if(out_quant_info == QuantizationInfo(0.0f, 0))
- {
- out_quant_info = src.quantization_info();
- }
- SimpleTensor<uint8_t> dst{ dst_shape, src.data_type(), 1, out_quant_info };
+ const QuantizationInfo &dst_qinfo = out_quant_info.uniform().empty() ? src.quantization_info() : out_quant_info;
+ SimpleTensor<uint8_t> dst{ dst_shape, src.data_type(), 1, dst_qinfo };
// Create reference
- const int input_offset = -src.quantization_info().offset;
- const float input_scale = src.quantization_info().scale;
- const int weights_offset = -weights.quantization_info().offset;
- const float weights_scale = weights.quantization_info().scale;
- const int output_offset = dst.quantization_info().offset;
- const float output_scale = dst.quantization_info().scale;
+ const int input_offset = -src.quantization_info().uniform().offset;
+ const float input_scale = src.quantization_info().uniform().scale;
+ const int weights_offset = -weights.quantization_info().uniform().offset;
+ const float weights_scale = weights.quantization_info().uniform().scale;
+ const int output_offset = dst.quantization_info().uniform().offset;
+ const float output_scale = dst.quantization_info().uniform().scale;
int output_multiplier;
int output_shift;
@@ -224,10 +221,10 @@ SimpleTensor<uint8_t> depthwise_convolution(const SimpleTensor<uint8_t> &src, co
}
template SimpleTensor<float> depthwise_convolution(const SimpleTensor<float> &src, const SimpleTensor<float> &weights, const SimpleTensor<float> &biases, const TensorShape &dst_shape,
- const PadStrideInfo &conv_info, unsigned int depth_multiplier, const Size2D &dilation, QuantizationInfo out_quant_info);
+ const PadStrideInfo &conv_info, unsigned int depth_multiplier, const Size2D &dilation, const QuantizationInfo &out_quant_info);
template SimpleTensor<half> depthwise_convolution(const SimpleTensor<half> &src, const SimpleTensor<half> &weights, const SimpleTensor<half> &biases, const TensorShape &dst_shape,
- const PadStrideInfo &conv_info, unsigned int depth_multiplier, const Size2D &dilation, QuantizationInfo out_quant_info);
+ const PadStrideInfo &conv_info, unsigned int depth_multiplier, const Size2D &dilation, const QuantizationInfo &out_quant_info);
} // namespace reference
} // namespace validation
} // namespace test
diff --git a/tests/validation/reference/DepthwiseConvolutionLayer.h b/tests/validation/reference/DepthwiseConvolutionLayer.h
index ac70de02ca..ee323fa8df 100644
--- a/tests/validation/reference/DepthwiseConvolutionLayer.h
+++ b/tests/validation/reference/DepthwiseConvolutionLayer.h
@@ -37,7 +37,7 @@ namespace reference
{
template <typename T, typename TB>
SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &biases, const TensorShape &dst_shape, const PadStrideInfo &conv_info,
- unsigned int depth_multiplier, const Size2D &dilation = Size2D(1U, 1U), QuantizationInfo out_quant_info = QuantizationInfo(0.0f, 0));
+ unsigned int depth_multiplier, const Size2D &dilation = Size2D(1U, 1U), const QuantizationInfo &out_quant_info = QuantizationInfo(0.0f, 0));
} // namespace reference
} // namespace validation
} // namespace test
diff --git a/tests/validation/reference/DequantizationLayer.cpp b/tests/validation/reference/DequantizationLayer.cpp
index df50c14ec7..286a609d79 100644
--- a/tests/validation/reference/DequantizationLayer.cpp
+++ b/tests/validation/reference/DequantizationLayer.cpp
@@ -34,14 +34,14 @@ namespace reference
template <typename T>
SimpleTensor<T> dequantization_layer(const SimpleTensor<uint8_t> &src)
{
- const DataType dst_data_type = std::is_same<T, float>::value ? DataType::F32 : DataType::F16;
- const QuantizationInfo &quantization_info = src.quantization_info();
+ const DataType dst_data_type = std::is_same<T, float>::value ? DataType::F32 : DataType::F16;
+ const UniformQuantizationInfo &quantization_info = src.quantization_info().uniform();
SimpleTensor<T> dst{ src.shape(), dst_data_type };
for(int i = 0; i < src.num_elements(); ++i)
{
- dst[i] = static_cast<T>(quantization_info.dequantize(src[i]));
+ dst[i] = static_cast<T>(dequantize_qasymm8(src[i], quantization_info));
}
return dst;
diff --git a/tests/validation/reference/FullyConnectedLayer.cpp b/tests/validation/reference/FullyConnectedLayer.cpp
index 07ddf6d308..cd84b9cfd1 100644
--- a/tests/validation/reference/FullyConnectedLayer.cpp
+++ b/tests/validation/reference/FullyConnectedLayer.cpp
@@ -67,12 +67,16 @@ void vector_matrix_multiply(const SimpleTensor<T> &src, const SimpleTensor<T> &w
const TB *bias_ptr = bias.data();
T *dst_ptr = dst.data() + offset_dst;
- const int input_offset = -src.quantization_info().offset;
- const float input_scale = src.quantization_info().scale;
- const int weights_offset = -weights.quantization_info().offset;
- const float weights_scale = weights.quantization_info().scale;
- const int output_offset = dst.quantization_info().offset;
- const float output_scale = dst.quantization_info().scale;
+ const UniformQuantizationInfo iq_info = src.quantization_info().uniform();
+ const UniformQuantizationInfo wq_info = weights.quantization_info().uniform();
+ const UniformQuantizationInfo oq_info = dst.quantization_info().uniform();
+
+ const int input_offset = -iq_info.offset;
+ const float input_scale = iq_info.scale;
+ const int weights_offset = -wq_info.offset;
+ const float weights_scale = wq_info.scale;
+ const int output_offset = oq_info.offset;
+ const float output_scale = oq_info.scale;
int output_multiplier = 0;
int output_shift = 0;
diff --git a/tests/validation/reference/Im2Col.cpp b/tests/validation/reference/Im2Col.cpp
index 076b2aba07..4d63696e67 100644
--- a/tests/validation/reference/Im2Col.cpp
+++ b/tests/validation/reference/Im2Col.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 ARM Limited.
+ * Copyright (c) 2018-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -50,7 +50,7 @@ void im2col_nchw(const SimpleTensor<T> &src, SimpleTensor<T> &dst, const Size2D
const int src_channels = src.shape().z();
const int batches = src.shape().total_size_upper(3);
const int dst_height = dst.shape().y();
- const int pad_val = is_data_type_quantized_asymmetric(src.data_type()) ? src.quantization_info().offset : 0;
+ const int pad_val = is_data_type_quantized_asymmetric(src.data_type()) ? src.quantization_info().uniform().offset : 0;
int dst_idx = 0;
// Compute width and height of the convolved tensors
@@ -105,7 +105,7 @@ void im2col_nhwc(const SimpleTensor<T> &src, SimpleTensor<T> &dst, const Size2D
const int batches = src.shape().total_size_upper(3);
const int dst_width = has_bias ? dst.shape().x() - 1 : dst.shape().x();
const int dst_height = dst.shape().y();
- const int pad_val = is_data_type_quantized_asymmetric(src.data_type()) ? src.quantization_info().offset : 0;
+ const int pad_val = is_data_type_quantized_asymmetric(src.data_type()) ? src.quantization_info().uniform().offset : 0;
// Compute width and height of the convolved tensors
std::pair<unsigned int, unsigned int> convolved_dims = scaled_dimensions(src_width, src_height, kernel_dims.width, kernel_dims.height, conv_info);
diff --git a/tests/validation/reference/QuantizationLayer.cpp b/tests/validation/reference/QuantizationLayer.cpp
index 2f3348178c..182585abf9 100644
--- a/tests/validation/reference/QuantizationLayer.cpp
+++ b/tests/validation/reference/QuantizationLayer.cpp
@@ -34,24 +34,25 @@ namespace validation
namespace reference
{
template <typename T>
-SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<T> &src, const QuantizationInfo quantization_info)
+SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<T> &src, const QuantizationInfo &quantization_info)
{
// Create reference
SimpleTensor<uint8_t> dst{ src.shape(), DataType::QASYMM8, 1, quantization_info };
+ const UniformQuantizationInfo qinfo = quantization_info.uniform();
for(int i = 0; i < src.num_elements(); ++i)
{
#ifdef __aarch64__
- dst[i] = quantization_info.quantize((src[i]), RoundingPolicy::TO_NEAREST_EVEN);
+ dst[i] = quantize_qasymm8((src[i]), qinfo, RoundingPolicy::TO_NEAREST_EVEN);
#else // __aarch64__
- dst[i] = quantization_info.quantize((src[i]), RoundingPolicy::TO_ZERO);
+ dst[i] = quantize_qasymm8((src[i]), qinfo, RoundingPolicy::TO_ZERO);
#endif // __aarch64__
}
return dst;
}
-template SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<half> &src, const QuantizationInfo quantization_info);
-template SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<float> &src, const QuantizationInfo quantization_info);
+template SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<half> &src, const QuantizationInfo &quantization_info);
+template SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<float> &src, const QuantizationInfo &quantization_info);
} // namespace reference
} // namespace validation
} // namespace test
diff --git a/tests/validation/reference/QuantizationLayer.h b/tests/validation/reference/QuantizationLayer.h
index 2d136908af..462396f131 100644
--- a/tests/validation/reference/QuantizationLayer.h
+++ b/tests/validation/reference/QuantizationLayer.h
@@ -36,7 +36,7 @@ namespace validation
namespace reference
{
template <typename T>
-SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<T> &src, const QuantizationInfo quantization_info);
+SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<T> &src, const QuantizationInfo &quantization_info);
} // namespace reference
} // namespace validation
} // namespace test
diff --git a/tests/validation/reference/Scale.cpp b/tests/validation/reference/Scale.cpp
index 2f7bf2deb3..84f4fb83c1 100644
--- a/tests/validation/reference/Scale.cpp
+++ b/tests/validation/reference/Scale.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -180,10 +180,10 @@ SimpleTensor<uint8_t> scale(const SimpleTensor<uint8_t> &src, float scale_x, flo
SamplingPolicy sampling_policy, bool ceil_policy_scale)
{
SimpleTensor<uint8_t> dst;
- if(src.quantization_info().scale != 0.f)
+ if(src.quantization_info().uniform().scale != 0.f)
{
SimpleTensor<float> src_tmp = convert_from_asymmetric(src);
- float constant_border_value_f = scvt_f32_qasymm8(constant_border_value, src.quantization_info().scale, src.quantization_info().offset);
+ float constant_border_value_f = dequantize_qasymm8(constant_border_value, src.quantization_info());
SimpleTensor<float> dst_tmp = scale_core<float>(src_tmp, scale_x, scale_y, policy, border_mode, constant_border_value_f, sampling_policy, ceil_policy_scale);
dst = convert_to_asymmetric(dst_tmp, src.quantization_info());
}