This is an automated email from the ASF dual-hosted git repository.
git-hulk pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new bae3ba7a3 perf(search): share a thread-local RNG for HNSW and drop
seed (#2398) (#3562)
bae3ba7a3 is described below
commit bae3ba7a356779a0af1798903aa0a0377b861b7e
Author: advisedy <[email protected]>
AuthorDate: Thu Jul 30 14:00:48 2026 +0800
perf(search): share a thread-local RNG for HNSW and drop seed (#2398)
(#3562)
Fixes #2398.
---
src/search/hnsw_indexer.cc | 11 +++++------
src/search/hnsw_indexer.h | 10 +++++-----
tests/cppunit/hnsw_index_test.cc | 3 +--
3 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/src/search/hnsw_indexer.cc b/src/search/hnsw_indexer.cc
index cb9aca770..7fbc193e7 100644
--- a/src/search/hnsw_indexer.cc
+++ b/src/search/hnsw_indexer.cc
@@ -24,7 +24,6 @@
#include <algorithm>
#include <cmath>
-#include <memory>
#include <queue>
#include <random>
#include <unordered_set>
@@ -172,15 +171,15 @@ StatusOr<double> ComputeSimilarity(const VectorItem&
left, const VectorItem& rig
}
}
-HnswIndex::HnswIndex(const SearchKey& search_key, HnswVectorFieldMetadata*
vector, engine::Storage* storage,
- std::random_device::result_type seed)
+thread_local std::mt19937 HnswIndex::generator{std::random_device()()};
+
+HnswIndex::HnswIndex(const SearchKey& search_key, HnswVectorFieldMetadata*
vector, engine::Storage* storage)
: search_key(search_key),
metadata(vector),
storage(storage),
- generator(std::mt19937(seed)),
m_level_normalization_factor(1.0 / std::log(metadata->m)) {}
-uint16_t HnswIndex::RandomizeLayer() {
+uint16_t HnswIndex::RandomizeLayer() const {
std::uniform_real_distribution<double> level_dist(0.0, 1.0);
double r = level_dist(generator);
double log_val = -std::log(r);
@@ -518,7 +517,7 @@ Status
HnswIndex::InsertVectorEntryInternal(engine::Context& ctx, std::string_vi
}
Status HnswIndex::InsertVectorEntry(engine::Context& ctx, std::string_view
key, const kqir::NumericArray& vector,
-
ObserverOrUniquePtr<rocksdb::WriteBatchBase>& batch) {
+
ObserverOrUniquePtr<rocksdb::WriteBatchBase>& batch) const {
auto target_level = RandomizeLayer();
return InsertVectorEntryInternal(ctx, key, vector, batch, target_level);
}
diff --git a/src/search/hnsw_indexer.h b/src/search/hnsw_indexer.h
index 579352a8b..461fd8eb5 100644
--- a/src/search/hnsw_indexer.h
+++ b/src/search/hnsw_indexer.h
@@ -89,17 +89,17 @@ struct HnswIndex {
HnswVectorFieldMetadata* metadata;
engine::Storage* storage = nullptr;
- std::mt19937 generator;
double m_level_normalization_factor;
- HnswIndex(const SearchKey& search_key, HnswVectorFieldMetadata* vector,
engine::Storage* storage,
- std::random_device::result_type seed = std::random_device()());
+ static thread_local std::mt19937 generator;
+
+ HnswIndex(const SearchKey& search_key, HnswVectorFieldMetadata* vector,
engine::Storage* storage);
static StatusOr<std::vector<VectorItem>>
DecodeNodesToVectorItems(engine::Context& ctx,
const
std::vector<NodeKey>& node_key,
uint16_t
level, const SearchKey& search_key,
const
HnswVectorFieldMetadata* metadata);
- uint16_t RandomizeLayer();
+ uint16_t RandomizeLayer() const;
StatusOr<NodeKey> DefaultEntryPoint(engine::Context& ctx, uint16_t level)
const;
Status AddEdge(const NodeKey& node_key1, const NodeKey& node_key2, uint16_t
layer,
ObserverOrUniquePtr<rocksdb::WriteBatchBase>& batch) const;
@@ -117,7 +117,7 @@ struct HnswIndex {
Status InsertVectorEntryInternal(engine::Context& ctx, std::string_view key,
const kqir::NumericArray& vector,
ObserverOrUniquePtr<rocksdb::WriteBatchBase>& batch, uint16_t layer) const;
Status InsertVectorEntry(engine::Context& ctx, std::string_view key, const
kqir::NumericArray& vector,
- ObserverOrUniquePtr<rocksdb::WriteBatchBase>&
batch);
+ ObserverOrUniquePtr<rocksdb::WriteBatchBase>&
batch) const;
Status DeleteVectorEntry(engine::Context& ctx, std::string_view key,
ObserverOrUniquePtr<rocksdb::WriteBatchBase>&
batch) const;
StatusOr<std::vector<KeyWithDistance>> KnnSearch(engine::Context& ctx, const
kqir::NumericArray& query_vector,
diff --git a/tests/cppunit/hnsw_index_test.cc b/tests/cppunit/hnsw_index_test.cc
index 022f2a738..332c1582a 100644
--- a/tests/cppunit/hnsw_index_test.cc
+++ b/tests/cppunit/hnsw_index_test.cc
@@ -66,7 +66,6 @@ struct HnswIndexTest : TestBase {
std::string idx_name = "hnsw_test_idx";
std::string key = "vector";
std::unique_ptr<redis::HnswIndex> hnsw_index;
- const std::random_device::result_type seed = 14863; // fixed seed for
reproducibility
HnswIndexTest() {
metadata.vector_type = redis::VectorType::FLOAT64;
@@ -74,7 +73,7 @@ struct HnswIndexTest : TestBase {
metadata.m = 3;
metadata.distance_metric = redis::DistanceMetric::L2;
auto search_key = redis::SearchKey(ns, idx_name, key);
- hnsw_index = std::make_unique<redis::HnswIndex>(search_key, &metadata,
storage_.get(), seed);
+ hnsw_index = std::make_unique<redis::HnswIndex>(search_key, &metadata,
storage_.get());
}
void TearDown() override { hnsw_index.reset(); }