diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index d671e21991..f5c5209b5c 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -987,6 +987,9 @@ class Graph { // NodeArgs that come from outer scope. Used when building a graph so that // these don't get recorded as graph inputs in the GraphProto. std::unordered_set outer_scope_node_arg_names_; + + // number of times Resolve has run. + int num_resolves_ = 0; }; } // namespace onnxruntime diff --git a/onnxruntime/core/framework/session_state_initializer.cc b/onnxruntime/core/framework/session_state_initializer.cc index 3911af9bda..3f4777d860 100644 --- a/onnxruntime/core/framework/session_state_initializer.cc +++ b/onnxruntime/core/framework/session_state_initializer.cc @@ -418,9 +418,10 @@ common::Status SaveInputOutputNamesToNodeMapping(const onnxruntime::Graph& graph for (const auto& graph_input : graph_inputs) { const auto& name = graph_input->Name(); if (input_map.find(name) == end_map) { - // dummy entry for an input that we didn't find a use of in the graph. warn about it in case that's a bug. + // dummy entry for an input that we didn't find a use of in the graph. log it in case that's a bug. // utils::CopyOneInputAcrossDevices will use the input OrtValue as is given we don't believe it's used anywhere. - LOGS(session_state.Logger(), WARNING) << "Graph input with name " << name << " is not associated with a node. "; + LOGS(session_state.Logger(), INFO) << (graph.IsSubgraph() ? "Subgraph" : "Graph") << " input with name " + << name << " is not used by any node."; ORT_RETURN_IF_ERROR(session_state.AddInputNameToNodeInfoMapping(name, empty_node_info)); } } diff --git a/onnxruntime/core/graph/graph.cc b/onnxruntime/core/graph/graph.cc index af46870030..217f04fe22 100644 --- a/onnxruntime/core/graph/graph.cc +++ b/onnxruntime/core/graph/graph.cc @@ -1330,6 +1330,7 @@ Status Graph::InferAndVerifySubgraphTypes(const Node& node, Graph& subgraph, " inputs and requires ", num_required_subgraph_inputs, " inputs. Either provide all subgraph inputs, or just the required inputs."); } + subgraph_inputs = &required_subgraph_inputs; num_subgraph_inputs = num_required_subgraph_inputs; } @@ -1879,6 +1880,8 @@ Status Graph::Resolve(bool no_proto_sync_required) { ORT_RETURN_IF_ERROR(ForThisAndAllSubgraphs(all_subgraphs, finalize_func)); + ++num_resolves_; + return Status::OK(); } @@ -2233,7 +2236,16 @@ void Graph::CleanUnusedInitializers() { for (const auto& pv : name_to_initial_tensor_) { const std::string& name = pv.first; if (used_args.find(name) == end) { - LOGS_DEFAULT(WARNING) << name << " exists in this graph's initializers but it is not used by any node"; + // on the first call to Graph::Resolve we are removing unnecessary initializers that should be removed + // from the model. + // on later calls we are removing initializers that optimizations have made redundant. + if (num_resolves_ == 0) { + LOGS_DEFAULT(WARNING) << "Removing initializer '" + << name << "'. It is not used by any node and should be removed from the model."; + } else { + LOGS_DEFAULT(INFO) << "Removing initializer '" << name << "'. It is no longer used by any node."; + } + erase_list.push_back(name); } }