-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Fix outer scope initializer type checking by using IsOuterScopeValue #25068
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: justinchuby <11205048+justinchuby@users.noreply.github.com>
What about outer_scope_node_arg_names_? Where is it used now? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can commit the suggested changes from lintrunner.
// during type inference, even without explicit value_info in the subgraph | ||
|
||
// Create parent graph with initializer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// during type inference, even without explicit value_info in the subgraph | |
// Create parent graph with initializer | |
// during type inference, even without explicit value_info in the subgraph | |
// Create parent graph with initializer |
tensor_proto.add_float_data(42.0f); | ||
|
||
parent_graph.AddInitializedTensor(tensor_proto); | ||
|
||
// Create a node in parent graph that will be the parent node for the subgraph |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tensor_proto.add_float_data(42.0f); | |
parent_graph.AddInitializedTensor(tensor_proto); | |
// Create a node in parent graph that will be the parent node for the subgraph | |
tensor_proto.add_float_data(42.0f); | |
parent_graph.AddInitializedTensor(tensor_proto); | |
// Create a node in parent graph that will be the parent node for the subgraph |
auto& condition_arg = parent_graph.GetOrCreateNodeArg("condition", &tensor_type); | ||
|
||
tensor_type.mutable_tensor_type()->set_elem_type(TensorProto_DataType_FLOAT); | ||
auto& output_arg = parent_graph.GetOrCreateNodeArg("output", &tensor_type); | ||
|
||
NodeArg* inputs[] = {&condition_arg}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto& condition_arg = parent_graph.GetOrCreateNodeArg("condition", &tensor_type); | |
tensor_type.mutable_tensor_type()->set_elem_type(TensorProto_DataType_FLOAT); | |
auto& output_arg = parent_graph.GetOrCreateNodeArg("output", &tensor_type); | |
NodeArg* inputs[] = {&condition_arg}; | |
auto& condition_arg = parent_graph.GetOrCreateNodeArg("condition", &tensor_type); | |
tensor_type.mutable_tensor_type()->set_elem_type(TensorProto_DataType_FLOAT); | |
auto& output_arg = parent_graph.GetOrCreateNodeArg("output", &tensor_type); | |
NodeArg* inputs[] = {&condition_arg}; |
auto& parent_node = parent_graph.AddNode("if_node", "If", "test if node", inputs, outputs); | ||
|
||
// Create subgraph |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto& parent_node = parent_graph.AddNode("if_node", "If", "test if node", inputs, outputs); | |
// Create subgraph | |
auto& parent_node = parent_graph.AddNode("if_node", "If", "test if node", inputs, outputs); | |
// Create subgraph |
subgraph_proto.set_name("TestSubgraph"); | ||
Graph subgraph(parent_model, &subgraph_proto, parent_graph.DomainToVersionMap(), | ||
parent_model.IrVersion(), nullptr, &parent_graph, &parent_node, | ||
DefaultLoggingManager().DefaultLogger(), false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
subgraph_proto.set_name("TestSubgraph"); | |
Graph subgraph(parent_model, &subgraph_proto, parent_graph.DomainToVersionMap(), | |
parent_model.IrVersion(), nullptr, &parent_graph, &parent_node, | |
DefaultLoggingManager().DefaultLogger(), false); | |
subgraph_proto.set_name("TestSubgraph"); | |
Graph subgraph(parent_model, &subgraph_proto, parent_graph.DomainToVersionMap(), | |
parent_model.IrVersion(), nullptr, &parent_graph, &parent_node, | |
DefaultLoggingManager().DefaultLogger(), false); |
auto& subgraph_output = subgraph.GetOrCreateNodeArg("subgraph_out", &tensor_type); | ||
|
||
NodeArg* sub_inputs[] = {&outer_init_nodearg}; | ||
NodeArg* sub_outputs[] = {&subgraph_output}; | ||
|
||
// Create an Identity node that uses the outer scope initializer | ||
auto& sub_node = subgraph.AddNode("identity_node", "Identity", "uses outer scope init", | ||
sub_inputs, sub_outputs); | ||
|
||
// Set the subgraph as an attribute of the parent node |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto& subgraph_output = subgraph.GetOrCreateNodeArg("subgraph_out", &tensor_type); | |
NodeArg* sub_inputs[] = {&outer_init_nodearg}; | |
NodeArg* sub_outputs[] = {&subgraph_output}; | |
// Create an Identity node that uses the outer scope initializer | |
auto& sub_node = subgraph.AddNode("identity_node", "Identity", "uses outer scope init", | |
sub_inputs, sub_outputs); | |
// Set the subgraph as an attribute of the parent node | |
auto& subgraph_output = subgraph.GetOrCreateNodeArg("subgraph_out", &tensor_type); | |
NodeArg* sub_inputs[] = {&outer_init_nodearg}; | |
NodeArg* sub_outputs[] = {&subgraph_output}; | |
// Create an Identity node that uses the outer scope initializer | |
auto& sub_node = subgraph.AddNode("identity_node", "Identity", "uses outer scope init", | |
sub_inputs, sub_outputs); | |
// Set the subgraph as an attribute of the parent node |
subgraph_proto.add_output()->set_name("subgraph_out"); | ||
|
||
parent_node.AddAttribute("then_branch", subgraph_proto); | ||
parent_node.AddAttribute("else_branch", subgraph_proto); // Same for simplicity | ||
|
||
// Add the initializer name to the parent node's implicit input defs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
subgraph_proto.add_output()->set_name("subgraph_out"); | |
parent_node.AddAttribute("then_branch", subgraph_proto); | |
parent_node.AddAttribute("else_branch", subgraph_proto); // Same for simplicity | |
// Add the initializer name to the parent node's implicit input defs | |
subgraph_proto.add_output()->set_name("subgraph_out"); | |
parent_node.AddAttribute("then_branch", subgraph_proto); | |
parent_node.AddAttribute("else_branch", subgraph_proto); // Same for simplicity | |
// Add the initializer name to the parent node's implicit input defs |
} | ||
|
||
// With the fix, this should NOT fail with "does not have type information set by parent node" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | |
// With the fix, this should NOT fail with "does not have type information set by parent node" | |
} | |
// With the fix, this should NOT fail with "does not have type information set by parent node" |
onnxruntime/test/ir/graph_test.cc
Outdated
|
||
// Set the subgraph as an attribute of the parent node | ||
subgraph_proto.set_name("then_branch"); | ||
*(subgraph_proto.add_node()) = sub_node.ToProto(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error: D:\a_work\onnxruntime\onnxruntime\onnxruntime\test\ir\graph_test.cc(2295,43): error C2660: 'onnxruntime::Node::ToProto': function does not take 0 arguments [D:\a_work_temp\build\RelWithDebInfo\onnxruntime_test_all.vcxproj]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed the compilation error in commit eb7fa32. The ToProto method requires a NodeProto reference parameter, so I've updated the test to create a NodeProto object and pass it to ToProto.
Co-authored-by: justinchuby <11205048+justinchuby@users.noreply.github.com>
The
My change only replaced its usage in the type inference lambda (line 2825) with |
Problem
When a subgraph references an initializer defined in an outer graph without having a corresponding
value_info
entry in the subgraph, ONNX Runtime incorrectly raises the error:This occurs because the
is_outer_scope_nodearg
lambda inInferAndVerifyTypeMatch
only checks the manually populatedouter_scope_node_arg_names_
set, which misses initializers from outer graphs that weren't explicitly added viaAddOuterScopeNodeArg()
.Root Cause
The issue is in
onnxruntime/core/graph/graph.cc
at lines 2824-2826:This implementation only checks a manually maintained set, but doesn't properly detect initializers that exist in parent graphs.
Solution
Replace the manual check with the existing
resolve_context_.IsOuterScopeValue()
method, which properly traverses the parent graph hierarchy to check if a name corresponds to an input, initializer, or output in any ancestor graph:The
IsOuterScopeValue
method already exists and correctly handles this scenario by recursively callingIsInputInitializerOrOutput
on parent graphs.Testing
Added a test case
OuterScopeInitializerTypeInference
that verifies:value_info
entry is required in the subgraphThe fix has been verified to compile successfully and doesn't break existing functionality.
Fixes #24880.
💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.