Repository navigation
fix(orchestrators): route stream assemble through the loader-based assemble - #417
Conversation
a2f6a28 to
416b0f9
Compare
| /// allocator type. | ||
| /// | ||
| template <typename Idx = uint32_t, typename Allocator = HugepageAllocator<Idx>> | ||
| struct StreamGraphLoader { |
There was a problem hiding this comment.
IMO, there is unnecessary code duplication.
It would be better to reuse existing GraphLoader class constructed from (stream, allocator) rather than multiply entities.
There was a problem hiding this comment.
Thanks. Good idea. I will try it this way.
StreamLoader carries the element type and loader arguments (e.g. an allocator) for one component of an index saved to a stream. The orchestrator hands it either the stream (native format) or the unpacked component directory (directory archive). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…semble Vamana, DynamicVamana and ConcurrentDynamicVamana now load from a stream through the existing assemble(config_proto, graph_loader, data_loader, ...) when config_proto is a std::istream and both loaders are StreamLoader. The stream body moved unchanged into a private helper. - The released assemble<Q, Data>(stream, distance, pool, data_args...) on Vamana and DynamicVamana stays as a thin wrapper with its v0.4.0 signature and default graph allocators. - Removed, never released: Vamana's view-backed overload and the (data_allocator, graph_allocator) overloads from #402, and ConcurrentDynamicVamana's stream overload from #413. - The stream path used to drop the logger and debug_load_from_static; both are now passed through. - The C API and C++ runtime call the loader-based form. Public binding headers are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bc42712 to
4f2975f
Compare
|
@rfsaliev yet another attempts to harmonize |
| svs::ConcurrentDynamicVamana::assemble<float, ConcurrentData>( | ||
| stream, svs::distance::DistanceL2(), num_threads | ||
| ); | ||
| svs::DynamicVamana loaded = svs::ConcurrentDynamicVamana::assemble<float>( |
There was a problem hiding this comment.
Consider adding the same tests for other affected orchestrators.
…loads Vamana, DynamicVamana and ConcurrentDynamicVamana now have a dedicated assemble(std::istream&, StreamLoader graph, StreamLoader data, ...) overload instead of branching inside the file-layout assemble. The file-layout overload is constrained to exclude streams and StreamLoader, so a mismatched call finds no viable overload rather than hitting a static_assert. The stream body moved unchanged; call sites are unaffected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/intelci |
The static-library C API job builds against the headers shipped in the prebuilt archive. The previous archive predates `svs::StreamLoader` and the StreamLoader assemble overloads, so the dispatchers failed to compile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The static-library C++ runtime job builds against the headers shipped in the prebuilt archive. The previous archive predates `svs::StreamLoader` and `Vamana::default_graph_type`, so the runtime impls failed to compile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/intelci |
rfsaliev
left a comment
There was a problem hiding this comment.
There are some suggestions.
And seems like the complex refactoring is needed for save/load index cases.
But functionally this PR looks good for me.
Approving.
|
|
||
| T load(std::istream& stream) const { | ||
| return std::apply( | ||
| [&](const Args&... args) { return lib::load_from_stream<T>(stream, args...); }, |
There was a problem hiding this comment.
what if one of Args is not copyable, i.e. has deleted copy constructor?
There was a problem hiding this comment.
It works so long it's passed as an rvalue. Will add a test case showcasing it. StreamLoader can of course always be extended if more scenarios are needed. For now, everything compiles though.
The static-library C API job builds against the headers shipped in the prebuilt archive. The previous archive predates `svs::make_stream_loader`, which the stream dispatchers now call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The static-library C++ runtime job builds against the headers shipped in the prebuilt archive. The previous archive predates `svs::make_stream_loader`, which the runtime impls now call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ethanglaser
left a comment
There was a problem hiding this comment.
LGTM, additional test coverage etc can be added as follow-up but this fixes CI and should be part of release
Loading a Vamana-family index from a stream now goes through the same
assemble(config_proto, graph_loader, data_loader, ...)entry point as loading from disk, so a stream is just one more kind of config source rather than its own code path.Stream save/load was added after the loader-based interface already existed, and it took a shortcut. Instead of handing assemble a config, a graph loader and a data loader, the stream overload took the stream plus a pack of arguments for the data, and decided internally how the graph was read. The graph allocator was fixed, and debug_load_from_static was not exposed. That was fine while one default allocator was enough. It stopped being fine once the C API needed to put the graph and the data in different allocators. #402 and the first version of this PR tried to close that gap by adding parameters and overloads to the stream path, and every attempt made the stream path more of a parallel copy of the loader path. This PR stops patching the copy and removes it.
This PR goes back to the original design. The loader-based
assembleon Vamana, DynamicVamana and ConcurrentDynamicVamana now accepts astd::istreamasconfig_proto. In that case it runs the existing stream logic unchanged: it detects native vs. directory-archive format, reads the native stream in place, or unpacks the archive and loads from paths. The graph and data allocators come from the loaders, exactly as they do for file loads. The releasedassemble<Q, Data>(stream, distance, pool, data_args...)stays as a thin wrapper with its v0.4.0 signature and default allocators, so existing callers compile and behave as before. The C API and the C++ runtime now call the loader-based form directly, and neither public binding header changes.svs::StreamLoader<T, Args...>lives insvs/core/loading.h, next todispatch_load. It plays the role on the stream side thatGraphLoaderandVectorDataLoaderplay for files: it fixes the type to load and carries the arguments for it, typically an allocator. Unlike those two it holds no source. The orchestrator hands it either the stream or the unpacked component directory, because only the orchestrator knows which format arrived. One generic template is enough, since the caller always knows the exact type and graphs, datasets and configs all already load from both a stream and a path. A file-side loader likeVectorDataLoaderalso deduces element type and dimensions, which a stream load never needs.static_asserts reject mixing aStreamLoaderwith a non-stream config, in either direction. A new public alias,Vamana::default_graph_type<Data>, names the default graph type. For view-backed data it rebinds the data's allocator touint32_t; otherwise it usesHugepageAllocator. The wrapper and the C++ runtime share that one rule instead of each keeping a copy.A few things a reviewer should know:
loggeranddebug_load_from_static. That is a behaviour change, though only for callers who were passing values that were being ignored.StreamLoaderstores copies of its arguments and passes them on asconstlvalues. A loader that needs to consume an rvalue would fail to compile; it would not misbehave silently.assemblehas no config slot, and IVF has no loader-basedassembleat all, so bringing them in line is separate work.auto_assemblefunctions insvs::index::*are untouched.