diff --git a/onnxruntime/core/providers/coreml/builders/helper.cc b/onnxruntime/core/providers/coreml/builders/helper.cc index a2b88f5008..4ddd2f94c1 100644 --- a/onnxruntime/core/providers/coreml/builders/helper.cc +++ b/onnxruntime/core/providers/coreml/builders/helper.cc @@ -69,7 +69,7 @@ bool IsInputSupported(const NodeArg& input, const std::string& parent_name, cons for (const auto& dim : shape_proto->dim()) { // For now we do not support dynamic shape if (!dim.has_dim_value()) { - LOGS(logger, WARNING) << "Dynamic shape is not supported yet, for input:" << input_name; + LOGS(logger, WARNING) << "Dynamic shape is not supported for now, for input:" << input_name; return false; } @@ -87,19 +87,19 @@ bool IsInputSupported(const NodeArg& input, const std::string& parent_name, cons } std::vector> GetSupportedNodes(const GraphViewer& graph_viewer, const logging::Logger& logger) { - std::vector> supported_node_vecs; + std::vector> supported_node_groups; if (!util::HasRequiredBaseOS()) { LOGS(logger, WARNING) << "All ops will fallback to CPU EP, because we do not have supported OS"; - return supported_node_vecs; + return supported_node_groups; } for (const auto* input : graph_viewer.GetInputs()) { if (!IsInputSupported(*input, "graph", logger)) { - return supported_node_vecs; + return supported_node_groups; } } - std::vector supported_node_vec; + std::vector supported_node_group; const auto& node_indices = graph_viewer.GetNodesInTopologicalOrder(); for (size_t i = 0; i < node_indices.size(); i++) { auto node_idx = node_indices[i]; @@ -111,20 +111,20 @@ std::vector> GetSupportedNodes(const GraphViewer& graph_v << "] supported: [" << supported << "]"; if (supported) { - supported_node_vec.push_back(node_idx); + supported_node_group.push_back(node_idx); } else { - if (!supported_node_vec.empty()) { - supported_node_vecs.push_back(supported_node_vec); - supported_node_vec.clear(); + if (!supported_node_group.empty()) { + supported_node_groups.push_back(supported_node_group); + supported_node_group.clear(); } } } - if (!supported_node_vec.empty()) { - supported_node_vecs.push_back(supported_node_vec); + if (!supported_node_group.empty()) { + supported_node_groups.push_back(supported_node_group); } - return supported_node_vecs; + return supported_node_groups; } bool HasNeuralEngine(const logging::Logger& logger) { diff --git a/onnxruntime/core/providers/coreml/coreml_execution_provider.cc b/onnxruntime/core/providers/coreml/coreml_execution_provider.cc index 8da522e3c3..dcc7a05716 100644 --- a/onnxruntime/core/providers/coreml/coreml_execution_provider.cc +++ b/onnxruntime/core/providers/coreml/coreml_execution_provider.cc @@ -163,10 +163,19 @@ CoreMLExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_vie result.push_back(std::make_unique(std::move(sub_graph))); } - LOGS(logger, INFO) << "CoreMLExecutionProvider::GetCapability," - << " number of partitions supported by CoreML: " << result.size() - << " number of nodes in the graph: " << graph_viewer.NumberOfNodes() - << " number of nodes supported by CoreML: " << num_of_supported_nodes; + auto num_of_partitions = result.size(); + const auto summary_msg = MakeString( + "CoreMLExecutionProvider::GetCapability,", + " number of partitions supported by CoreML: ", num_of_partitions, + " number of nodes in the graph: ", graph_viewer.NumberOfNodes(), + " number of nodes supported by CoreML: ", num_of_supported_nodes); + + // If the graph is partitioned in multiple subgraphs, and this may impact performance, + // we want to give users a summary message at warning level. + if (num_of_partitions > 1) + LOGS_DEFAULT(WARNING) << summary_msg; + else + LOGS_DEFAULT(INFO) << summary_msg; return result; } diff --git a/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/helper.cc b/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/helper.cc index e92ab4bf4f..2aa753f52f 100644 --- a/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/helper.cc +++ b/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/helper.cc @@ -483,6 +483,27 @@ bool IsNodeSupportedInternal(const Node& node, const GraphViewer& graph_viewer, return true; } +bool IsInputSupported(const NodeArg& input, const std::string& parent_name) { + const auto& input_name = input.Name(); + const auto* shape_proto = input.Shape(); + // We do not support input with no shape + if (!shape_proto) { + LOGS_DEFAULT(VERBOSE) << "Input [" << input_name << "] of [" << parent_name + << "] has not shape"; + return false; + } + + for (const auto& dim : shape_proto->dim()) { + // For now we do not support dynamic shape + if (!dim.has_dim_value()) { + LOGS_DEFAULT(WARNING) << "Dynamic shape is not supported for now, for input:" << input_name; + return false; + } + } + + return true; +} + std::vector> GetSupportedNodes(const GraphViewer& graph_viewer, const OpSupportCheckParams& params) { std::vector> supported_node_groups; if (params.android_sdk_ver < ORT_NNAPI_MIN_API_LEVEL) { @@ -492,6 +513,13 @@ std::vector> GetSupportedNodes(const GraphViewer& graph_view return supported_node_groups; } + // Disable NNAPI if the graph has input with dynamic shape + for (const auto* input : graph_viewer.GetInputs()) { + if (!IsInputSupported(*input, "graph")) { + return supported_node_groups; + } + } + // This holds the supported node's topological index std::vector supported_node_group; // This holds the NodeIndex of the nodes in the above group 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 2260a04ddb..92a42a2beb 100644 --- a/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.cc +++ b/onnxruntime/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.cc @@ -196,10 +196,19 @@ NnapiExecutionProvider::GetCapability(const onnxruntime::GraphViewer& graph_view result.push_back(std::make_unique(std::move(sub_graph))); } - LOGS_DEFAULT(INFO) << "NnapiExecutionProvider::GetCapability," - << " number of partitions supported by NNAPI: " << result.size() - << " number of nodes in the graph: " << graph_view.NumberOfNodes() - << " number of nodes supported by NNAPI: " << num_of_supported_nodes; + auto num_of_partitions = result.size(); + const auto summary_msg = MakeString( + "NnapiExecutionProvider::GetCapability,", + " number of partitions supported by NNAPI: ", num_of_partitions, + " number of nodes in the graph: ", graph_view.NumberOfNodes(), + " number of nodes supported by NNAPI: ", num_of_supported_nodes); + + // If the graph is partitioned in multiple subgraphs, and this may impact performance, + // we want to give users a summary message at warning level. + if (num_of_partitions > 1) + LOGS_DEFAULT(WARNING) << summary_msg; + else + LOGS_DEFAULT(INFO) << summary_msg; return result; }