From 9fef38ac706aac6ff194fb76e92dcc774e12e115 Mon Sep 17 00:00:00 2001 From: Michele Di Giorgio Date: Fri, 6 Jul 2018 18:06:58 +0100 Subject: COMPMID-1376: Add support for QASYMM8 in CLDeconvolutionLayer Change-Id: I13ec79b6668e2b9559d3fa789ae0b51ab6975289 Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/139126 Reviewed-by: Michalis Spyrou Tested-by: Jenkins --- .../kernels/CLDeconvolutionLayerUpsampleKernel.h | 8 +-- .../runtime/CL/functions/CLDeconvolutionLayer.h | 4 +- .../CL/functions/CLDeconvolutionLayerUpsample.h | 10 +-- src/core/CL/cl_kernels/deconvolution_layer.cl | 4 +- .../kernels/CLDeconvolutionLayerUpsampleKernel.cpp | 2 +- src/runtime/CL/functions/CLDeconvolutionLayer.cpp | 17 +++-- .../CL/functions/CLDeconvolutionLayerUpsample.cpp | 12 +++- tests/validation/CL/DeconvolutionLayer.cpp | 53 ++++++++++++--- .../fixtures/DeconvolutionLayerFixture.h | 79 ++++++++++++++++------ tests/validation/reference/ConvolutionLayer.cpp | 2 +- tests/validation/reference/DeconvolutionLayer.cpp | 17 +++-- tests/validation/reference/DeconvolutionLayer.h | 6 +- 12 files changed, 155 insertions(+), 59 deletions(-) diff --git a/arm_compute/core/CL/kernels/CLDeconvolutionLayerUpsampleKernel.h b/arm_compute/core/CL/kernels/CLDeconvolutionLayerUpsampleKernel.h index d63f5d4907..5ccf4e64ed 100644 --- a/arm_compute/core/CL/kernels/CLDeconvolutionLayerUpsampleKernel.h +++ b/arm_compute/core/CL/kernels/CLDeconvolutionLayerUpsampleKernel.h @@ -50,16 +50,16 @@ public: /** Initialise the kernel's input and output. * - * @param[in] input Source tensor. Data types supported: F16/F32. - * @param[out] output Destination tensor. Data types supported: F16/F32. All but the lowest two dimensions must be the same size as in the input tensor, i.e. scaling is only performed within the XY-plane. + * @param[in] input Source tensor. Data types supported: QASYMM8/F16/F32. + * @param[out] output Destination tensor. Data types supported: same as @p input. All but the lowest two dimensions must be the same size as in the input tensor, i.e. scaling is only performed within the XY-plane. * @param[in] inner_border Top and right inner border sizes. These rows and columns will be filled with zero. * @param[in] info Contains padding and stride information described in @ref PadStrideInfo. */ void configure(const ICLTensor *input, ICLTensor *output, const BorderSize &inner_border, const PadStrideInfo &info); /** Static function to check if given info will lead to a valid configuration of @ref CLDeconvolutionLayerUpsample * - * @param[in] input Source tensor info. Data types supported: F16/F32. - * @param[in] output Destination tensor info. Data types supported: F16/F32. All but the lowest two dimensions must be the same size as in the input tensor, i.e. scaling is only performed within the XY-plane. + * @param[in] input Source tensor info. Data types supported: QASYMM8/F16/F32. + * @param[in] output Destination tensor info. Data types supported: same as @p input. All but the lowest two dimensions must be the same size as in the input tensor, i.e. scaling is only performed within the XY-plane. * @param[in] inner_border Top and right inner border sizes. These rows and columns will be filled with zero. * @param[in] info Contains padding and stride information described in @ref PadStrideInfo. * diff --git a/arm_compute/runtime/CL/functions/CLDeconvolutionLayer.h b/arm_compute/runtime/CL/functions/CLDeconvolutionLayer.h index 7767b73e10..4dce1e1801 100644 --- a/arm_compute/runtime/CL/functions/CLDeconvolutionLayer.h +++ b/arm_compute/runtime/CL/functions/CLDeconvolutionLayer.h @@ -64,7 +64,7 @@ public: CLDeconvolutionLayer(std::shared_ptr memory_manager = nullptr); /** Set the input, weights, biases and output tensors. * - * @param[in,out] input Input tensor. 3 lower dimensions represent a single input, and an optional 4th dimension for batch of inputs. Data types supported: F16/F32. + * @param[in,out] input Input tensor. 3 lower dimensions represent a single input, and an optional 4th dimension for batch of inputs. Data types supported: QASYMM8/F16/F32. * @param[in] weights The 4d weights with dimensions [width, height, IFM, OFM]. Data type supported: Same as @p input. * @param[in] bias (Optional) The biases have one dimension. Data type supported: Same as @p input. * @param[out] output Output tensor. The output has the same number of dimensions as the @p input. @@ -78,7 +78,7 @@ public: unsigned int inner_border_right, unsigned int inner_border_top, const WeightsInfo &weights_info = WeightsInfo()); /** Static function to check if given info will lead to a valid configuration of @ref CLDeconvolutionLayer * - * @param[in] input Input tensor info. 3 lower dimensions represent a single input, and an optional 4th dimension for batch of inputs. Data types supported: F16/F32. + * @param[in] input Input tensor info. 3 lower dimensions represent a single input, and an optional 4th dimension for batch of inputs. Data types supported: QASYMM8/F16/F32. * @param[in] weights The 4d weights info with dimensions [width, height, IFM, OFM]. Data type supported: Same as @p input. * @param[in] bias (Optional) The biases have one dimension. Data type supported: Same as @p input. * @param[in] output Output tensor info. The output has the same number of dimensions as the @p input. diff --git a/arm_compute/runtime/CL/functions/CLDeconvolutionLayerUpsample.h b/arm_compute/runtime/CL/functions/CLDeconvolutionLayerUpsample.h index 74ee4efb2c..d2f8a78f87 100644 --- a/arm_compute/runtime/CL/functions/CLDeconvolutionLayerUpsample.h +++ b/arm_compute/runtime/CL/functions/CLDeconvolutionLayerUpsample.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018 ARM Limited. + * Copyright (c) 2017-2018 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -55,8 +55,8 @@ public: /** Initialize the function's source, destination, interpolation type and border_mode. * - * @param[in, out] input Source tensor. Data type supported: F32. - * @param[out] output Destination tensor. Data type supported: F32. + * @param[in, out] input Source tensor. Data type supported: QASYMM8/F16/F32. + * @param[out] output Destination tensor. Data type supported: same as @p input. * @param[in] inner_border The number of zeros added to right and top edges of the input. * @param[in] info Contains padding and policies to be used in the deconvolution. */ @@ -64,8 +64,8 @@ public: const PadStrideInfo &info); /** Static function to check if given info will lead to a valid configuration of @ref CLDeconvolutionLayerUpsample * - * @param[in] input Source tensor info. Data type supported: F32. - * @param[in] output Destination tensor info. Data type supported: F32. + * @param[in] input Source tensor info. Data type supported: QASYMM8/F16/F32. + * @param[in] output Destination tensor info. Data type supported: same as @p input. * @param[in] inner_border The number of zeros added to right and top edges of the input. * @param[in] info Contains padding and policies to be used in the deconvolution. * diff --git a/src/core/CL/cl_kernels/deconvolution_layer.cl b/src/core/CL/cl_kernels/deconvolution_layer.cl index e15482c1ba..e5169f983f 100644 --- a/src/core/CL/cl_kernels/deconvolution_layer.cl +++ b/src/core/CL/cl_kernels/deconvolution_layer.cl @@ -25,7 +25,7 @@ /** This function applies upsample on an input image. * - * @param[in] src_ptr Pointer to the source image. Supported data types: F16/F32 + * @param[in] src_ptr Pointer to the source image. Supported data types: QASYMM8/F16/F32 * @param[in] src_stride_x Stride of the source image in X dimension (in bytes) * @param[in] src_step_x src_stride_x * number of elements along X processed per workitem(in bytes) * @param[in] src_stride_y Stride of the source image in Y dimension (in bytes) @@ -33,7 +33,7 @@ * @param[in] src_stride_z Stride of the source tensor in Z dimension (in bytes) * @param[in] src_step_z src_stride_z * number of elements along Z processed per workitem(in bytes) * @param[in] src_offset_first_element_in_bytes The offset of the first element in the source image - * @param[out] dst_ptr Pointer to the destination image. Supported data types: F16/F32 + * @param[out] dst_ptr Pointer to the destination image. Supported data types: same as @p src_ptr * @param[in] dst_stride_x Stride of the destination image in X dimension (in bytes) * @param[in] dst_step_x dst_stride_x * number of elements along X processed per workitem(in bytes) * @param[in] dst_stride_y Stride of the destination image in Y dimension (in bytes) diff --git a/src/core/CL/kernels/CLDeconvolutionLayerUpsampleKernel.cpp b/src/core/CL/kernels/CLDeconvolutionLayerUpsampleKernel.cpp index c6a0031f4a..be3a926b96 100644 --- a/src/core/CL/kernels/CLDeconvolutionLayerUpsampleKernel.cpp +++ b/src/core/CL/kernels/CLDeconvolutionLayerUpsampleKernel.cpp @@ -43,7 +43,7 @@ Status CLDeconvolutionLayerUpsampleKernel::validate(const ITensorInfo *input, co { ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, output); - ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F16, DataType::F32); + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QASYMM8, DataType::F16, DataType::F32); ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, output); ARM_COMPUTE_RETURN_ERROR_ON(output->dimension(0) == 0); ARM_COMPUTE_RETURN_ERROR_ON(output->dimension(1) == 0); diff --git a/src/runtime/CL/functions/CLDeconvolutionLayer.cpp b/src/runtime/CL/functions/CLDeconvolutionLayer.cpp index 40562b5e3e..3f5b8c92dd 100644 --- a/src/runtime/CL/functions/CLDeconvolutionLayer.cpp +++ b/src/runtime/CL/functions/CLDeconvolutionLayer.cpp @@ -47,7 +47,7 @@ Status CLDeconvolutionLayer::validate(const ITensorInfo *input, const ITensorInf unsigned int inner_border_right, unsigned int inner_border_top, const WeightsInfo &weights_info) { ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, weights, output); - ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::F16, DataType::F32); + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QASYMM8, DataType::F16, DataType::F32); ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(0) != weights->dimension(1)); ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(0) < 1); ARM_COMPUTE_RETURN_ERROR_ON(!info.padding_is_symmetric()); @@ -67,7 +67,14 @@ Status CLDeconvolutionLayer::validate(const ITensorInfo *input, const ITensorInf if(bias != nullptr) { - ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, bias); + if(is_data_type_quantized_asymmetric(input->data_type())) + { + ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(bias, 1, DataType::S32); + } + else + { + ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, bias); + } } ARM_COMPUTE_RETURN_ERROR_ON_MSG(output->dimension(Window::DimX) != output_shape.x(), "Output's width is invalid."); @@ -98,7 +105,7 @@ void CLDeconvolutionLayer::configure(ICLTensor *input, const ICLTensor *weights, const TensorShape output_shape = deconvolution_output_shape(out_dims, input->info()->tensor_shape(), weights->info()->tensor_shape()); // Output auto initialization if not yet initialized - auto_init_if_empty(*output->info(), output_shape, 1, input->info()->data_type()); + auto_init_if_empty(*output->info(), output_shape, 1, input->info()->data_type(), input->info()->quantization_info()); // Perform validation step ARM_COMPUTE_ERROR_THROW_ON(CLDeconvolutionLayer::validate(input->info(), weights->info(), bias == nullptr ? nullptr : bias->info(), output->info(), info, inner_border_right, inner_border_top)); @@ -108,13 +115,13 @@ void CLDeconvolutionLayer::configure(ICLTensor *input, const ICLTensor *weights, _memory_group.manage(&_scaled_output); // configure scale function - // Init and allocate intermmidiate tensor for output, same size as input but the first two axis are the same as the output tensor + // Init and allocate intermediate tensor for output, same size as input but the first two axis are the same as the output tensor TensorShape scale_out_shape(input->info()->tensor_shape()); const unsigned int out_x = input->info()->dimension(0) + (input->info()->dimension(0) - 1) * (stride_x - 1) + inner_border_right + 2 * info.pad().first; const unsigned int out_y = input->info()->dimension(1) + (input->info()->dimension(1) - 1) * (stride_y - 1) + inner_border_top + 2 * info.pad().second; scale_out_shape.set(0, out_x); scale_out_shape.set(1, out_y); - TensorInfo scale_out_info(scale_out_shape, 1, input->info()->data_type()); + TensorInfo scale_out_info(scale_out_shape, 1, input->info()->data_type(), input->info()->quantization_info()); _scaled_output.allocator()->init(scale_out_info); _scale_f.configure(input, &_scaled_output, BorderSize(inner_border_top, inner_border_right), info); diff --git a/src/runtime/CL/functions/CLDeconvolutionLayerUpsample.cpp b/src/runtime/CL/functions/CLDeconvolutionLayerUpsample.cpp index 13a24f8ba4..ce8667d656 100644 --- a/src/runtime/CL/functions/CLDeconvolutionLayerUpsample.cpp +++ b/src/runtime/CL/functions/CLDeconvolutionLayerUpsample.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018 ARM Limited. + * Copyright (c) 2017-2018 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -57,7 +57,15 @@ void CLDeconvolutionLayerUpsample::configure(ICLTensor *input, ICLTensor *output void CLDeconvolutionLayerUpsample::run() { _output->map(CLScheduler::get().queue(), true); - memset(_output->buffer(), 0, _output->info()->total_size()); + if(is_data_type_quantized_asymmetric(_output->info()->data_type())) + { + const uint8_t quantized_zero = _output->info()->quantization_info().offset; + std::fill_n(_output->buffer(), _output->info()->total_size(), quantized_zero); + } + else + { + memset(_output->buffer(), 0, _output->info()->total_size()); + } _output->unmap(CLScheduler::get().queue()); CLScheduler::get().enqueue(_upsample, false); diff --git a/tests/validation/CL/DeconvolutionLayer.cpp b/tests/validation/CL/DeconvolutionLayer.cpp index 0fd7ed4ddc..5d10073641 100644 --- a/tests/validation/CL/DeconvolutionLayer.cpp +++ b/tests/validation/CL/DeconvolutionLayer.cpp @@ -45,6 +45,7 @@ namespace { constexpr AbsoluteTolerance tolerance_fp32(0.001f); /**< Tolerance for floating point tests */ RelativeTolerance tolerance_f16(half_float::half(0.2)); /**< Tolerance value for comparing reference's for DataType::F16 */ +constexpr AbsoluteTolerance tolerance_qasymm8(1.0); /**< Tolerance value for comparing reference's output against implementation's output for quantized data types */ constexpr float tolerance_num = 0.07f; /**< Tolerance number */ const auto data4x4 = datasets::SmallDeconvolutionShapes() * framework::dataset::make("StrideX", 1, 4) * framework::dataset::make("StrideY", 1, 4) * framework::dataset::make("PadX", 0, 3) @@ -105,54 +106,48 @@ DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, (combine(datasets::Sm DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(zip( framework::dataset::make("InputInfo", { TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Mismatching data type TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid weights shape - TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QASYMM8), // Non supported data type TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid bias shape TensorInfo(TensorShape(13U, 11U, 4U, 3U), 1, DataType::F32), // Window shrink TensorInfo(TensorShape(32U, 16U, 2U), 1, DataType::F32), }), framework::dataset::make("WeightsInfo", { TensorInfo(TensorShape(3U, 3U, 2U, 2U), 1, DataType::F16), TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32), - TensorInfo(TensorShape(3U, 3U, 2U, 2U), 1, DataType::QASYMM8), TensorInfo(TensorShape(3U, 2U, 2U, 2U), 1, DataType::F32), TensorInfo(TensorShape(3U, 3U, 4U), 1, DataType::F32), TensorInfo(TensorShape(1U, 1U, 2U, 4U), 1, DataType::F32), })), framework::dataset::make("BiasInfo", { TensorInfo(TensorShape(1U), 1, DataType::F16), - TensorInfo(TensorShape(1U), 1, DataType::F32), TensorInfo(TensorShape(1U), 1, DataType::F32), TensorInfo(TensorShape(25U, 11U), 1, DataType::F32), TensorInfo(TensorShape(1U), 1, DataType::F32), TensorInfo(TensorShape(4U), 1, DataType::F32), + TensorInfo(TensorShape(4U), 1, DataType::S32), })), framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(25U, 11U, 2U), 1, DataType::F16), TensorInfo(TensorShape(25U, 10U, 2U), 1, DataType::F32), - TensorInfo(TensorShape(25U, 11U, 2U), 1, DataType::F32), TensorInfo(TensorShape(13U, 13U, 2U), 1, DataType::F32), TensorInfo(TensorShape(11U, 9U, 1U, 3U), 1, DataType::F32), TensorInfo(TensorShape(32U, 16U, 4U), 1, DataType::F32), })), framework::dataset::make("PadStrideInfo", { PadStrideInfo(1, 1, 0, 0), - PadStrideInfo(1, 1, 0, 0), PadStrideInfo(1, 1, 0, 0), PadStrideInfo(1, 1, 0, 0), PadStrideInfo(1, 1, 1, 1), PadStrideInfo(1, 1, 0, 0), })), framework::dataset::make("ax", { 1U, - 1U, 1U, 1U, 0U, 0U, })), framework::dataset::make("ay", { 1U, - 1U, 1U, 1U, 0U, 0U, })), - framework::dataset::make("Expected", { false, false, false, false, false, true })), + framework::dataset::make("Expected", { false, false, false, false, true })), input_info, weights_info, bias_info, output_info, pad_info, ax, ay, expected) { bool is_valid = bool(CLDeconvolutionLayer::validate(&input_info.clone()->set_is_resizable(false), &weights_info.clone()->set_is_resizable(false), &bias_info.clone()->set_is_resizable(false), &output_info.clone()->set_is_resizable(false), pad_info, ax, ay)); @@ -228,6 +223,48 @@ TEST_SUITE_END() TEST_SUITE_END() TEST_SUITE_END() +template +using CLDeconvolutionLayerQuantizedFixture4x4 = DeconvolutionValidationQuantizedFixture; + +template +using CLDeconvolutionLayerQuantizedFixture3x3 = DeconvolutionValidationQuantizedFixture; + +template +using CLDeconvolutionLayerQuantizedFixture1x1 = DeconvolutionValidationQuantizedFixture; + +TEST_SUITE(Quantized) +TEST_SUITE(QASYMM8) + +TEST_SUITE(W4x4) +FIXTURE_DATA_TEST_CASE(Run, CLDeconvolutionLayerQuantizedFixture4x4, framework::DatasetMode::ALL, combine(combine(data4x4, framework::dataset::make("DataType", DataType::QASYMM8)), + framework::dataset::make("QuantizationInfo", QuantizationInfo(2.f / 255.f, 127)))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qasymm8, tolerance_num); +} +TEST_SUITE_END() + +TEST_SUITE(W3x3) +FIXTURE_DATA_TEST_CASE(Run, CLDeconvolutionLayerQuantizedFixture3x3, framework::DatasetMode::ALL, combine(combine(data3x3, framework::dataset::make("DataType", DataType::QASYMM8)), + framework::dataset::make("QuantizationInfo", QuantizationInfo(2.f / 255.f, 127)))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qasymm8, tolerance_num); +} +TEST_SUITE_END() + +TEST_SUITE(W1x1) +FIXTURE_DATA_TEST_CASE(Run, CLDeconvolutionLayerQuantizedFixture1x1, framework::DatasetMode::ALL, combine(combine(data1x1, framework::dataset::make("DataType", DataType::QASYMM8)), + framework::dataset::make("QuantizationInfo", QuantizationInfo(2.f / 255.f, 127)))) +{ + // Validate output + validate(CLAccessor(_target), _reference, tolerance_qasymm8, tolerance_num); +} +TEST_SUITE_END() + +TEST_SUITE_END() +TEST_SUITE_END() + TEST_SUITE_END() TEST_SUITE_END() } // namespace validation diff --git a/tests/validation/fixtures/DeconvolutionLayerFixture.h b/tests/validation/fixtures/DeconvolutionLayerFixture.h index 12ce9cefc7..7741557f48 100644 --- a/tests/validation/fixtures/DeconvolutionLayerFixture.h +++ b/tests/validation/fixtures/DeconvolutionLayerFixture.h @@ -42,40 +42,58 @@ namespace validation template class DeconvolutionLayerFixtureBase : public framework::Fixture { +public: + using TBias = typename std::conditional::type, uint8_t>::value, int32_t, T>::type; + public: template void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, - const std::pair &inner_border, DataType data_type) + const std::pair &inner_border, DataType data_type, QuantizationInfo quantization_info) { _data_type = data_type; - _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, inner_border, data_type); - _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, inner_border, data_type); + _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, inner_border, data_type, quantization_info); + _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, inner_border, data_type, quantization_info); } protected: template void fill(U &&tensor, int i) { - if(is_data_type_float(tensor.data_type())) + switch(tensor.data_type()) { - std::uniform_real_distribution<> distribution(-1.0f, 1.0f); - library->fill(tensor, distribution, i); - } - else - { - library->fill_tensor_uniform(tensor, i); + case DataType::QASYMM8: + { + std::uniform_int_distribution distribution(0, 255); + library->fill(tensor, distribution, i); + break; + } + case DataType::S32: + { + std::uniform_int_distribution distribution(-100, 100); + library->fill(tensor, distribution, i); + break; + } + case DataType::F16: + case DataType::F32: + { + std::uniform_real_distribution<> distribution(-1.0f, 1.0f); + library->fill(tensor, distribution, i); + break; + } + default: + library->fill_tensor_uniform(tensor, i); } } TensorType compute_target(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, - const PadStrideInfo &info, const std::pair &inner_border, DataType data_type) + const PadStrideInfo &info, const std::pair &inner_border, DataType data_type, QuantizationInfo quantization_info) { // Create tensors - TensorType src = create_tensor(input_shape, data_type, 1); - TensorType weights = create_tensor(weights_shape, data_type, 1); - TensorType bias = create_tensor(bias_shape, data_type, 1); - TensorType dst = create_tensor(output_shape, data_type, 1); + TensorType src = create_tensor(input_shape, data_type, 1, quantization_info); + TensorType weights = create_tensor(weights_shape, data_type, 1, quantization_info); + TensorType bias = create_tensor(bias_shape, is_data_type_quantized_asymmetric(data_type) ? DataType::S32 : data_type, 1, quantization_info); + TensorType dst = create_tensor(output_shape, data_type, 1, quantization_info); // Create and configure function FunctionType conv; @@ -102,19 +120,19 @@ protected: fill(AccessorType(weights), 1); fill(AccessorType(bias), 2); - // Compute NEConvolutionLayer function + // Compute DeconvolutionLayer function conv.run(); return dst; } SimpleTensor compute_reference(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, - const PadStrideInfo &info, const std::pair inner_border, DataType data_type) + const PadStrideInfo &info, const std::pair inner_border, DataType data_type, QuantizationInfo quantization_info) { // Create reference - SimpleTensor src{ input_shape, data_type, 1 }; - SimpleTensor weights{ weights_shape, data_type, 1 }; - SimpleTensor bias{ bias_shape, data_type, 1 }; + SimpleTensor src{ input_shape, data_type, 1, quantization_info }; + SimpleTensor weights{ weights_shape, data_type, 1, quantization_info }; + SimpleTensor bias{ bias_shape, data_type, 1, quantization_info }; // Fill reference fill(src, 0); @@ -144,7 +162,26 @@ public: const std::pair inner_border(inner_border_right, inner_border_top); auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, padx, pady, inner_border.first, inner_border.second, sx, sy); TensorShape output_shape = deconvolution_output_shape(out_dim, input_shape, weights_shape); - DeconvolutionLayerFixtureBase::setup(input_shape, weights_shape, bias_shape, output_shape, info, inner_border, data_type); + DeconvolutionLayerFixtureBase::setup(input_shape, weights_shape, bias_shape, output_shape, info, inner_border, data_type, QuantizationInfo()); + } +}; + +template +class DeconvolutionValidationQuantizedFixture : public DeconvolutionLayerFixtureBase +{ +public: + template + void setup(TensorShape input_shape, unsigned int sx, unsigned int sy, unsigned int padx, unsigned int pady, + unsigned int inner_border_right, unsigned int inner_border_top, unsigned int num_kernels, DataType data_type, QuantizationInfo quantization_info) + { + ARM_COMPUTE_ERROR_ON_MSG(kernel_size_x != kernel_size_y, "Only square kernels supported"); + const TensorShape weights_shape(kernel_size_x, kernel_size_y, input_shape.z(), num_kernels); + const TensorShape bias_shape(num_kernels); + const PadStrideInfo info(sx, sy, padx, pady, DimensionRoundingType::CEIL); + const std::pair inner_border(inner_border_right, inner_border_top); + auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, padx, pady, inner_border.first, inner_border.second, sx, sy); + TensorShape output_shape = deconvolution_output_shape(out_dim, input_shape, weights_shape); + DeconvolutionLayerFixtureBase::setup(input_shape, weights_shape, bias_shape, output_shape, info, inner_border, data_type, quantization_info); } }; diff --git a/tests/validation/reference/ConvolutionLayer.cpp b/tests/validation/reference/ConvolutionLayer.cpp index e212e2742f..2d314059dd 100644 --- a/tests/validation/reference/ConvolutionLayer.cpp +++ b/tests/validation/reference/ConvolutionLayer.cpp @@ -132,4 +132,4 @@ template SimpleTensor convolution_layer(const SimpleTensor &sr } // namespace reference } // namespace validation } // namespace test -} // namespace arm_compute \ No newline at end of file +} // namespace arm_compute diff --git a/tests/validation/reference/DeconvolutionLayer.cpp b/tests/validation/reference/DeconvolutionLayer.cpp index e73023e419..ba28b46d3a 100644 --- a/tests/validation/reference/DeconvolutionLayer.cpp +++ b/tests/validation/reference/DeconvolutionLayer.cpp @@ -33,8 +33,8 @@ namespace validation { namespace reference { -template -SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, +template +SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, const PadStrideInfo &info, const std::pair &a) { // Create reference @@ -45,7 +45,7 @@ SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTens int out_y = src.shape().y() + (src.shape().y() - 1) * (stride_y - 1) + a.second + 2 * info.pad().second; scaled_shape.set(0, out_x); scaled_shape.set(1, out_y); - SimpleTensor scaled{ scaled_shape, src.data_type(), 1 }; + SimpleTensor scaled{ scaled_shape, src.data_type(), 1, src.quantization_info() }; const int width_in = src.shape().x(); const int height_in = src.shape().y(); @@ -59,9 +59,14 @@ SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTens ARM_COMPUTE_ERROR_ON_MSG(ax > stride_x - 1, "ax must be smaller than stride_x"); ARM_COMPUTE_ERROR_ON_MSG(ay > stride_y - 1, "ay must be smaller than stride_y"); - for(int j = 0; j < scaled.num_elements(); ++j) + if(src.data_type() == DataType::QASYMM8) { - scaled[j] = T(0); + const uint8_t quantized_zero = src.quantization_info().offset; + std::fill_n(scaled.data(), scaled.num_elements(), quantized_zero); + } + else + { + std::fill_n(scaled.data(), scaled.num_elements(), T(0)); } for(int slice = 0; slice < num_2d_slices; ++slice) @@ -88,6 +93,8 @@ SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTens return convolution_layer(scaled, weights, bias, output_shape, conv_info); } +template SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, + const PadStrideInfo &info, const std::pair &a); template SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, const PadStrideInfo &info, const std::pair &a); template SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, diff --git a/tests/validation/reference/DeconvolutionLayer.h b/tests/validation/reference/DeconvolutionLayer.h index c0bc1fa928..95fb416b30 100644 --- a/tests/validation/reference/DeconvolutionLayer.h +++ b/tests/validation/reference/DeconvolutionLayer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018 ARM Limited. + * Copyright (c) 2017-2018 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -45,8 +45,8 @@ namespace reference * a The number of zeros added to right and top edges of the input. * */ -template -SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, const PadStrideInfo &info, +template +SimpleTensor deconvolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, const PadStrideInfo &info, const std::pair &a); } // namespace reference } // namespace validation -- cgit v1.2.1