Skip to content
This repository was archived by the owner on Aug 16, 2023. It is now read-only.

Commit e5d7dff

Browse files
authored
replace omp with threads pool in diskann (#759)
Signed-off-by: cqy123456 <[email protected]>
1 parent 7937871 commit e5d7dff

File tree

14 files changed

+586
-470
lines changed

14 files changed

+586
-470
lines changed

ci/docker/set_docker_mirror.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ set_mirror(){
5656
restart_docker
5757
echo "Success."
5858
exit 0
59+
5960
}
6061

6162
set_mirror

include/knowhere/feder/DiskANN.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,14 @@ class DiskANNMeta {
4242
DiskANNMeta() = default;
4343

4444
DiskANNMeta(const std::string& data_path, const int32_t max_degree, const int32_t search_list_size,
45-
const float pq_code_budget_gb, const float build_dram_budget_gb, const int32_t num_threads,
46-
const int32_t disk_pq_dims, const bool accelerate_build, const int64_t num_elem,
47-
const std::vector<int64_t>& entry_points)
45+
const float pq_code_budget_gb, const float build_dram_budget_gb, const int32_t disk_pq_dims,
46+
const bool accelerate_build, const int64_t num_elem, const std::vector<int64_t>& entry_points)
4847
: num_elem_(num_elem), entry_points_(entry_points) {
4948
build_params_.data_path = data_path;
5049
build_params_.max_degree = max_degree;
5150
build_params_.search_list_size = search_list_size;
5251
build_params_.pq_code_budget_gb = pq_code_budget_gb;
5352
build_params_.build_dram_budget_gb = build_dram_budget_gb;
54-
build_params_.num_threads = num_threads;
5553
build_params_.disk_pq_dims = disk_pq_dims;
5654
build_params_.accelerate_build = accelerate_build;
5755
}

src/common/config.cc

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,33 @@
1414
#include "knowhere/log.h"
1515
namespace knowhere {
1616

17-
static const std::unordered_set<std::string> ext_legal_json_keys = {
18-
"metric_type",
19-
"dim",
20-
"nlist",
21-
"nprobe",
22-
"level",
23-
"index_type",
24-
"index_mode",
25-
"collection_id",
26-
"partition_id",
27-
"segment_id",
28-
"field_id",
29-
"index_build_id",
30-
"index_id",
31-
"index_version",
32-
"pq_code_budget_gb_ratio",
33-
"num_build_thread_ratio",
34-
"search_cache_budget_gb_ratio",
35-
"num_load_thread_ratio",
36-
"beamwidth_ratio",
37-
"search_list",
38-
"num_build_thread",
39-
"num_load_thread",
40-
"index_files",
41-
"gpu_id",
42-
"nbits",
43-
"m",
44-
};
17+
static const std::unordered_set<std::string> ext_legal_json_keys = {"metric_type",
18+
"dim",
19+
"nlist",
20+
"nprobe",
21+
"level",
22+
"index_type",
23+
"index_mode",
24+
"collection_id",
25+
"partition_id",
26+
"segment_id",
27+
"field_id",
28+
"index_build_id",
29+
"index_id",
30+
"index_version",
31+
"pq_code_budget_gb_ratio",
32+
"num_build_thread_ratio",
33+
"search_cache_budget_gb_ratio",
34+
"num_load_thread_ratio",
35+
"beamwidth_ratio",
36+
"search_list",
37+
"num_build_thread",
38+
"num_load_thread",
39+
"index_files",
40+
"gpu_id",
41+
"nbits",
42+
"m",
43+
"num_threads"};
4544

4645
Status
4746
Config::FormatAndCheck(const Config& cfg, Json& json) {

src/index/diskann/diskann.cc

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ class DiskANNIndexNode : public IndexNode {
156156
std::string index_prefix_;
157157
mutable std::mutex preparation_lock_;
158158
std::atomic_bool is_prepared_;
159-
int32_t num_threads_;
160159
std::shared_ptr<FileManager> file_manager_;
161160
std::unique_ptr<diskann::PQFlashIndex<T>> pq_flash_index_;
162161
std::atomic_int64_t dim_;
@@ -280,7 +279,6 @@ DiskANNIndexNode<T>::Add(const DataSet& dataset, const Config& cfg) {
280279
static_cast<unsigned>(build_conf.search_list_size),
281280
static_cast<double>(build_conf.pq_code_budget_gb),
282281
static_cast<double>(build_conf.build_dram_budget_gb),
283-
static_cast<uint32_t>(build_conf.num_threads),
284282
static_cast<uint32_t>(build_conf.disk_pq_dims),
285283
false,
286284
build_conf.accelerate_build};
@@ -355,8 +353,8 @@ DiskANNIndexNode<T>::Prepare(const Config& cfg) {
355353

356354
pq_flash_index_ = std::make_unique<diskann::PQFlashIndex<T>>(reader, diskann_metric);
357355

358-
auto load_expect = TryDiskANNCall<int>(
359-
[&]() -> int { return pq_flash_index_->load(prep_conf.num_threads, index_prefix_.c_str()); });
356+
auto load_expect =
357+
TryDiskANNCall<int>([&]() -> int { return pq_flash_index_->load(pool_->size(), index_prefix_.c_str()); });
360358

361359
if (!load_expect.has_value() || load_expect.value() != 0) {
362360
LOG_KNOWHERE_ERROR_ << "Failed to load DiskANN.";
@@ -397,7 +395,7 @@ DiskANNIndexNode<T>::Prepare(const Config& cfg) {
397395
} else {
398396
auto gen_cache_expect = TryDiskANNCall<bool>([&]() -> bool {
399397
pq_flash_index_->generate_cache_list_from_sample_queries(warmup_query_file, 15, 6, num_nodes_to_cache,
400-
prep_conf.num_threads, node_list);
398+
node_list);
401399
return true;
402400
});
403401

@@ -417,10 +415,6 @@ DiskANNIndexNode<T>::Prepare(const Config& cfg) {
417415
}
418416
}
419417

420-
// set thread number
421-
omp_set_num_threads(prep_conf.num_threads);
422-
num_threads_ = prep_conf.num_threads;
423-
424418
// warmup
425419
if (prep_conf.warm_up) {
426420
LOG_KNOWHERE_INFO_ << "Warming up.";
@@ -441,15 +435,22 @@ DiskANNIndexNode<T>::Prepare(const Config& cfg) {
441435
std::vector<float> warmup_result_dists(warmup_num, 0);
442436

443437
bool all_searches_are_good = true;
444-
#pragma omp parallel for schedule(dynamic, 1)
438+
439+
std::vector<std::future<void>> futures;
440+
futures.reserve(warmup_num);
445441
for (_s64 i = 0; i < (int64_t)warmup_num; ++i) {
446-
auto search_expect = TryDiskANNCall<bool>([&]() -> bool {
447-
pq_flash_index_->cached_beam_search(warmup + (i * warmup_aligned_dim), 1, warmup_L,
448-
warmup_result_ids_64.data() + (i * 1),
449-
warmup_result_dists.data() + (i * 1), 4);
442+
futures.push_back(pool_->push([&, index = i]() {
443+
pq_flash_index_->cached_beam_search(warmup + (index * warmup_aligned_dim), 1, warmup_L,
444+
warmup_result_ids_64.data() + (index * 1),
445+
warmup_result_dists.data() + (index * 1), 4);
446+
}));
447+
}
448+
for (auto& future : futures) {
449+
auto one_search_res = TryDiskANNCall<bool>([&]() {
450+
future.get();
450451
return true;
451452
});
452-
if (!search_expect.has_value()) {
453+
if (!one_search_res.has_value()) {
453454
all_searches_are_good = false;
454455
}
455456
}
@@ -507,6 +508,7 @@ DiskANNIndexNode<T>::Search(const DataSet& dataset, const Config& cfg, const Bit
507508
auto p_id = new int64_t[k * nq];
508509
auto p_dist = new float[k * nq];
509510

511+
bool all_searches_are_good = true;
510512
std::vector<std::future<void>> futures;
511513
futures.reserve(nq);
512514
for (int64_t row = 0; row < nq; ++row) {
@@ -516,7 +518,17 @@ DiskANNIndexNode<T>::Search(const DataSet& dataset, const Config& cfg, const Bit
516518
}));
517519
}
518520
for (auto& future : futures) {
519-
future.get();
521+
auto one_search_res = TryDiskANNCall<bool>([&]() {
522+
future.get();
523+
return true;
524+
});
525+
if (!one_search_res.has_value()) {
526+
all_searches_are_good = false;
527+
}
528+
}
529+
530+
if (!all_searches_are_good) {
531+
return unexpected(Status::diskann_inner_error);
520532
}
521533

522534
auto res = GenResultDataSet(nq, k, p_id, p_dist);
@@ -572,6 +584,7 @@ DiskANNIndexNode<T>::RangeSearch(const DataSet& dataset, const Config& cfg, cons
572584

573585
std::vector<std::future<void>> futures;
574586
futures.reserve(nq);
587+
bool all_searches_are_good = true;
575588
for (int64_t row = 0; row < nq; ++row) {
576589
futures.push_back(pool_->push([&, index = row]() {
577590
std::vector<int64_t> indices;
@@ -586,8 +599,18 @@ DiskANNIndexNode<T>::RangeSearch(const DataSet& dataset, const Config& cfg, cons
586599
}));
587600
}
588601
for (auto& future : futures) {
589-
future.get();
602+
auto one_search_res = TryDiskANNCall<bool>([&]() {
603+
future.get();
604+
return true;
605+
});
606+
if (!one_search_res.has_value()) {
607+
all_searches_are_good = false;
608+
}
590609
}
610+
if (!all_searches_are_good) {
611+
return unexpected(Status::diskann_inner_error);
612+
}
613+
591614
GetRangeSearchResult(result_dist_array, result_id_array, is_ip, nq, radius, search_conf.range_filter, p_dist, p_id,
592615
p_lims);
593616
return GenResultDataSet(nq, p_id, p_dist, p_lims);
@@ -603,8 +626,7 @@ DiskANNIndexNode<T>::GetIndexMeta(const Config& cfg) const {
603626
auto diskann_conf = static_cast<const DiskANNConfig&>(cfg);
604627
feder::diskann::DiskANNMeta meta(diskann_conf.data_path, diskann_conf.max_degree, diskann_conf.search_list_size,
605628
diskann_conf.pq_code_budget_gb, diskann_conf.build_dram_budget_gb,
606-
diskann_conf.num_threads, diskann_conf.disk_pq_dims, diskann_conf.accelerate_build,
607-
Count(), entry_points);
629+
diskann_conf.disk_pq_dims, diskann_conf.accelerate_build, Count(), entry_points);
608630
std::unordered_set<int64_t> id_set(entry_points.begin(), entry_points.end());
609631

610632
Json json_meta, json_id_set;

src/index/diskann/diskann_config.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,6 @@ class DiskANNConfig : public BaseConfig {
4646
// This is the flag to enable fast build, in which we will not build vamana graph by full 2 round. This can
4747
// accelerate index build ~30% with an ~1% recall regression.
4848
CFG_BOOL accelerate_build;
49-
// The number of threads used for preparing and searching. When 'num_threads' uses as build parameter, the indexing
50-
// time improves almost linearly with the number of threads (subject to the cores available on the machine and DRAM
51-
// bandwidth). When 'num_threads' uses as prepare parameter, Threads run in parallel and one thread handles one
52-
// query at a time. More threads will result in higher aggregate query throughput, but will also use more IOs/second
53-
// across the system, which may lead to higher per-query latency. So find the balance depending on the maximum
54-
// number of IOPs supported by the SSD.
55-
CFG_INT num_threads;
5649
// While serving the index, the entire graph is stored on SSD. For faster search performance, you can cache a few
5750
// frequently accessed nodes in memory.
5851
CFG_FLOAT search_cache_budget_gb;
@@ -102,13 +95,6 @@ class DiskANNConfig : public BaseConfig {
10295
.description("limit on the memory allowed for building the index in GB.")
10396
.set_range(0, std::numeric_limits<CFG_FLOAT>::max())
10497
.for_train();
105-
KNOWHERE_CONFIG_DECLARE_FIELD(num_threads)
106-
.description("number of threads used by the index build/search process.")
107-
.set_default(8)
108-
.set_range(1, 256)
109-
.for_train()
110-
.for_search()
111-
.for_range_search();
11298
KNOWHERE_CONFIG_DECLARE_FIELD(disk_pq_dims)
11399
.description("the dimension of compressed vectors stored on the ssd, use 0 to store uncompressed data.")
114100
.set_default(0)

thirdparty/DiskANN/include/diskann/aux_utils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#pragma once
55
#include <algorithm>
66
#include <fcntl.h>
7+
#include <future>
78
#include <cassert>
89
#include <cstdlib>
910
#include <cstring>
@@ -31,6 +32,7 @@ typedef int FileHandle;
3132

3233
#include "utils.h"
3334
#include "windows_customizations.h"
35+
#include "knowhere/comp/thread_pool.h"
3436

3537
namespace diskann {
3638
const size_t MAX_PQ_TRAINING_SET_SIZE = 256000;
@@ -117,8 +119,6 @@ namespace diskann {
117119
double pq_code_size_gb = 0.0;
118120
// M (memory limit while indexing)
119121
double index_mem_gb = 0.0;
120-
// T (number of threads for indexing)
121-
uint32_t num_threads = 0;
122122
// B' (PQ dim for disk index: optional parameter for very
123123
// large dimensional data)
124124
uint32_t disk_pq_dims = 0;

0 commit comments

Comments
 (0)