From 0957e53d4a01d616b7fdffd57ab7ce086e9194cd Mon Sep 17 00:00:00 2001 From: Nat Jeffries Date: Fri, 20 Nov 2020 16:30:24 -0800 Subject: [PATCH] Fix xtensa kernel quantize int16->int32. Increase tolerance for reset frame to 4 in order to manage subtle differences in reset trigger between reference and optimized kernels. PiperOrigin-RevId: 343586545 Change-Id: If290d1eebd0774e8e4966cfaae882f29fbef8a21 --- .../lite/micro/kernels/xtensa/quantize.cc | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/tensorflow/lite/micro/kernels/xtensa/quantize.cc b/tensorflow/lite/micro/kernels/xtensa/quantize.cc index 752bd855430..05646a32ad7 100644 --- a/tensorflow/lite/micro/kernels/xtensa/quantize.cc +++ b/tensorflow/lite/micro/kernels/xtensa/quantize.cc @@ -19,10 +19,12 @@ limitations under the License. #include "tensorflow/lite/c/common.h" #include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/requantize.h" #include "tensorflow/lite/kernels/internal/tensor_ctypes.h" #include "tensorflow/lite/kernels/kernel_util.h" #include "tensorflow/lite/micro/kernels/kernel_util.h" #include "tensorflow/lite/micro/kernels/xtensa/fixedpoint_utils.h" +#include "tensorflow/lite/micro/micro_utils.h" namespace tflite { namespace { @@ -30,6 +32,12 @@ namespace { struct OpData { int32_t zero_point = 0; int scale_multiplier = 0; + + // Use 32-bit multiplier and scale for requantize version of this operator + // to preserve compatibility with reference op. + int32_t requantize_output_multiplier; + int requantize_output_shift; + int32_t input_zero_point = 0; }; void AffineQuantize(int scale_multiplier, const int32_t zero_point, @@ -116,6 +124,12 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { CreateQConstantForInt24(0, input->params.scale / output->params.scale); op_data->zero_point = output->params.zero_point; + op_data->input_zero_point = input->params.zero_point; + + double effective_scale = static_cast(input->params.scale) / + static_cast(output->params.scale); + QuantizeMultiplier(effective_scale, &op_data->requantize_output_multiplier, + &op_data->requantize_output_shift); return kTfLiteOk; } @@ -127,21 +141,25 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0); TfLiteEvalTensor* output = tflite::micro::GetEvalOutput(context, node, 0); - tflite::QuantizationParams op_params; - op_params.zero_point = op_data->zero_point; - - if (input->type != kTfLiteInt16 && output->type != kTfLiteInt8) { + if (output->type == kTfLiteInt8 && input->type == kTfLiteInt16) { + AffineQuantize(op_data->scale_multiplier, op_data->zero_point, + tflite::micro::GetTensorShape(input), + tflite::micro::GetTensorData(input), + tflite::micro::GetTensorShape(output), + tflite::micro::GetTensorData(output)); + } else if (output->type == kTfLiteInt32 && input->type == kTfLiteInt16) { + int size = ElementCount(*input->dims); + reference_ops::Requantize(tflite::micro::GetTensorData(input), + size, op_data->requantize_output_multiplier, + op_data->requantize_output_shift, + op_data->input_zero_point, op_data->zero_point, + tflite::micro::GetTensorData(output)); + } else { TF_LITE_KERNEL_LOG(context, "Input %s, output %s not supported.", TfLiteTypeGetName(input->type), TfLiteTypeGetName(output->type)); return kTfLiteError; } - - AffineQuantize(op_data->scale_multiplier, op_data->zero_point, - tflite::micro::GetTensorShape(input), - tflite::micro::GetTensorData(input), - tflite::micro::GetTensorShape(output), - tflite::micro::GetTensorData(output)); return kTfLiteOk; }