Repository navigation
Conversation
Signed-off-by: targabor <tar.gabor14@gmail.com>
Author
|
Hi! Just following up on this PR. It's been open for a couple of weeks, and I'd appreciate any feedback when someone has a chance to review it. Happy to make adjustments if needed. Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #4874.
Graph.toposort()orders local functions with a nested helper,get_used_funcs(nodes). The helper looped overself.subgraphs(), which are the subgraphs of the graph being sorted, instead of the subgraphs of thenodesit was given.selfis the same on every recursive call, which caused two bugs:If/Loop/Scan), sorting functions fails withRecursionError. This happens withmode="full"(the default) andmode="functions", from bothGraph.toposort()andFunction.toposort().Fix
Recurse into each node's own subgraphs:
def get_used_funcs(nodes): inputs = {} - for subgraph in self.subgraphs(): - inputs.update(get_used_funcs(subgraph.nodes)) for node in nodes: + for subgraph in node.subgraphs(): + inputs.update(get_used_funcs(subgraph.nodes)) func_id = (node.domain, node.op)Whenever the old loop ran at all, it never terminated, so every graph that sorts successfully today skipped it. For valid graphs, the result only changes when a function uses another function from inside a subgraph.
Behavior change
A cycle between function definitions that goes through a subgraph (for example,
func2callsfunc1in anIfbranch andfunc1callsfunc2) now raisesOnnxGraphSurgeonException: Cycle detected in function definitions!, the same as direct cycles already did. Previously it was missed and the functions were sorted silently. ONNX doesn't allow these models anyway: theModelProto.functionscomment inonnx.protosays "recursive reference is not allowed".Tests
New cases in
tests/ir/test_graph.py::TestToposort:test_function_order_with_subgraph_in_graph[full],[functions]RecursionErrortest_function_toposort_with_subgraph_in_functionRecursionErrortest_function_order_dependency_in_subgraph[full],[functions](dependency only in the else-branch)test_function_order_dependency_in_nested_subgraphtest_function_circular_dep_through_subgraphI also checked that the tests reject incomplete fixes. Removing the loop without the per-node recursion, searching only one nesting level, or searching only a node's first subgraph each make at least one new test fail.
Checked manually as well, not added as tests:
LoopandScanbodiesIfnested 300 levels deeprecurse_subgraphs/recurse_functionscombinationsonnx.checker.check_model(full_check=True)→ onnxruntime inference on a model whose function calls another only inside anIfTesting
Run in
python:3.12-slimwithtests/requirements.txtanddocs/requirements.txtinstalled (onnx 1.20.0, onnxruntime 1.19.2):PYTHONPATH=. python3 -m pytest tests/: 299 passed, 1 skipped before the change; 306 passed, 1 skipped after.sphinx-build docs build/docs -j auto -W(the docs step ofmake test): passes.black --checkon the changed files andgit diff --check: clean.I added a CHANGELOG entry under
vNext→Fixed.