-
Notifications
You must be signed in to change notification settings - Fork 111
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
Replace map with unordered_map #484
Conversation
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## master #484 +/- ##
==========================================
+ Coverage 90.31% 90.35% +0.03%
==========================================
Files 35 35
Lines 4389 4396 +7
==========================================
+ Hits 3964 3972 +8
+ Misses 425 424 -1
☔ View full report in Codecov by Sentry. |
Thanks for the perf data! What device are you testing on and which backend are you using? Would you mind adding a comparison with the hash table we already use? #483 (comment) First, because I'd like to benchmark its performance anyway, and second, because it'd be nice to use the same hash table everywhere if we find a favorite. |
I made another branch to test. Device is MacBookAir M1, backend is TBB but it doesn't matter since the two sections of the code I changed are both serial.
For now a simple Not sure if I understand how hashtable.h is working but it's not a drop-in replacement to map/unordered_map. |
Indeed, given the high likelihood of degree-6 verts, I think your vector of vectors approach makes a lot of sense. I'm reading about the small vector lib, but I don't quite understand why it's an improvement over a std::vector? If std::vector gives about the same perf, let's just use that (I figure the compilers have lots of experience optimizing std::vector). |
I think those small vector libraries usually flatten the vector and perform some small size optimizations, so to reduce the number of pointer chasing when accessing an element (at the expense of more expensive move etc.). I thought I modified map with unordered_map a few months ago but it seems that this is reintroduced for other parts of the code, have to say that the naming of std::map is unfortunate... It seems to me that using vector of vectors make sense in this case. I just got back home and is now dealing with jet lag, will look at it in more details tmr. |
930925e
to
4d1e82b
Compare
It's not a compiler thing but purely a malloc thing. There's a slight gain with svo, but I'm fine with std::vector<std::vector though!
Fyi
For I updated the PR. If you want svector, just tell me and I'll update it. |
577413f
to
8e35908
Compare
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.
Looks good to me! I think the gain from svector is pretty small, so it may not be worth it to introduce new dependency unless we can find cases in which the gain is very significant. The current performance with nested vector looks pretty good already.
This looks significant. How moch perf gains are we looking here? |
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.
Excellent, thank you for a significant speed up when handling properties! And also for not introducing an extra dependency. One fix and I think it's ready.
if (oldNumProp > 0) { | ||
std::get<1>(key) = vert; |
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.
These lines are something I just changed in #480 that I think we want to keep. The fact the tests still pass implies I need to add a test. This is to keep extra properties from being created when a mesh without properties is attached a mesh with properties.
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.
Ok but maybe I'll need to revert to hashmap for manifold.cpp
as it breaks most assumptions.
I'll check.
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.
One way would be to use plain array for small size hashmap and hashmap for larger size.
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.
It's fine, I can still use the std::vector<std::vector
approach.
I made the previous assumption that one prop could belong to only 1 logical vertex but it's not the case (although gets flattened in the end).
Seems pretty large when your mesh uses UV mapping. |
To clarify, it's not necassirly UV, but simply the presence of extra properties ( And yes the difference is big, to sum up:
The manifold creation itself takes 780ms (prop=3) 850ms (prop>3). |
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.
Looks great, thanks!
src/manifold/src/boolean_result.cpp
Outdated
using Entry = std::pair<glm::ivec3, int>; | ||
int idMissProp = outR.NumVert(); | ||
std::vector<std::vector<Entry>> propIdx(outR.NumVert() + 1); | ||
outR.meshRelation_.properties.reserve(outR.NumVert() * numProp * 1.1); |
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.
What is * 1.1
for?
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.
I've removed it.
Replace map usage with vector
Context: #483
Case study: subtract a 150k verts mesh on a 1.5M verts one (with UVs).
The edge map is one of the bottleneck when doing boolean on high poly.
Total time of
GetMeshGL()
:phmap is header-only and from https://github.com/greg7mdp/parallel-hashmap.
For now I didn't include it, but the performance is not negligeable.
Should I do it? (git submodule? just copying the include directory?)