-
Notifications
You must be signed in to change notification settings - Fork 352
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
Fix performance issues with graph edge iteration in ShaderGraph #2023
base: main
Are you sure you want to change the base?
Fix performance issues with graph edge iteration in ShaderGraph #2023
Conversation
322ab92
to
e8c8ccf
Compare
This is a really interesting proposal, @nadult, and my main concern is that we'd have two subtly different approaches for traversing graphs in MaterialX, each of which would need to be maintained, validated, and extended in the future. Perhaps it would actually be better to upgrade the This would still allow the addition of a top-level |
OK, makes sense. I will try to prepare a new solution this week with your suggestions included. |
For this, I think it would be useful to have the traversal API have 2 extensions:
Item (1) I think is useful to preserve as an integration may iterate and want to perform some action during traversal, including extracting out additional information which may be hard to get afterwards since not all information during traversal is cached on an edge. Of course I only looked at the changes briefly, so just my initial thoughts. Thoughts on this ? Thanks. |
e8c8ccf
to
7f044fe
Compare
I updated the solution in the following way:
|
7f044fe
to
93a7bfe
Compare
Here is an example of a complex material, for which this PR makes a big difference: slow_material.zip |
In complex materials graph and shader graph edge iteration can be extremely slow, because some edges may be visited many times unnecessarily. This is especially noticable in two functions: ShaderGraph::addUpstreamDependencies and ShaderGraph::optimize() . GraphIterator and ShaderGraphEdgeIterator classes iterate over DAGs without marking nodes as visited, which may lead to exponential traversal time for some DAGs: https://stackoverflow.com/a/69326676 This patch adds an option to skip visited edges in GraphIterator and modifies ShaderGraphEdgeIterator so that each edge is visited only once.
93a7bfe
to
47f9bea
Compare
@nadult From a first read, this looks really promising, and thanks for the example material! We would certainly benefit from test suite examples that are focused on loading/traversal performance (rather than render performance), and it seems worthwhile to consider a contribution along these lines in a future PR. |
The performance improvements here are really impressive! This looks good to me. |
|
@kwokcb OK, I will try to do what you suggest on Monday. |
@kwokcb I'd recommend leaving new test suite examples to a follow-up PR, as we'll want to spend some real time in designing and validating those new examples. Similarly, let's make sure we have exactly the right API before moving forward with Python bindings, and I would recommend omitting new JavaScript bindings until they're needed in a concrete application. It's always easier to add new bindings than it is to modify or remove existing ones. |
This looks like a great improvement, @nadult, and at this point I believe we're just making sure that all of the new naming conventions and flags are set up in a forward-looking way. I'll plan to take a closer look at this soon, and our goal would be to merge this change for MaterialX 1.39.2. |
In complex materials graph and shader graph edge iteration can be extremely slow, because some edges may be visited unnecessarily multiple times. This is especially noticable in two functions: ShaderGraph::addUpstreamDependencies and ShaderGraph::optimize() .
GraphIterator and ShaderGraphEdgeIterator classes iterate over DAGs without marking nodes as visited, which may lead to exponential traversal time for some DAGs: https://stackoverflow.com/a/69326676
This patch adds two functions which efficiently generate a unique list of (shader) graph edges and uses those lists instead of graph iterators.
For one especially complex material on which I tested this fix, shader code generation time decreased from 156.13 sec to 0.08 sec (almost 2000x speedup). Number of visited edges in ShaderGraph::optimize() decreased from 42M to ~600.
I'm not sure if the best approach is to add those two functions next to current graph iterators or maybe those iterators should be replaced altogether. Another solution which I see would be to fix the graph iterators, but IMO they add a lot of overhead and it's faster to simply use a function which returns a list of all edges in a given graph in std::vector.