From dbdea0d1c025b18d4d82c278c87454427918f5b4 Mon Sep 17 00:00:00 2001 From: Georgios Pinitas Date: Wed, 16 Oct 2019 19:21:40 +0100 Subject: COMPMID-2308: NEConvolutionLayer: support QUANT8_SYMM_PER_CHANNEL filters Change-Id: Ic1bf5f0d21ccd525f84213a360f7e199d7f50577 Signed-off-by: Georgios Pinitas Reviewed-on: https://review.mlplatform.org/c/2177 Tested-by: Arm Jenkins Reviewed-by: Michele Di Giorgio Comments-Addressed: Arm Jenkins --- tests/validation/reference/Convolution3d.h | 51 ++++++++++++++++--------- tests/validation/reference/ConvolutionLayer.cpp | 20 +++++----- tests/validation/reference/ConvolutionLayer.h | 4 +- 3 files changed, 46 insertions(+), 29 deletions(-) (limited to 'tests/validation/reference') diff --git a/tests/validation/reference/Convolution3d.h b/tests/validation/reference/Convolution3d.h index 30be25f504..23918a4055 100644 --- a/tests/validation/reference/Convolution3d.h +++ b/tests/validation/reference/Convolution3d.h @@ -42,13 +42,16 @@ inline bool is_valid_pixel(int i, int min, int max) } // 3D convolution for floating point type -template < typename T, typename TB, typename std::enable_if < validation::is_floating_point::value &&validation::is_floating_point::value, int >::type = 0 > -inline void convolution3d(const SimpleTensor &in, const SimpleTensor &weights, const SimpleTensor &bias, SimpleTensor &out, +template < typename T, typename TW, typename TB, typename std::enable_if < validation::is_floating_point::value &&validation::is_floating_point::value + &&validation::is_floating_point::value, + int >::type = 0 > +inline void convolution3d(const SimpleTensor &in, const SimpleTensor &weights, const SimpleTensor &bias, SimpleTensor &out, int i_offset, int w_offset, int b_offset, int o_offset, - int xi, int yi, int width_in, int height_in, int depth_in, int width_weights, int height_weights, int dilation_x = 1, int dilation_y = 1) + int xi, int yi, int width_in, int height_in, int depth_in, int width_weights, int height_weights, int dilation_x = 1, int dilation_y = 1, int filter_id = 0) { + ARM_COMPUTE_UNUSED(filter_id); const T *in_ptr = in.data() + i_offset; - const T *w_ptr = weights.data() + w_offset; + const TW *w_ptr = weights.data() + w_offset; const TB *b_ptr = bias.data() + b_offset; T *out_ptr = out.data() + o_offset; @@ -77,8 +80,8 @@ inline void convolution3d(const SimpleTensor &in, const SimpleTensor &weig const int idx = xk + half_width_weights_start; const int idy = yk + half_height_weights_start; - const T i_value = in_ptr[offset_slice_in + xk * dilation_x + yk * dilation_y * width_in]; - const T w_value = w_ptr[idx + idy * width_weights + ifm * width_weights * height_weights]; + const T i_value = in_ptr[offset_slice_in + xk * dilation_x + yk * dilation_y * width_in]; + const TW w_value = w_ptr[idx + idy * width_weights + ifm * width_weights * height_weights]; acc += i_value * w_value; } @@ -91,13 +94,16 @@ inline void convolution3d(const SimpleTensor &in, const SimpleTensor &weig } // 3D convolution for QASYMM8 type -template < typename T, typename TB, typename std::enable_if < std::is_same::value &&std::is_same::value, int >::type = 0 > -inline void convolution3d(const SimpleTensor &in, const SimpleTensor &weights, const SimpleTensor &bias, SimpleTensor &out, +template < typename T, typename TW, typename TB, typename std::enable_if < std::is_same::value &&(std::is_same::value + || std::is_same::value) + &&std::is_same::value, + int >::type = 0 > +inline void convolution3d(const SimpleTensor &in, const SimpleTensor &weights, const SimpleTensor &bias, SimpleTensor &out, int i_offset, int w_offset, int b_offset, int o_offset, - int xi, int yi, int width_in, int height_in, int depth_in, int width_weights, int height_weights, int dilation_x = 1, int dilation_y = 1) + int xi, int yi, int width_in, int height_in, int depth_in, int width_weights, int height_weights, int dilation_x = 1, int dilation_y = 1, int filter_id = 0) { const T *in_ptr = in.data() + i_offset; - const T *w_ptr = weights.data() + w_offset; + const TW *w_ptr = weights.data() + w_offset; const TB *b_ptr = bias.data() + b_offset; T *out_ptr = out.data() + o_offset; @@ -107,10 +113,22 @@ inline void convolution3d(const SimpleTensor &in, const SimpleTensor &weig 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 weights_offset = -wq_info.offset; + float weights_scale = wq_info.scale; + if(is_data_type_quantized_per_channel(weights.data_type())) + { + if(is_data_type_quantized_asymmetric(weights.data_type())) + { + weights_offset = weights.quantization_info().offset()[filter_id]; + } + else + { + weights_offset = 0; + } + weights_scale = weights.quantization_info().scale()[filter_id]; + } + const int output_offset = oq_info.offset; + const float output_scale = oq_info.scale; int output_multiplier = 0; int output_shift = 0; @@ -142,9 +160,8 @@ inline void convolution3d(const SimpleTensor &in, const SimpleTensor &weig const int idx = xk + half_width_weights_start; const int idy = yk + half_height_weights_start; - const uint8_t i_value = in_ptr[offset_slice_in + xk * dilation_x + yk * dilation_y * width_in]; - const uint8_t w_value = w_ptr[idx + idy * width_weights + ifm * width_weights * height_weights]; - + const int32_t i_value = in_ptr[offset_slice_in + xk * dilation_x + yk * dilation_y * width_in]; + const int32_t w_value = w_ptr[idx + idy * width_weights + ifm * width_weights * height_weights]; acc += (i_value + input_offset) * (w_value + weights_offset); } } diff --git a/tests/validation/reference/ConvolutionLayer.cpp b/tests/validation/reference/ConvolutionLayer.cpp index 69090117fe..4d2c1acb6f 100644 --- a/tests/validation/reference/ConvolutionLayer.cpp +++ b/tests/validation/reference/ConvolutionLayer.cpp @@ -45,8 +45,8 @@ namespace { } // namespace -template -SimpleTensor convolution_layer_nchw(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, SimpleTensor &dst, const PadStrideInfo &info, +template +SimpleTensor convolution_layer_nchw(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, SimpleTensor &dst, const PadStrideInfo &info, const Size2D &dilation, unsigned int num_groups) { ARM_COMPUTE_ERROR_ON((src.shape()[2] / num_groups) != weights.shape()[2]); @@ -73,7 +73,6 @@ SimpleTensor convolution_layer_nchw(const SimpleTensor &src, const SimpleT const int end_xi = output_wh.first * stride_xi; const int end_yi = output_wh.second * stride_yi; const int num_batches = src.shape().total_size() / (width_in * height_in * depth_in); - for(int r = 0; r < num_batches; ++r) { for(int yi = start_yi; yi < start_yi + end_yi; yi += stride_yi) @@ -100,17 +99,16 @@ SimpleTensor convolution_layer_nchw(const SimpleTensor &src, const SimpleT offset_in, offset_w, offset_b, offset_out, xi, yi, width_in, height_in, (depth_in / num_groups), - width_weights, height_weights, dilation.x(), dilation.y()); + width_weights, height_weights, dilation.x(), dilation.y(), ofm); } } } } } - return dst; } -template -SimpleTensor convolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, const PadStrideInfo &info, +template +SimpleTensor convolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, const PadStrideInfo &info, const Size2D &dilation, unsigned int num_groups, QuantizationInfo out_quant_info) { // if no explicit quantization has been set you the same as src @@ -123,9 +121,9 @@ SimpleTensor convolution_layer(const SimpleTensor &src, const SimpleTensor if(src.data_layout() == DataLayout::NHWC) { - SimpleTensor src_nchw = reference::permute(src, PermutationVector(1U, 2U, 0U)); - SimpleTensor weights_nchw = reference::permute(weights, PermutationVector(1U, 2U, 0U)); - SimpleTensor dst_nchw = reference::permute(dst, PermutationVector(1U, 2U, 0U)); + SimpleTensor src_nchw = reference::permute(src, PermutationVector(1U, 2U, 0U)); + SimpleTensor weights_nchw = reference::permute(weights, PermutationVector(1U, 2U, 0U)); + SimpleTensor dst_nchw = reference::permute(dst, PermutationVector(1U, 2U, 0U)); return reference::permute(convolution_layer_nchw(src_nchw, weights_nchw, bias, dst_nchw, info, dilation, num_groups), PermutationVector(2U, 0U, 1U)); } @@ -141,6 +139,8 @@ template SimpleTensor convolution_layer(const SimpleTensor &src, con const PadStrideInfo &info, const Size2D &dilation, unsigned int num_groups, QuantizationInfo out_quant_info); template SimpleTensor convolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, const PadStrideInfo &info, const Size2D &dilation, unsigned int num_groups, QuantizationInfo out_quant_info); +template SimpleTensor convolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, + const PadStrideInfo &info, const Size2D &dilation, unsigned int num_groups, QuantizationInfo out_quant_info); } // namespace reference } // namespace validation } // namespace test diff --git a/tests/validation/reference/ConvolutionLayer.h b/tests/validation/reference/ConvolutionLayer.h index c51a9b3ad7..8f41073fe2 100644 --- a/tests/validation/reference/ConvolutionLayer.h +++ b/tests/validation/reference/ConvolutionLayer.h @@ -35,8 +35,8 @@ namespace validation { namespace reference { -template -SimpleTensor convolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, const PadStrideInfo &info, +template +SimpleTensor convolution_layer(const SimpleTensor &src, const SimpleTensor &weights, const SimpleTensor &bias, const TensorShape &output_shape, const PadStrideInfo &info, const Size2D &dilation = Size2D(1U, 1U), unsigned int num_groups = 1, QuantizationInfo out_quant_info = QuantizationInfo()); } // namespace reference } // namespace validation -- cgit v1.2.1