-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Undesirable heap allocations in MultibodyPlant #13186
Comments
Thanks for pointing these out, @edrumwri! Some questions:
|
The colorful lines of code (tree functions) are a distraction. Look at the method names after the bullet points (plant functions). Those plant function do not offer user-supplied storage, and the entry points that we actually care about. (In particular, GetKinematicPathToWorld is called internally by MbT, not by the user.) |
Per discussion with @jwnimmer-tri over slack, the key point that I neglected to mention is the typical workflow for real-time programming where one first goes through a "warm up" period where heap can be allocated at will. Afterwards, a real-time phase is entered where no further heap allocations are allowed. The caching system naturally supports this workflow systems if the cache allocates the memory once and the cache evaluation function doesn't allocate any new memory (@ggould-tri has pointed out concerns with using the caching system in a real-time context; we're still proceeding under the assumption that we can use caching, carefully, to avoid unwanted heap allocations).
I don't think API changes are necessary as long as the caching system is used for maintaining those std::vector objects. In any case, our primary concern isn't cost, but deterministic computation times, and memory allocation (among other OS services) is typically not deterministic. |
Ah, yes for the first case the guilty code is here, where that output argument is allocated. |
cc @mitiguy |
Issue #13186 was filed on MBP doing "undesirable heap allocation" by @edrumwri who was also the requester of issue #12592 for the new moving-frame bias acceleration feature (related issue #13453). Heap allocation in CalcBiasSpatialAcceleration() caused concern -- is the new method useful for Evan's application without caching? From email correspondence with Evan (June 16, 2020): "I can wait for the heap allocation to be eliminated at a later date. We're unable to use Drake in a real-time application until all of the heap allocations in MBP have been eliminated: adding a new heap allocation does not make the problem any better, but neither does it make it considerably worse." |
Not sure I agree with that -- the changes in #13453 double the number of heap allocations in MBP. |
Turns out there are many other heap allocations in the MultibodyPlant computations. We are tracking those now with the instrumented cassie_benchmark and work is in progress to remove them. |
This issue does not seem specific enough to be actionable. There are hundreds of public functions on MbP (and more if you count the supporting public classes like Body, Joint, etc.). What list of functions in particular need to be heap-sensitive? Without a list of functions to tackle (i.e., to write LimitMalloc test cases for), there is no way to move forward here and we should close out the issue. Is the implication of Sherm's comment above that the only relevant functions are the non-autodiff cassie tests? Which is to say, fixing the 3 heap ops in |
WDYT @edrumwri ? |
I think we can discount the parts of the forward dynamics stepping scheme- there is little hope that methods that compute contact forces can be made real-time safe, at least in general, so it doesn't make sense to chase down heap allocs there. But pretty much everything else in MBP*- query functions, slicing functions (i.e., get parts of an array), forward kinematics, inverse dynamics- should be able to avoid heap allocations / be made to be real time safe. I've viewed removing heap allocs as a win for both real time safety and performance. If there is not interest in maintaining no-heap-allocs on the MBP side (we've been blessed with few heap allocs in the systems framework), we can always move the MBP accesses to a non-real time thread on our end. But it would be a shame to have to do so.
|
For my part I think it's a useful enough goal. We just need to understand what's desired.
That's at least a start for setting a goal here. I suppose the next actionable step would be for someone to try to turn that general idea into a list of specific function names to repair. Here's an approximate tally of all functions in scope (based on the pybind coverage report).
We need to cut down that list of ~800 functions into the subset which needs to be heapless. (Some of those 800 are probably obviously irrelevant, e.g., constructors and destructors, etc.) If you want to propose a few dozen that are more important that the rest, we can look into fixing those first. |
If you could give us a short list (say 3 to 5) methods you'd like us to work on first @edrumwri, that'd help a lot. |
Will do. |
@edrumwri is this issue still relevant? My thought is to close it now and open more-specific heap issues as they crop up. |
Still highly relevant. Our engineering cycles have been focused elsewhere, but I'll be able to get you a list of functions this quarter. |
I think that our remaining heap allocations are limited to CalcInverseDynamics(). It looks like the heap allocations are due to some temporary storage in MultibodyTree::CalcInverseDynamics(), as well as it returning a VectorX, rather than allowing an output vector to be passed in. |
Update on this: we hadn't exercised all code paths. We're also seeing heap allocations in some Jacobian functions as well. The author (@mitiguy) is aware of two: drake/multibody/tree/multibody_tree.cc Line 2497 in b6d7485
and: drake/multibody/tree/multibody_tree.cc Line 2183 in b6d7485
We're seeing another here that is not just a heap allocation, but seemingly pretty inefficient as well (why wouldn't calculating the kinematic path to the world take constant time?): drake/multibody/tree/multibody_tree.cc Line 2656 in b6d7485
Another (seems pretty simple to address): drake/multibody/tree/multibody_tree.cc Line 2166 in b6d7485
Another: drake/multibody/tree/multibody_tree.cc Line 2599 in b6d7485
Last one: drake/multibody/tree/multibody_tree.cc Line 1737 in b6d7485
|
We welcome any pull requests from users to fix these kind of problems that they care about. For now, the Drake team doesn't plan to make any changes ourselves here. |
Heap allocations make computational run times nondeterministic and should be avoided, if possible to permit real-time applications. In some cases, the heap allocations identified below are likely reducing performance in non-real-time applications as well.
drake/multibody/tree/multibody_tree_topology.h
Line 920 in 00e1d5e
drake/multibody/tree/multibody_tree.cc
Line 1618 in 00e1d5e
drake/multibody/tree/multibody_tree.cc
Line 740 in 00e1d5e
I expect this list will grow over time.
The text was updated successfully, but these errors were encountered: