From f29d1b7d8bf2d1619554eb3443556b44d4aa1a4c Mon Sep 17 00:00:00 2001 From: Michele Di Giorgio Date: Tue, 29 Oct 2019 10:58:13 +0000 Subject: COMPMID-2608: Enable quantization with multiplier greater than 1 on NEON Change-Id: Ib2b0c9ac88fc2b645f478c9981f71ee28f2c77fd Signed-off-by: Michele Di Giorgio Reviewed-on: https://review.mlplatform.org/c/2425 Comments-Addressed: Arm Jenkins Reviewed-by: Georgios Pinitas Tested-by: Arm Jenkins --- .../NEDepthwiseConvolutionLayerNativeKernel.cpp | 33 +++++++++++++--------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'src/core/NEON/kernels/NEDepthwiseConvolutionLayerNativeKernel.cpp') diff --git a/src/core/NEON/kernels/NEDepthwiseConvolutionLayerNativeKernel.cpp b/src/core/NEON/kernels/NEDepthwiseConvolutionLayerNativeKernel.cpp index a9a3183c5d..aee13ee578 100644 --- a/src/core/NEON/kernels/NEDepthwiseConvolutionLayerNativeKernel.cpp +++ b/src/core/NEON/kernels/NEDepthwiseConvolutionLayerNativeKernel.cpp @@ -289,7 +289,16 @@ void depthwise_loop_multiplier1_quantized(const ITensor *input, const ITensor *w acc.at(i) += *reinterpret_cast(biases_it.ptr() + i * sizeof(int32_t)); } - acc.at(i) = rounding_divide_by_exp2(saturating_doubling_high_mul(acc.at(i), output_multiplier.at(id.x() + i)), output_shift.at(id.x() + i)) + output_qoffset; + const int out_mul = output_multiplier.at(id.x() + i); + const int out_shift = output_shift.at(id.x() + i); + if(out_shift < 0) + { + acc.at(i) = saturating_doubling_high_mul(acc.at(i) * (1 << (-out_shift)), out_mul) + output_qoffset; + } + else + { + acc.at(i) = rounding_divide_by_exp2(saturating_doubling_high_mul(acc.at(i), out_mul), out_shift) + output_qoffset; + } out_vals[i] = static_cast(utility::clamp(acc.at(i))); } @@ -381,21 +390,20 @@ void depthwise_loop_generic_quantized(const ITensor *input, const ITensor *weigh if(has_biases) { - const auto biases_val = *(reinterpret_cast(biases_it.ptr() + m * sizeof(int32_t))); + acc.at(m) += *(reinterpret_cast(biases_it.ptr() + m * sizeof(int32_t))); + } - int32_t out_val = acc.at(m) + biases_val; - out_val = rounding_divide_by_exp2(saturating_doubling_high_mul(out_val, output_multiplier.at(id.x() + m)), - output_shift.at(id.x() + m)) - + output_qoffset; - *(reinterpret_cast(output_it.ptr() + m * sizeof(T))) = static_cast(utility::clamp(out_val)); + const int out_mul = output_multiplier.at(id.x() + m); + const int out_shift = output_shift.at(id.x() + m); + if(out_shift < 0) + { + acc.at(m) = saturating_doubling_high_mul(acc.at(m) * (1 << (-out_shift)), out_mul) + output_qoffset; } else { - int32_t out_val = rounding_divide_by_exp2(saturating_doubling_high_mul(acc.at(m), output_multiplier.at(id.x() + m)), - output_shift.at(id.x() + m)) - + output_qoffset; - *(reinterpret_cast(output_it.ptr() + m * sizeof(T))) = static_cast(utility::clamp(out_val)); + acc.at(m) = rounding_divide_by_exp2(saturating_doubling_high_mul(acc.at(m), out_mul), out_shift) + output_qoffset; } + *(reinterpret_cast(output_it.ptr() + m * sizeof(T))) = static_cast(utility::clamp(acc.at(m))); } }, input_it, weights_it, biases_it, output_it); @@ -531,8 +539,7 @@ void NEDepthwiseConvolutionLayerNativeKernel::configure(const ITensor *input, co int32_t out_mult = 0; int32_t out_shift = 0; const float multiplier = input_scale * weights_scale.at(i) / output_scale; - ARM_COMPUTE_ERROR_ON(multiplier > 1.f); - arm_compute::quantization::calculate_quantized_multiplier_less_than_one(multiplier, &out_mult, &out_shift); + arm_compute::quantization::calculate_quantized_multiplier(multiplier, &out_mult, &out_shift); _output_multiplier.push_back(out_mult); _output_shift.push_back(out_shift); -- cgit v1.2.1