Skip to content
Open
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
40 changes: 40 additions & 0 deletions bindings/cpp/include/svs/runtime/dynamic_vamana_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ struct SVS_RUNTIME_API DynamicVamanaIndex : public VamanaIndex {
// Utility function to check storage kind support
static Status check_storage_kind(StorageKind storage_kind) noexcept;

static Status check_params(const VamanaIndex::DynamicIndexParams& dynamic_index_params
) noexcept;

// Static constructors and destructors
// ABI backward compatibility
static Status build(
DynamicVamanaIndex** index,
size_t dim,
Expand All @@ -49,6 +53,16 @@ struct SVS_RUNTIME_API DynamicVamanaIndex : public VamanaIndex {
const VamanaIndex::SearchParams& default_search_params = {}
) noexcept;

static Status build(
DynamicVamanaIndex** index,
size_t dim,
MetricType metric,
StorageKind storage_kind,
const VamanaIndex::BuildParams& params,
const VamanaIndex::SearchParams& default_search_params,
const VamanaIndex::DynamicIndexParams& dynamic_index_params
) noexcept;

static Status destroy(DynamicVamanaIndex* index) noexcept;

virtual Status save(std::ostream& out) const noexcept = 0;
Expand All @@ -58,10 +72,13 @@ struct SVS_RUNTIME_API DynamicVamanaIndex : public VamanaIndex {
MetricType metric,
StorageKind storage_kind
) noexcept;

virtual size_t blocksize_bytes() const noexcept = 0;
};

struct SVS_RUNTIME_API DynamicVamanaIndexLeanVec : public DynamicVamanaIndex {
// Specialization to build LeanVec-based Vamana index with specified leanvec dims
// ABI backward compatibility
static Status build(
DynamicVamanaIndex** index,
size_t dim,
Expand All @@ -72,7 +89,19 @@ struct SVS_RUNTIME_API DynamicVamanaIndexLeanVec : public DynamicVamanaIndex {
const VamanaIndex::SearchParams& default_search_params = {}
) noexcept;

static Status build(
DynamicVamanaIndex** index,
size_t dim,
MetricType metric,
StorageKind storage_kind,
size_t leanvec_dims,
const VamanaIndex::BuildParams& params,
const VamanaIndex::SearchParams& default_search_params,
const VamanaIndex::DynamicIndexParams& dynamic_index_params
) noexcept;

// Specialization to build LeanVec-based Vamana index with provided training data
// ABI backward compatibility
static Status build(
DynamicVamanaIndex** index,
size_t dim,
Expand All @@ -82,6 +111,17 @@ struct SVS_RUNTIME_API DynamicVamanaIndexLeanVec : public DynamicVamanaIndex {
const VamanaIndex::BuildParams& params = {},
const VamanaIndex::SearchParams& default_search_params = {}
) noexcept;

static Status build(
DynamicVamanaIndex** index,
size_t dim,
MetricType metric,
StorageKind storage_kind,
const LeanVecTrainingData* training_data,
const VamanaIndex::BuildParams& params,
const VamanaIndex::SearchParams& default_search_params,
const VamanaIndex::DynamicIndexParams& dynamic_index_params
) noexcept;
};

} // namespace v0
Expand Down
4 changes: 4 additions & 0 deletions bindings/cpp/include/svs/runtime/vamana_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ struct SVS_RUNTIME_API VamanaIndex {
size_t prefetch_step = Unspecify<size_t>();
};

struct DynamicIndexParams {
size_t blocksize_exp = 30;
};

virtual Status search(
size_t n,
const float* x,
Expand Down
127 changes: 120 additions & 7 deletions bindings/cpp/src/dynamic_vamana_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ struct DynamicVamanaIndexManagerBase : public DynamicVamanaIndex {
});
}

size_t blocksize_bytes() const noexcept { return impl_->blocksize_bytes(); }

Status
remove_selected(size_t* num_removed, const IDFilter& selector) noexcept override {
return runtime_error_wrapper([&] {
Expand Down Expand Up @@ -136,19 +138,60 @@ Status DynamicVamanaIndex::check_storage_kind(StorageKind storage_kind) noexcept
);
}

Status DynamicVamanaIndex::check_params(
const DynamicVamanaIndex::DynamicIndexParams& dynamic_index_params
) noexcept {
constexpr static size_t kMaxBlockSizeExp = 30; // 1GB
constexpr static size_t kMinBlockSizeExp = 12; // 4KB

if (dynamic_index_params.blocksize_exp > kMaxBlockSizeExp)
return Status(ErrorCode::INVALID_ARGUMENT, "Blocksize is too large");

if (dynamic_index_params.blocksize_exp < kMinBlockSizeExp)
return Status(ErrorCode::INVALID_ARGUMENT, "Blocksize is too small");

return Status_Ok;
}

// ABI backward compatibility
Status DynamicVamanaIndex::build(
DynamicVamanaIndex** index,
size_t dim,
MetricType metric,
StorageKind storage_kind,
const DynamicVamanaIndex::BuildParams& params,
const DynamicVamanaIndex::SearchParams& default_search_params
) noexcept {
return build(
index,
dim,
metric,
storage_kind,
params,
default_search_params,
DynamicVamanaIndex::DynamicIndexParams{}
);
}

Status DynamicVamanaIndex::build(
DynamicVamanaIndex** index,
size_t dim,
MetricType metric,
StorageKind storage_kind,
const DynamicVamanaIndex::BuildParams& params,
const DynamicVamanaIndex::SearchParams& default_search_params,
const DynamicVamanaIndex::DynamicIndexParams& dynamic_index_params
) noexcept {
using Impl = DynamicVamanaIndexImpl;
*index = nullptr;

auto status = DynamicVamanaIndex::check_params(dynamic_index_params);
if (!status.ok())
return status;

return runtime_error_wrapper([&] {
auto impl = std::make_unique<Impl>(
dim, metric, storage_kind, params, default_search_params
dim, metric, storage_kind, params, default_search_params, dynamic_index_params
);
*index = new DynamicVamanaIndexManagerBase<Impl>{std::move(impl)};
});
Expand All @@ -172,8 +215,8 @@ Status DynamicVamanaIndex::load(
});
}

#ifdef SVS_LEANVEC_HEADER
// Specialization to build LeanVec-based Vamana index with specified leanvec dims
// ABI backward compatibility
Status DynamicVamanaIndexLeanVec::build(
DynamicVamanaIndex** index,
size_t dim,
Expand All @@ -182,12 +225,70 @@ Status DynamicVamanaIndexLeanVec::build(
size_t leanvec_dims,
const DynamicVamanaIndex::BuildParams& params,
const DynamicVamanaIndex::SearchParams& default_search_params
) noexcept {
return build(
index,
dim,
metric,
storage_kind,
leanvec_dims,
params,
default_search_params,
DynamicVamanaIndex::DynamicIndexParams{}
);
}

// Specialization to build LeanVec-based Vamana index with provided training data
// ABI backward compatibility
Status DynamicVamanaIndexLeanVec::build(
DynamicVamanaIndex** index,
size_t dim,
MetricType metric,
StorageKind storage_kind,
const LeanVecTrainingData* training_data,
const DynamicVamanaIndex::BuildParams& params,
const DynamicVamanaIndex::SearchParams& default_search_params
) noexcept {
return build(
index,
dim,
metric,
storage_kind,
training_data,
params,
default_search_params,
DynamicVamanaIndex::DynamicIndexParams{}
);
}

#ifdef SVS_LEANVEC_HEADER
// Specialization to build LeanVec-based Vamana index with specified leanvec dims
Status DynamicVamanaIndexLeanVec::build(
DynamicVamanaIndex** index,
size_t dim,
MetricType metric,
StorageKind storage_kind,
size_t leanvec_dims,
const DynamicVamanaIndex::BuildParams& params,
const DynamicVamanaIndex::SearchParams& default_search_params,
const DynamicVamanaIndex::DynamicIndexParams& dynamic_index_params
) noexcept {
using Impl = DynamicVamanaIndexLeanVecImpl;
*index = nullptr;

auto status = DynamicVamanaIndex::check_params(dynamic_index_params);
if (!status.ok())
return status;

return runtime_error_wrapper([&] {
auto impl = std::make_unique<Impl>(
dim, metric, storage_kind, leanvec_dims, params, default_search_params
dim,
metric,
storage_kind,
leanvec_dims,
params,
default_search_params,
dynamic_index_params
);
*index = new DynamicVamanaIndexManagerBase<Impl>{std::move(impl)};
});
Expand All @@ -201,15 +302,27 @@ Status DynamicVamanaIndexLeanVec::build(
StorageKind storage_kind,
const LeanVecTrainingData* training_data,
const DynamicVamanaIndex::BuildParams& params,
const DynamicVamanaIndex::SearchParams& default_search_params
const DynamicVamanaIndex::SearchParams& default_search_params,
const DynamicVamanaIndex::DynamicIndexParams& dynamic_index_params
) noexcept {
using Impl = DynamicVamanaIndexLeanVecImpl;
*index = nullptr;

auto status = DynamicVamanaIndex::check_params(dynamic_index_params);
if (!status.ok())
return status;

return runtime_error_wrapper([&] {
auto training_data_impl =
static_cast<const LeanVecTrainingDataManager*>(training_data)->impl_;
auto impl = std::make_unique<Impl>(
dim, metric, storage_kind, training_data_impl, params, default_search_params
dim,
metric,
storage_kind,
training_data_impl,
params,
default_search_params,
dynamic_index_params
);
*index = new DynamicVamanaIndexManagerBase<Impl>{std::move(impl)};
});
Expand All @@ -218,15 +331,15 @@ Status DynamicVamanaIndexLeanVec::build(
#else // SVS_LEANVEC_HEADER
// LeanVec storage kind is not supported in this build configuration
Status DynamicVamanaIndexLeanVec::
build(DynamicVamanaIndex**, size_t, MetricType, StorageKind, size_t, const DynamicVamanaIndex::BuildParams&, const DynamicVamanaIndex::SearchParams&) noexcept {
build(DynamicVamanaIndex**, size_t, MetricType, StorageKind, size_t, const DynamicVamanaIndex::BuildParams&, const DynamicVamanaIndex::SearchParams&, const DynamicVamanaIndex::DynamicIndexParams&) noexcept {
return Status(
ErrorCode::NOT_IMPLEMENTED,
"DynamicVamanaIndexLeanVec is not supported in this build configuration."
);
}

Status DynamicVamanaIndexLeanVec::
build(DynamicVamanaIndex**, size_t, MetricType, StorageKind, const LeanVecTrainingData*, const DynamicVamanaIndex::BuildParams&, const DynamicVamanaIndex::SearchParams&) noexcept {
build(DynamicVamanaIndex**, size_t, MetricType, StorageKind, const LeanVecTrainingData*, const DynamicVamanaIndex::BuildParams&, const DynamicVamanaIndex::SearchParams&, const DynamicVamanaIndex::DynamicIndexParams&) noexcept {
return Status(
ErrorCode::NOT_IMPLEMENTED,
"DynamicVamanaIndexLeanVec is not supported in this build configuration."
Expand Down
30 changes: 22 additions & 8 deletions bindings/cpp/src/dynamic_vamana_index_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@ class DynamicVamanaIndexImpl {
MetricType metric,
StorageKind storage_kind,
const VamanaIndex::BuildParams& params,
const VamanaIndex::SearchParams& default_search_params
const VamanaIndex::SearchParams& default_search_params,
const VamanaIndex::DynamicIndexParams& dynamic_index_params
)
: dim_{dim}
, metric_type_{metric}
, storage_kind_{storage_kind}
, build_params_{params}
, default_search_params_{default_search_params} {
, default_search_params_{default_search_params}
, dynamic_index_params_{dynamic_index_params} {
if (!storage::is_supported_storage_kind(storage_kind)) {
throw StatusException{
ErrorCode::INVALID_ARGUMENT,
Expand All @@ -63,6 +65,8 @@ class DynamicVamanaIndexImpl {

size_t size() const { return impl_ ? impl_->size() : 0; }

size_t blocksize_bytes() const { return 1u << dynamic_index_params_.blocksize_exp; }

size_t dimensions() const { return dim_; }

MetricType metric_type() const { return metric_type_; }
Expand All @@ -71,7 +75,8 @@ class DynamicVamanaIndexImpl {

void add(data::ConstSimpleDataView<float> data, std::span<const size_t> labels) {
if (!impl_) {
return init_impl(data, labels);
auto blocksize_bytes = lib::PowerOfTwo(dynamic_index_params_.blocksize_exp);
return init_impl(data, labels, blocksize_bytes);
}

impl_->add_points(data, labels);
Expand Down Expand Up @@ -385,6 +390,7 @@ class DynamicVamanaIndexImpl {
const index::vamana::VamanaBuildParameters& parameters,
const svs::data::ConstSimpleDataView<float>& data,
std::span<const size_t> labels,
svs::lib::PowerOfTwo blocksize_bytes,
StorageArgs&&... storage_args
) {
auto threadpool = default_threadpool();
Expand All @@ -393,6 +399,7 @@ class DynamicVamanaIndexImpl {
std::forward<Tag>(tag),
data,
threadpool,
blocksize_bytes,
std::forward<StorageArgs>(storage_args)...
);

Expand All @@ -408,26 +415,32 @@ class DynamicVamanaIndexImpl {
});
}

virtual void
init_impl(data::ConstSimpleDataView<float> data, std::span<const size_t> labels) {
virtual void init_impl(
data::ConstSimpleDataView<float> data,
std::span<const size_t> labels,
lib::PowerOfTwo blocksize_bytes
) {
impl_.reset(storage::dispatch_storage_kind(
get_storage_kind(),
[this](
auto&& tag,
data::ConstSimpleDataView<float> data,
std::span<const size_t> labels
std::span<const size_t> labels,
lib::PowerOfTwo blocksize_bytes
) {
using Tag = std::decay_t<decltype(tag)>;
return build_impl(
std::forward<Tag>(tag),
this->metric_type_,
this->vamana_build_parameters(),
data,
labels
labels,
blocksize_bytes
);
},
data,
labels
labels,
blocksize_bytes
));
}

Expand Down Expand Up @@ -522,6 +535,7 @@ class DynamicVamanaIndexImpl {
StorageKind storage_kind_;
VamanaIndex::BuildParams build_params_;
VamanaIndex::SearchParams default_search_params_;
VamanaIndex::DynamicIndexParams dynamic_index_params_;
std::unique_ptr<svs::DynamicVamana> impl_;
size_t ntotal_soft_deleted{0};
};
Expand Down
Loading
Loading