From d279ce2f675ac2f99f854c09c7d7fcef2944eff5 Mon Sep 17 00:00:00 2001 From: JiCheng Date: Wed, 4 Jan 2023 20:20:00 +0800 Subject: [PATCH] bug fix, NNAPI filter out un-supported graph (#14040) ### Description "Consttant Folding" need to enhance to support "function" in onnx spec. If those nodes are inlined into sub-graph and captured by a EP, espeicially this EP doesn't support that, error occured. There are many test failure in Onnx 1.13 agaist NNAPI, these are listed bellow; ``` prelu_broadcast_expanded selu_example_expanded_ver18 layer_normalization_2d_axis0 shrink_hard_expanded_ver18 elu_expanded_ver18 softsign_example_expanded_ver18 leakyrelu_example_expanded hardsigmoid_example_expanded_ver18 thresholdedrelu_default_expanded_ver18 split_variable_parts_2d_opset18 efault_expanded prelu_example_expanded thresholdedrelu_example_expanded_ver18 selu_default_expanded_ver18 elu_example_expanded_ver18 hardsigmoid_default_expanded_ver18 softsign_expanded_ver18 hardsigmoid_expanded_ver18 leakyrelu_expanded scatter_with_axis selu_expanded_ver18 shrink_soft_expanded_ver18 relu_expanded_ver18 thresholdedrelu_expanded_ver18 elu_default_expanded_ver18 ``` Solution: To prevent NNAPI capture it for now, we can revert it once a better CF implemented. ### Motivation and Context --- .../nnapi_builtin/nnapi_execution_provider.cc | 23 ++++++++++++++++++- .../core/providers/partitioning_utils.cc | 6 ++--- .../test/providers/nnapi/nnapi_basic_test.cc | 13 +++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.cc b/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.cc index e6ff9ba6fb..11f771d007 100644 --- a/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.cc +++ b/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.cc @@ -175,6 +175,27 @@ NnapiExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_view result = utils::CreateSupportedPartitions(graph_viewer, is_node_supported, on_group_closed, gen_metadef_name, NNAPI, kNnapiExecutionProvider); + // Generally, NNAPI support graph with inputs and outputs except constant initializer. + // So far, we have a few cases that sub-graph has zero inputs, + // a) A sub-graph has only initializer as inputs + // b) A sub-graph has zero inputs + // So we just remove these sub-graph which is captured by NNAPI. + // A existing example is CastLike, as which can't be fold in constant folding pass. + // CastLike Op will be inlined into Cast after Pass transform. + // Can we remove it if support CastLike in CF or support Pass transform after InlineNodes? + std::for_each(result.begin(), result.end(), [&graph_viewer](auto& capability) { + if (capability && capability->sub_graph && capability->sub_graph->GetMetaDef()) { + const auto* meta_def = capability->sub_graph->GetMetaDef(); + bool not_empty_inputs = std::any_of(meta_def->inputs.begin(), meta_def->inputs.end(), [&graph_viewer](const auto& input) { + return !graph_viewer.IsConstantInitializer(input, true); + }); + + if (!not_empty_inputs || meta_def->outputs.empty()) { + capability.reset(); + } + } + }); + const auto num_of_partitions = result.size(); const auto num_of_supported_nodes = std::accumulate( result.begin(), result.end(), size_t{0}, @@ -298,7 +319,7 @@ common::Status NnapiExecutionProvider::Compile(const std::vector(state); const size_t num_inputs = ctx.GetInputCount(); const size_t num_outputs = ctx.GetOutputCount(); diff --git a/onnxruntime/core/providers/partitioning_utils.cc b/onnxruntime/core/providers/partitioning_utils.cc index 85b95bd638..d537a4cf58 100644 --- a/onnxruntime/core/providers/partitioning_utils.cc +++ b/onnxruntime/core/providers/partitioning_utils.cc @@ -96,9 +96,9 @@ std::vector> CreateSupportedPartitionNodeGroups( ORT_ENFORCE(is_node_supported_fn, "Node support test is required."); /* - * NOTE: when making change here PLEASE update the logic that replicates the C++ partitioning in - * /tools/python/util/mobile_helpers/usability_checker.py:check_partitioning - */ + * NOTE: when making change here PLEASE update the logic that replicates the C++ partitioning in + * /tools/python/util/mobile_helpers/usability_checker.py:check_partitioning + */ std::vector> supported_groups{}; // number of inputs from unprocessed nodes (in-degree) per node diff --git a/onnxruntime/test/providers/nnapi/nnapi_basic_test.cc b/onnxruntime/test/providers/nnapi/nnapi_basic_test.cc index dbf71d00b4..106bc632a3 100644 --- a/onnxruntime/test/providers/nnapi/nnapi_basic_test.cc +++ b/onnxruntime/test/providers/nnapi/nnapi_basic_test.cc @@ -16,6 +16,7 @@ #include "test/util/include/inference_session_wrapper.h" #include "test/util/include/test/test_environment.h" #include "test/util/include/test_utils.h" +#include "core/framework/data_types_internal.h" #if !defined(ORT_MINIMAL_BUILD) // if this is a full build we need the provider test utils @@ -504,6 +505,18 @@ TEST(NnapiExecutionProviderTest, TestQDQMatMul) { {ExpectedEPNodeAssignment::All}); } +// zero inputs test +TEST(NnapiExecutionProviderTest, TestCast) { + std::vector input1_shape{1, 2, 3, 4}; + auto build_func = [input1_shape](ModelTestBuilder& builder) { + auto* input_arg = builder.MakeInitializer(input1_shape, -100.f, 100.f); + auto* output_arg = builder.MakeOutput(); + + builder.AddNode("CastLike", {input_arg, input_arg}, {output_arg}); + }; + RunQDQModelTest(build_func, "nnapi_qdq_test_graph_cast", {ExpectedEPNodeAssignment::None}); +} + #endif // !(ORT_MINIMAL_BUILD) TEST(NnapiExecutionProviderTest, NNAPIFlagsTest) {