Allocator (memory control) support for graphs and algorithms #481
Replies: 1 comment
-
|
A common pattern in the std library is to have an allocator as the last parameter with a matching allocator template parameter. For example: A problem when dealing with graphs is that the type we want to allocate isn't available because it's internal and not exposed to the user, or that we want to use it for multiple types. In that case, we can use a common type instead, such as: In the implementation we can then cast the allocator to a new allocator, such as WVAlloc can be used to allocate a Weighted Vertex. The allocator can be applied to all the graph data structures (e.g. adjacency_list), and algorithms that allocate memory (e.g. for stack or queue). |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Stateful allocator support
Story
Three independent users, completely different domains, same root cause:
addy90 abandoned BGL after two years because he needed to load Germany's full OSM road network (~128 GB) using memory-mapped files via Boost.Interprocess. He discovered that
adjacency_listhas no allocator parameter: it uses hardcodednewfor vertex storage and edge properties indetail/adjacency_list.hpp, and thecontainer_genmachinery that maps selectors likevecSto actual containers has no allocator parameter either. He built his own allocator-aware graph from scratch.megyhazy:
pratzl confirmed he has working MMF-backed graphs using Boost.Interprocess, but that code lives in his private products.
jcelerier (OSSIA) comes from the opposite direction: small graphs, real-time audio threads with strict deadlines (2ms for transitive closure, 16ms for cycle detection). For him hidden allocations are not a scalability problem, they are a correctness problem: a malloc in the audio thread causes a glitch or a missed frame. He rewrote BGL algorithms by hand just to extract and control temporary allocations. His verdict:
There are two related but distinct problems here.
The group can decide at the start which one to focus on. The data structure problem is harder and more impactful. The algorithm problem is more approachable in 45 minutes. Both are worth thinking about.
Dream solution
boost::graph::adjacency_listgains anAllocatortemplate parameter (C++14-compatible, defaulted). A Boost.Interprocess-backed graph just works. No rawnewanywhere in the implementation. BFS, DFS, and Dijkstra accept an optional allocator parameter for their internal scratch memory.Starting point
addy90's full writeup in discussion #466
jcelerier's writeup in discussion #466
adjacency_list.hpp
detail/adjacency_list.hpp
Boost.Interprocess allocator docs
Intermediary objective (45 min)
It's a very challenging problem. Any lead, design idea, incomplete thoughts are welcome and valuable.
Option 1: Data structures. Design the missing interface. Write the new
adjacency_listtemplate signature with anAllocatorparameter. Think about where a new allocator-awareadjacency_listshould live to avoid breaking existing users. A modernboost::graph::adjacency_list<...>superseding the oldboost::adjacency_list? Show what construction with a Boost.Interprocess allocator would look like at the call site. Note which internalnewcalls need replacing and with what.Option 2: Algorithms. Write the proposed signature for allocator-aware BFS:
breadth_first_search(g, source, queue, visitor, color_map, alloc). List which other algorithms have the same problem. Rewriting algorithms will be very painful: is there a happy path?That is the design document a contributor needs before touching a single line of code.
Beta Was this translation helpful? Give feedback.
All reactions