Skip to content
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 O(N^2) algorithm on the number of geometry subsets in Hydra #1170

Merged
merged 3 commits into from
Apr 29, 2020

Conversation

marktucker
Copy link
Contributor

Fix O(N^2) algorithm when displaying a mesh with a very large number of geometry subsets on it. Use a Set instead of a Vector for extraDependencies. This was resulting in extremely long update times in Hydra when asked to display a mesh with 500K geomsubsets in the Moana island scene (ignoring the wisdom of organizing the USD that way).

Description of Change(s)

Replace the use of an SdfPathVector with an SdfPathSet to avoid linear search costs.

geometry subsets on it. Use a Set instead of a Vector for extraDependencies.
@jilliene
Copy link

Filed as internal issue #USD-6004

@spiffmon
Copy link
Member

Thanks, @marktucker ! Given the benefits of coherent memory access and that we don't expect the common case for Subsets to be so meaty, I wonder if it might make sense to try a TfDenseHashSet here?

@spitzak
Copy link

spitzak commented Apr 20, 2020

I think std::set is more space-efficient than hash sets?

@marktucker
Copy link
Contributor Author

I'll give TfDenseHashSet a try, just to validate it gives similar performance characteristics. Related to this, I noticed that extraDependencies is never cleared, and when I remove this prim from the scene, UsdImagingIndexProxy::_RemoveDependencies is getting called for each geom subset, which results in the _dependenciesToRemove vector trying to fill with 500K*500K entries, of which only the first 500K are unique. Should there be a call to primInfo->extraDependencies.clear() at the end of that function?

Alternatively _dependenciesToRemove could be made into a set of some kind, but it would still be doing N^2 insertion tests without the clearing of the extraDependencies, so performance will still be awful (but at least it won't chew up all my RAM)... Any thoughts?

@marktucker
Copy link
Contributor Author

TfDenseHashSet works great as a replacement for std::set. I'm happy to defer to your judgement on balancing performance vs. memory use.

I also tried adding the extraDependencies.clear() call and it made the removal of the 500K subsets very fast, and didn't seem to prevent it from coming back when I re-added it. The extraDependencies were also rebuilt. But I fear that you leave the extraDependencies around for some more complex code path. This comment https://github.com/PixarAnimationStudios/USD/blob/ebac0a8b6703f4fa1c27115f1f013bb9819662f4/pxr/usdImaging/usdImaging/indexProxy.cpp#L158 makes me think there is more going on here?

…speed

of a vector for iterating, but also the fast lookup for existing members.
@spiffmon
Copy link
Member

I think std::set is more space-efficient than hash sets?

That is true, @spitzak , but TfDenseHashSet will be a std::vector until a specified threshold of elements is met. Though there's of course a tuning issue in that threshold, we'd hope that most Mesh's have few enough subsets that they'd stay a vector.

@spiffmon
Copy link
Member

With respect to clearing the dependencies, @marktucker, that's beyond my expertise. Maybe try it with comment and see what the Hydra team says?

TfDenseHashSet works great as a replacement for std::set. I'm happy to defer to your judgement on balancing performance vs. memory use.

I also tried adding the extraDependencies.clear() call and it made the removal of the 500K subsets very fast, and didn't seem to prevent it from coming back when I re-added it. The extraDependencies were also rebuilt. But I fear that you leave the extraDependencies around for some more complex code path. This comment

https://github.com/PixarAnimationStudios/USD/blob/ebac0a8b6703f4fa1c27115f1f013bb9819662f4/pxr/usdImaging/usdImaging/indexProxy.cpp#L158

makes me think there is more going on here?

@spitzak
Copy link

spitzak commented Apr 20, 2020

Sounds good to me

@@ -59,6 +59,7 @@
#include "pxr/base/tf/declarePtrs.h"
#include "pxr/base/tf/hashmap.h"
#include "pxr/base/tf/hashset.h"
#include "pxr/base/tf/denseHashset.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @marktucker, I think that needs to be denseHashSet.h -- capital 'S'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sure does. Unless you're on Windows. Sigh. Fixed.

@c64kernal
Copy link
Contributor

@marktucker with respect to the clearing -- we did run into some issues a while back where uses cases involved in our Presto delegates that handle multiple USD stages at once ran into problems, but that's been a while now and things have changed. I'm wondering if we can try it again. If you'd like to submit it in a different PR, please, I'd be happy to run it through our internal tests and validate it.

@pixar-oss pixar-oss merged commit 66bed6f into PixarAnimationStudios:dev Apr 29, 2020
@marktucker marktucker deleted the dev_extradeps_as_set branch July 22, 2020 07:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants