Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/svs/concepts/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,11 @@ template <ImmutableMemoryGraph G> using index_type_t = typename G::index_type;
/// };
/// @endcode
///
template <typename T>
template <typename T, typename AddEdgeReturn = size_t>
concept MemoryGraph = requires(T& g, const T& const_g) {
// Adding an edge.
requires requires(index_type_t<T> src, index_type_t<T> dst) {
{ g.add_edge(src, dst) } -> std::convertible_to<size_t>;
{ g.add_edge(src, dst) } -> std::convertible_to<AddEdgeReturn>;
};

// Clear adjacency list.
Expand Down
1 change: 0 additions & 1 deletion include/svs/concurrent/concurrent.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
#include "svs/concurrent/prune.h"
#include "svs/concurrent/reverse_edges.h"
#include "svs/concurrent/spinlock.h"
#include "svs/concurrent/translation.h"
#include "svs/concurrent/vamana_build.h"

namespace svs {
Expand Down
80 changes: 2 additions & 78 deletions include/svs/concurrent/consolidate.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "svs/concurrent/graph.h"
#include "svs/concurrent/prune.h"
#include "svs/core/distance.h"
#include "svs/index/vamana/consolidate.h"
#include "svs/index/vamana/extensions.h"
#include "svs/lib/array.h"
#include "svs/lib/threads.h"
Expand Down Expand Up @@ -52,68 +53,7 @@ struct ConsolidationParameters {
float alpha;
};

///
/// A helper struct to store pending updates for the consolidated graph.
/// Represents pending updates using several large allocations rather than many small ones.
///
template <std::integral I> class BulkUpdate {
public:
// Constructor
BulkUpdate(size_t max_batch_size, size_t prune_to)
: neighbors_{make_dims(max_batch_size, prune_to)}
, lengths_{max_batch_size}
, needs_update_{max_batch_size} {}

///
/// Pre-conditions:
/// * 0 <= src < max_batch_size
/// * neighbors.size() <= prune_to
/// * May be called concurrently from multiple threads as long as `src` is
/// unique for each thread.
///
template <typename Allocator>
void insert(size_t src, const std::vector<I, Allocator>& neighbors) {
assert(neighbors.size() <= getsize<1>(neighbors_));
assert(src < getsize<0>(neighbors_));

needs_update_.at(src) = true;
// N.B.: There is no way we get even close to crossing what can be
// expressed as a 32-bit unsigned number.
lengths_.at(src) = lib::narrow_cast<I>(neighbors.size());
std::copy(neighbors.begin(), neighbors.end(), neighbors_.slice(src).begin());
}

///
/// Return `true` if index `src` has a pending update.
///
bool needs_update(size_t src) const { return needs_update_.at(src); }

///
/// Return the pending update for `src`.
/// Pre-conditions:
/// * `needs_update(src) == true`
///
std::span<const I> get_update(size_t src) const {
assert(needs_update(src));
return neighbors_.slice(src).first(lengths_.at(src));
}

///
/// Prepare the data structure for another batch of processing.
/// **Preconditions:**
///
/// * Must be called from a single thread.
///
void prepare() { std::fill(needs_update_.begin(), needs_update_.end(), false); }

private:
Matrix<I> neighbors_;
Vector<I> lengths_;
// N.B.: Use a `Vector` instead of a `std::vector` because `std::vector`
// specialized on `bool` and will thus cannot be guarantee coherent updates from
// multiple threads.
Vector<bool> needs_update_;
};
using vamana::BulkUpdate;

template <std::integral I> struct ConsolidateThreadLocal {
template <typename T> using allocator_type = threads::CacheAlignedAllocator<T>;
Expand Down Expand Up @@ -290,22 +230,6 @@ class GraphConsolidator {
}
}

///
/// Write pending updates to the graph.
///
template <typename GlobalIds>
void apply_updates(
BulkUpdate<I>& update_buffer,
const GlobalIds& global_ids,
const threads::UnitRange<size_t>& local_ids
) {
for (auto i : local_ids) {
if (update_buffer.needs_update(i)) {
graph_.replace_node(global_ids[i], update_buffer.get_update(i));
}
}
}

///
/// Gather a superset of the live nodes with an edge to some deleted node in `D`.
///
Expand Down
2 changes: 1 addition & 1 deletion include/svs/concurrent/dynamic_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
#include "svs/concurrent/dynamic_search_buffer.h"
#include "svs/concurrent/graph.h"
#include "svs/concurrent/greedy_search.h"
#include "svs/concurrent/translation.h"
#include "svs/concurrent/vamana_build.h"
#include "svs/core/data.h"
#include "svs/core/distance.h"
Expand All @@ -45,6 +44,7 @@
#include "svs/core/medioid.h"
#include "svs/core/query_result.h"
#include "svs/core/recall.h"
#include "svs/core/translation.h"
#include "svs/index/vamana/index.h"
#include "svs/lib/boundscheck.h"
#include "svs/lib/neighbor.h"
Expand Down
Loading
Loading