From 64bcff84a4de184a16cc1f58e674a9a6ecd2f9be Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 8 Jan 2021 14:12:39 -0800 Subject: [PATCH] Update NNAPI delegate to be able to handle single input Reshape op PiperOrigin-RevId: 350834072 Change-Id: Ia49996542b9a89e87a6058bfd0155c4b8715c01c --- .../delegates/nnapi/acceleration_test_list.cc | 9 +++--- .../lite/delegates/nnapi/nnapi_delegate.cc | 29 +++++++++++++++++-- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/tensorflow/lite/delegates/nnapi/acceleration_test_list.cc b/tensorflow/lite/delegates/nnapi/acceleration_test_list.cc index 240448799b7..dc84aac5488 100644 --- a/tensorflow/lite/delegates/nnapi/acceleration_test_list.cc +++ b/tensorflow/lite/delegates/nnapi/acceleration_test_list.cc @@ -334,10 +334,11 @@ ConstFloat(Mean|Any)OpTest/KeepDims ConstFloat(Sum|Prod|Max|Min)OpTest/ScalarAxis,29 # reshape_test -# Acceleration would be only for the test with shape being a constant tensor -VariedShapeSpec/ReshapeOpTest/InvalidShape/1 -VariedShapeSpec/ReshapeOpTest/RegularShapes/1 -VariedShapeSpec/ReshapeOpTest/WithStretchDimension/1 +# Acceleration would be only for the test with shape being a constant tensor or +# as hardcoded options. +VariedShapeSpec/ReshapeOpTest/InvalidShape/[01] +VariedShapeSpec/ReshapeOpTest/RegularShapes/[01] +VariedShapeSpec/ReshapeOpTest/WithStretchDimension/[01] # resize_bilinear_test // align_corners & half_pixel_centers are not implemented in NNAPI before API 30 diff --git a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc index 79ff14dc622..23fed266359 100644 --- a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc +++ b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc @@ -1878,15 +1878,26 @@ bool NNAPIDelegateKernel::Validate( case kTfLiteBuiltinReshape: { ExpectOpVersion(version, 1, &val_ctx); ExpectIsFloatOrQuant8Operator(context, node, &val_ctx); - Expect(node->inputs->size >= 2, - NNAPIValidationFailureType::kMissingRequiredOperand, - "Expected at least 2 inputs", &val_ctx); if (node->inputs->size >= 2) { Expect(context->tensors[node->inputs->data[1]].allocation_type == kTfLiteMmapRo, NNAPIValidationFailureType::kInputTensorShouldHaveConstantShape, "The shape input tensor must be constant.", &val_ctx); } + if (node->inputs->size == 1) { + // reject scalar reshaping + auto* params = + reinterpret_cast(node->builtin_data); + int num_dimensions = params->num_dimensions; + if (num_dimensions == 1 && params->shape[0] == 0) { + // Legacy tflite models use a shape parameter of [0] to indicate + // scalars. + num_dimensions = 0; + } + Expect(num_dimensions > 0, + NNAPIValidationFailureType::kUnsupportedOperandRank, + "New shape rank should be > 0", &val_ctx); + } } break; case kTfLiteBuiltinResizeBilinear: { ExpectMaxOpVersion(version, 3, &val_ctx); @@ -2813,6 +2824,18 @@ TfLiteStatus NNAPIDelegateKernel::Map( *nn_op_type = ANEURALNETWORKS_SOFTMAX; } break; case kTfLiteBuiltinReshape: { + if (mapping_args.node->inputs->size == 1) { + // if no new_shape tensor, construct the new shape from params. + auto* params = reinterpret_cast( + mapping_args.node->builtin_data); + int num_dimensions = params->num_dimensions; + std::vector output_shape(num_dimensions); + for (int i = 0; i < num_dimensions; ++i) { + output_shape[i] = params->shape[i]; + } + mapping_args.builder->AddVectorInt32Operand( + output_shape.data(), static_cast(num_dimensions)); + } *nn_op_type = ANEURALNETWORKS_RESHAPE; } break; case kTfLiteBuiltinResizeBilinear: {