Skip to content

feat(concurrent): Implement ConcurrentDynamicVamana orchestrator and associated tests - #413

Open
rfsaliev wants to merge 8 commits into
mainfrom
rfsaliev/concurrent-orchestrator
Open

rfsaliev wants to merge 8 commits into
mainfrom
rfsaliev/concurrent-orchestrator

Conversation

@rfsaliev

@rfsaliev rfsaliev commented Oct 6, 2026

Copy link
Copy Markdown
Member

This pull request introduces significant improvements to the concurrent dynamic Vamana index, focusing on allocator flexibility, type safety, and enhanced assembly and construction options. The changes make it easier to use custom allocators for graph storage, provide robust mechanisms for assembling indices from existing data, and improve the underlying type traits and loading mechanisms to ensure correctness and extensibility.

Key changes include:

Allocator and Storage Flexibility

  • SimpleBlockedGraph is now templated on its allocator type, allowing users to specify custom allocators instead of being limited to HugepageAllocator. All loading and construction methods in SimpleBlockedGraph now accept an allocator parameter, making it easier to control memory management.
  • The graph's reverse-edge storage now uses a conditional allocator: it attempts to use the graph's base allocator if possible, otherwise falls back to std::allocator. This is determined by a new reverse_edges_rebindable_v trait. [1] [2] [3]

Type Traits and Compile-Time Safety

  • Added the is_segmented_blocked_v trait to detect at compile-time whether an allocator or dataset uses segmented blocked storage, ensuring that only compatible types are used with the concurrent index.

Index Construction and Assembly

  • Introduced a new auto_dynamic_build function that builds a concurrent dynamic Vamana index using grow-stable (segmented blocked) storage for both data and graph, enforcing allocator compatibility at compile time.
  • Added a new constructor to MutableVamanaIndex that assembles an index from arbitrary data, graph, status, and ID translator, with robust precondition checks to ensure consistency and correctness.

API Improvements and Documentation

  • Exposed new methods in MutableVamanaIndex for accessing the ID translator and obtaining a snapshot of slot statuses, improving observability and debugging.
  • Updated the documentation (README.md) to describe the new type-erased wrapper and allocator selection mechanisms for concurrent dynamic Vamana.

These changes collectively make the concurrent dynamic Vamana index more flexible, safer, and easier to use in a variety of memory management scenarios.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Assembly can accept relocation-prone graph storage, and allocator detection and constructor overload resolution have compile-time defects.

Review effort: Balanced
Findings: 3 High severity · 1 Low severity

Open (4)
What changed in this PR

Adds the type-erased concurrent dynamic Vamana orchestrator with allocator-aware graph storage, assembly support, and integration tests.

Changes:

  • Adds concurrent build, mutation, iteration, persistence, and concurrency APIs/tests.
  • Generalizes blocked graph allocators and reverse-edge allocation.
  • Adds segmented-storage traits and state-based index assembly.
File Description
tests/​svs/​orchestrators/​concurrent_dynamic_vamana.cpp Adds orchestrator integration tests.
tests/​CMakeLists.txt Registers the new tests.
include/​svs/​orchestrators/​vamana_iterator.h Selects index-specific iterator types.
include/​svs/​orchestrators/​concurrent_dynamic_vamana.h Adds the concurrent type-erased wrapper.
include/​svs/​concurrent/​README.md Documents allocator and wrapper APIs.
include/​svs/​concurrent/​graph.h Adds allocator-flexible blocked graphs.
include/​svs/​concurrent/​dynamic_index.h Adds allocator-aware build and state assembly.
include/​svs/​concurrent/​blocked_data.h Adds segmented allocator detection.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread include/svs/concurrent/dynamic_index.h Outdated
Comment thread include/svs/concurrent/graph.h
Comment thread include/svs/orchestrators/concurrent_dynamic_vamana.h Outdated
Comment thread include/svs/concurrent/dynamic_index.h

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Allocator selection, translator validation, and iterator factory handling contain unresolved correctness and performance issues.

Review effort: Balanced
Findings: 1 High severity · 3 Medium severity

Open (4)
Resolved since last review (3)

Comment thread include/svs/concurrent/dynamic_index.h
Comment thread include/svs/concurrent/graph.h
Comment thread include/svs/orchestrators/vamana_iterator.h

@ahuber21 ahuber21 left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am worried about drift between sequential and concurrent code and I'm wondering why we can't pick the same approach as in #380. I have a suggestion below. Let's discuss why it's not the right choice:

Suggestion: pass the graph allocator the way #380 does for the sequential index. In #380 the sequential auto_dynamic_build builds the graph and hands it to a ready-graph build constructor. Here the same capability comes in a second way: an allocator overload of the build constructor, a std::monostate sentinel, and make_graph. Mirroring the sequential shape would:

  • leave the existing build constructor exactly as it is on `main;
  • drop the requires clause, so the nullptr logger problem Copilot raised goes away;
  • allocate the graph once on the allocator path instead of twice.

I tried it locally to check that it holds. auto_dynamic_build becomes:

auto verified_parameters = parameters;
verify_and_set_default_index_parameters(verified_parameters, distance);
graph_type graph{data.size(), verified_parameters.graph_max_degree, graph_allocator};
auto entry_point = data.size() == 0 ? 0 : extensions::compute_entry_point(data, threadpool);
return MutableVamanaIndex<graph_type, data_type, Distance>(
    verified_parameters, std::move(graph), std::move(data), lib::narrow<Idx>(entry_point),
    std::move(distance), external_ids, std::move(threadpool), std::move(logger));

Points I'm unsure about:

  • Sequential has no reverse edges. Not sure if that already breaks the option to mirror #380.
  • In sequential, direct callers of MutableVamanaIndex cannot pass an allocator to the build-from-scratch constructor. They have to allocate the graph and compute the entry point themselves, then call the ready-graph constructor. Is this a limitation we could fix for both versions, assuming we decide to mirror the patterns?

@rfsaliev
rfsaliev requested a balanced review from Copilot October 7, 2026 12:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread include/svs/concurrent/graph.h
Comment thread include/svs/orchestrators/concurrent_dynamic_vamana.h
Comment thread tests/svs/orchestrators/concurrent_dynamic_vamana.cpp
Comment thread include/svs/orchestrators/concurrent_dynamic_vamana.h

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread include/svs/concurrent/dynamic_index.h Outdated
Comment thread include/svs/concurrent/dynamic_index.h
Comment thread include/svs/concurrent/graph.h
Comment thread tests/svs/orchestrators/concurrent_dynamic_vamana.cpp
@rfsaliev

rfsaliev commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

I am worried about drift between sequential and concurrent code and I'm wondering why we can't pick the same approach as in #380.
@ahuber21, I've updated concurrent .ctors to match non-concurrent MutableVamanaIndex.

@rfsaliev
rfsaliev requested review from ahuber21 and a balanced review from Copilot October 7, 2026 14:24
@rfsaliev
rfsaliev force-pushed the rfsaliev/concurrent-orchestrator branch from 41a4f67 to 6775223 Compare October 7, 2026 16:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Empty-index construction can retain an invalid entry point, and key allocator and hole-aware paths lack coverage.

0 open findings

4 resolved since last review

🧠 Review effort: Balanced

@ahuber21 ahuber21 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Two more small comments.

Comment thread include/svs/concurrent/dynamic_index.h
Comment thread include/svs/concurrent/dynamic_index.h
@rfsaliev
rfsaliev requested review from ahuber21 and a balanced review from Copilot October 8, 2026 09:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The assembly constructor breaks an existing public signature, and key concurrent and hole-aware behavior lacks deterministic coverage.

3 open findings

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment on lines 443 to +444
const Dist& distance_function,
const std::vector<SlotMetadata>& status,
Comment thread include/svs/concurrent/README.md Outdated
Comment thread include/svs/orchestrators/concurrent_dynamic_vamana.h Outdated
@mergify

mergify Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

This pull request does not currently match the merge queue conditions, so it cannot be queued from here. The box comes back if it matches again.

@rfsaliev
rfsaliev force-pushed the rfsaliev/concurrent-orchestrator branch from e753cca to 886bd8a Compare October 8, 2026 11:15
@rfsaliev
rfsaliev force-pushed the rfsaliev/concurrent-orchestrator branch from 886bd8a to 47164bc Compare October 8, 2026 14:30

This branch has not been deployed

No deployments
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.

3 participants