Skip to content

Commit aceb8ff

Browse files
committed
fix: expand Pyramid ef search for large topk
Signed-off-by: JiangChao <jacllovey@qq.com> Assisted-by: Codex:GPT-5
1 parent 8b1ff27 commit aceb8ff

2 files changed

Lines changed: 38 additions & 1 deletion

File tree

src/algorithm/pyramid.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,14 +240,15 @@ Pyramid::KnnSearch(const DatasetPtr& query,
240240
QueryContext ctx{.stats = &stats};
241241

242242
auto parsed_param = PyramidSearchParameters::FromJson(parameters);
243+
CHECK_ARGUMENT(k > 0, fmt::format("k({}) must be greater than 0", k));
243244
auto ef_search_threshold = std::max<uint64_t>(AMPLIFICATION_FACTOR * k, 1000L);
244245
CHECK_ARGUMENT( // NOLINT
245246
(1 <= parsed_param.ef_search) and (parsed_param.ef_search <= ef_search_threshold),
246247
fmt::format(
247248
"ef_search({}) must in range[1, {}]", parsed_param.ef_search, ef_search_threshold));
248249

249250
InnerSearchParam search_param;
250-
search_param.ef = parsed_param.ef_search;
251+
search_param.ef = std::max<uint64_t>(parsed_param.ef_search, static_cast<uint64_t>(k));
251252
search_param.radius = std::numeric_limits<float>::max();
252253
search_param.topk = k;
253254
search_param.search_mode = KNN_SEARCH;

tests/test_pyramid.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,42 @@ TEST_CASE_PERSISTENT_FIXTURE(fixtures::PyramidTestIndex,
373373
REQUIRE(ids_a.count(402) == 0);
374374
}
375375

376+
TEST_CASE_PERSISTENT_FIXTURE(fixtures::PyramidTestIndex,
377+
"Pyramid KnnSearch Expands Ef Search To Topk",
378+
"[ft][build][pyramid]") {
379+
PyramidParam pyramid_param;
380+
pyramid_param.no_build_levels = {};
381+
382+
const auto param = GeneratePyramidBuildParametersString("l2", 4, pyramid_param);
383+
auto index = TestFactory("pyramid", param, true);
384+
385+
constexpr int64_t data_count = 24;
386+
constexpr int64_t topk = 20;
387+
constexpr int64_t ef_search = 5;
388+
std::vector<std::array<float, 4>> vectors;
389+
std::vector<int64_t> ids;
390+
std::vector<std::string> paths;
391+
vectors.reserve(data_count);
392+
ids.reserve(data_count);
393+
paths.reserve(data_count);
394+
for (int64_t i = 0; i < data_count; ++i) {
395+
auto value = static_cast<float>(i);
396+
vectors.push_back({value, value + 1.0F, value + 2.0F, value + 3.0F});
397+
ids.push_back(1000 + i);
398+
paths.emplace_back("all");
399+
}
400+
401+
auto base = MakeDenseDataset(vectors, ids, paths);
402+
auto build_result = index->Build(base);
403+
REQUIRE(build_result.has_value());
404+
405+
auto query = MakeSingleQuery(vectors.front(), "all");
406+
auto search_result =
407+
index->KnnSearch(query, topk, GeneratePyramidSearchParametersString(ef_search));
408+
REQUIRE(search_result.has_value());
409+
REQUIRE(search_result.value()->GetDim() == topk);
410+
}
411+
376412
TEST_CASE_PERSISTENT_FIXTURE(fixtures::PyramidTestIndex,
377413
"Pyramid Add Test",
378414
"[ft][build][pyramid]") {

0 commit comments

Comments
 (0)