faiss 0.3.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +11 -8
- data/vendor/faiss/faiss/Clustering.cpp +0 -16
- data/vendor/faiss/faiss/IVFlib.cpp +213 -0
- data/vendor/faiss/faiss/IVFlib.h +42 -0
- data/vendor/faiss/faiss/Index.h +1 -1
- data/vendor/faiss/faiss/IndexBinaryFlat.cpp +9 -7
- data/vendor/faiss/faiss/IndexBinaryFlat.h +2 -1
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +1 -1
- data/vendor/faiss/faiss/IndexFlatCodes.h +4 -2
- data/vendor/faiss/faiss/IndexHNSW.cpp +13 -20
- data/vendor/faiss/faiss/IndexHNSW.h +1 -1
- data/vendor/faiss/faiss/IndexIVF.cpp +20 -3
- data/vendor/faiss/faiss/IndexIVF.h +5 -2
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +2 -1
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +2 -1
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +2 -1
- data/vendor/faiss/faiss/IndexIVFFlat.h +2 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +2 -1
- data/vendor/faiss/faiss/IndexIVFPQ.h +2 -1
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +277 -0
- data/vendor/faiss/faiss/IndexIVFRaBitQ.h +70 -0
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +2 -1
- data/vendor/faiss/faiss/IndexIVFSpectralHash.h +2 -1
- data/vendor/faiss/faiss/IndexRaBitQ.cpp +148 -0
- data/vendor/faiss/faiss/IndexRaBitQ.h +65 -0
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +2 -1
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +2 -1
- data/vendor/faiss/faiss/clone_index.cpp +38 -3
- data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +19 -0
- data/vendor/faiss/faiss/cppcontrib/factory_tools.h +4 -11
- data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +2 -1
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +13 -3
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +1 -1
- data/vendor/faiss/faiss/gpu/StandardGpuResources.h +1 -1
- data/vendor/faiss/faiss/gpu/test/TestGpuIcmEncoder.cpp +112 -0
- data/vendor/faiss/faiss/impl/HNSW.cpp +35 -13
- data/vendor/faiss/faiss/impl/HNSW.h +5 -4
- data/vendor/faiss/faiss/impl/NNDescent.cpp +1 -1
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +519 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +78 -0
- data/vendor/faiss/faiss/impl/ResultHandler.h +2 -2
- data/vendor/faiss/faiss/impl/code_distance/code_distance-sve.h +3 -4
- data/vendor/faiss/faiss/impl/index_read.cpp +220 -25
- data/vendor/faiss/faiss/impl/index_write.cpp +29 -0
- data/vendor/faiss/faiss/impl/io.h +2 -2
- data/vendor/faiss/faiss/impl/io_macros.h +2 -0
- data/vendor/faiss/faiss/impl/mapped_io.cpp +313 -0
- data/vendor/faiss/faiss/impl/mapped_io.h +51 -0
- data/vendor/faiss/faiss/impl/maybe_owned_vector.h +316 -0
- data/vendor/faiss/faiss/impl/platform_macros.h +7 -3
- data/vendor/faiss/faiss/impl/simd_result_handlers.h +1 -1
- data/vendor/faiss/faiss/impl/zerocopy_io.cpp +67 -0
- data/vendor/faiss/faiss/impl/zerocopy_io.h +32 -0
- data/vendor/faiss/faiss/index_factory.cpp +16 -5
- data/vendor/faiss/faiss/index_io.h +4 -0
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +3 -3
- data/vendor/faiss/faiss/invlists/InvertedLists.h +5 -3
- data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +3 -3
- data/vendor/faiss/faiss/python/python_callbacks.cpp +24 -0
- data/vendor/faiss/faiss/python/python_callbacks.h +22 -0
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +30 -12
- data/vendor/faiss/faiss/utils/hamming.cpp +45 -21
- data/vendor/faiss/faiss/utils/hamming.h +7 -3
- data/vendor/faiss/faiss/utils/hamming_distance/avx512-inl.h +1 -1
- data/vendor/faiss/faiss/utils/utils.cpp +4 -4
- data/vendor/faiss/faiss/utils/utils.h +3 -3
- metadata +16 -4
@@ -19,6 +19,8 @@
|
|
19
19
|
#include <faiss/IndexAdditiveQuantizerFastScan.h>
|
20
20
|
#include <faiss/IndexBinary.h>
|
21
21
|
#include <faiss/IndexBinaryFlat.h>
|
22
|
+
#include <faiss/IndexBinaryHNSW.h>
|
23
|
+
#include <faiss/IndexBinaryIVF.h>
|
22
24
|
#include <faiss/IndexFlat.h>
|
23
25
|
#include <faiss/IndexHNSW.h>
|
24
26
|
#include <faiss/IndexIVF.h>
|
@@ -107,6 +109,11 @@ IndexIVF* Cloner::clone_IndexIVF(const IndexIVF* ivf) {
|
|
107
109
|
return nullptr;
|
108
110
|
}
|
109
111
|
|
112
|
+
IndexBinaryIVF* clone_IndexBinaryIVF(const IndexBinaryIVF* ivf) {
|
113
|
+
TRYCLONE(IndexBinaryIVF, ivf)
|
114
|
+
return nullptr;
|
115
|
+
}
|
116
|
+
|
110
117
|
IndexRefine* clone_IndexRefine(const IndexRefine* ir) {
|
111
118
|
TRYCLONE(IndexRefineFlat, ir)
|
112
119
|
TRYCLONE(IndexRefine, ir) {
|
@@ -131,6 +138,11 @@ IndexHNSW* clone_IndexHNSW(const IndexHNSW* ihnsw) {
|
|
131
138
|
}
|
132
139
|
}
|
133
140
|
|
141
|
+
IndexBinaryHNSW* clone_IndexBinaryHNSW(const IndexBinaryHNSW* ihnsw) {
|
142
|
+
TRYCLONE(IndexBinaryHNSW, ihnsw)
|
143
|
+
return nullptr;
|
144
|
+
}
|
145
|
+
|
134
146
|
IndexNNDescent* clone_IndexNNDescent(const IndexNNDescent* innd) {
|
135
147
|
TRYCLONE(IndexNNDescentFlat, innd)
|
136
148
|
TRYCLONE(IndexNNDescent, innd) {
|
@@ -323,9 +335,10 @@ Index* Cloner::clone_Index(const Index* index) {
|
|
323
335
|
IndexNSG* res = clone_IndexNSG(insg);
|
324
336
|
|
325
337
|
// copy the dynamic allocated graph
|
326
|
-
auto&
|
327
|
-
|
328
|
-
|
338
|
+
if (auto& old_graph = insg->nsg.final_graph) {
|
339
|
+
auto& new_graph = res->nsg.final_graph;
|
340
|
+
new_graph = std::make_shared<nsg::Graph<int>>(*old_graph);
|
341
|
+
}
|
329
342
|
|
330
343
|
res->own_fields = true;
|
331
344
|
res->storage = clone_Index(insg->storage);
|
@@ -385,6 +398,28 @@ Quantizer* clone_Quantizer(const Quantizer* quant) {
|
|
385
398
|
IndexBinary* clone_binary_index(const IndexBinary* index) {
|
386
399
|
if (auto ii = dynamic_cast<const IndexBinaryFlat*>(index)) {
|
387
400
|
return new IndexBinaryFlat(*ii);
|
401
|
+
} else if (
|
402
|
+
const IndexBinaryIVF* ivf =
|
403
|
+
dynamic_cast<const IndexBinaryIVF*>(index)) {
|
404
|
+
IndexBinaryIVF* res = clone_IndexBinaryIVF(ivf);
|
405
|
+
if (ivf->invlists == nullptr) {
|
406
|
+
res->invlists = nullptr;
|
407
|
+
} else {
|
408
|
+
res->invlists = clone_InvertedLists(ivf->invlists);
|
409
|
+
res->own_invlists = true;
|
410
|
+
}
|
411
|
+
|
412
|
+
res->own_fields = true;
|
413
|
+
res->quantizer = clone_binary_index(ivf->quantizer);
|
414
|
+
|
415
|
+
return res;
|
416
|
+
} else if (
|
417
|
+
const IndexBinaryHNSW* ihnsw =
|
418
|
+
dynamic_cast<const IndexBinaryHNSW*>(index)) {
|
419
|
+
IndexBinaryHNSW* res = clone_IndexBinaryHNSW(ihnsw);
|
420
|
+
res->own_fields = true;
|
421
|
+
res->storage = clone_binary_index(ihnsw->storage);
|
422
|
+
return res;
|
388
423
|
} else {
|
389
424
|
FAISS_THROW_MSG("cannot clone this type of index");
|
390
425
|
}
|
@@ -8,8 +8,22 @@
|
|
8
8
|
// -*- c++ -*-
|
9
9
|
|
10
10
|
#include <faiss/cppcontrib/factory_tools.h>
|
11
|
+
|
11
12
|
#include <map>
|
12
13
|
|
14
|
+
#include <faiss/IndexBinaryFlat.h>
|
15
|
+
#include <faiss/IndexBinaryHNSW.h>
|
16
|
+
#include <faiss/IndexBinaryIVF.h>
|
17
|
+
#include <faiss/IndexHNSW.h>
|
18
|
+
#include <faiss/IndexIDMap.h>
|
19
|
+
#include <faiss/IndexIVFFlat.h>
|
20
|
+
#include <faiss/IndexIVFPQFastScan.h>
|
21
|
+
#include <faiss/IndexLSH.h>
|
22
|
+
#include <faiss/IndexNSG.h>
|
23
|
+
#include <faiss/IndexPQFastScan.h>
|
24
|
+
#include <faiss/IndexPreTransform.h>
|
25
|
+
#include <faiss/IndexRefine.h>
|
26
|
+
|
13
27
|
namespace faiss {
|
14
28
|
|
15
29
|
namespace {
|
@@ -122,6 +136,11 @@ std::string reverse_index_factory(const faiss::Index* index) {
|
|
122
136
|
const faiss::IndexHNSW* hnsw_index =
|
123
137
|
dynamic_cast<const faiss::IndexHNSW*>(index)) {
|
124
138
|
return "HNSW" + std::to_string(get_hnsw_M(hnsw_index));
|
139
|
+
} else if (
|
140
|
+
const faiss::IndexNSG* nsg_index =
|
141
|
+
dynamic_cast<const faiss::IndexNSG*>(index)) {
|
142
|
+
return "NSG" + std::to_string(nsg_index->nsg.R) + "," +
|
143
|
+
reverse_index_factory(nsg_index->storage);
|
125
144
|
} else if (
|
126
145
|
const faiss::IndexRefine* refine_index =
|
127
146
|
dynamic_cast<const faiss::IndexRefine*>(index)) {
|
@@ -9,20 +9,13 @@
|
|
9
9
|
|
10
10
|
#pragma once
|
11
11
|
|
12
|
-
#include <
|
13
|
-
#include <faiss/IndexBinaryHNSW.h>
|
14
|
-
#include <faiss/IndexBinaryIVF.h>
|
15
|
-
#include <faiss/IndexHNSW.h>
|
16
|
-
#include <faiss/IndexIDMap.h>
|
17
|
-
#include <faiss/IndexIVFFlat.h>
|
18
|
-
#include <faiss/IndexIVFPQFastScan.h>
|
19
|
-
#include <faiss/IndexLSH.h>
|
20
|
-
#include <faiss/IndexPQFastScan.h>
|
21
|
-
#include <faiss/IndexPreTransform.h>
|
22
|
-
#include <faiss/IndexRefine.h>
|
12
|
+
#include <string>
|
23
13
|
|
24
14
|
namespace faiss {
|
25
15
|
|
16
|
+
struct Index;
|
17
|
+
struct IndexBinary;
|
18
|
+
|
26
19
|
std::string reverse_index_factory(const faiss::Index* index);
|
27
20
|
std::string reverse_index_factory(const faiss::IndexBinary* index);
|
28
21
|
|
@@ -28,7 +28,8 @@ using namespace ::faiss;
|
|
28
28
|
* Parameters to auto-tune on GpuIndex'es
|
29
29
|
**********************************************************/
|
30
30
|
|
31
|
-
#define DC(classname)
|
31
|
+
#define DC(classname) \
|
32
|
+
[[maybe_unused]] auto ix = dynamic_cast<const classname*>(index)
|
32
33
|
|
33
34
|
void GpuParameterSpace::initialize(const Index* index) {
|
34
35
|
if (DC(IndexPreTransform)) {
|
@@ -173,8 +173,8 @@ struct GpuIndexCagraConfig : public GpuIndexConfig {
|
|
173
173
|
/// Number of Iterations to run if building with NN_DESCENT
|
174
174
|
size_t nn_descent_niter = 20;
|
175
175
|
|
176
|
-
IVFPQBuildCagraConfig
|
177
|
-
IVFPQSearchCagraConfig
|
176
|
+
std::shared_ptr<IVFPQBuildCagraConfig> ivf_pq_params{nullptr};
|
177
|
+
std::shared_ptr<IVFPQSearchCagraConfig> ivf_pq_search_params{nullptr};
|
178
178
|
float refine_rate = 2.0f;
|
179
179
|
bool store_dataset = true;
|
180
180
|
};
|
@@ -245,7 +245,17 @@ struct GpuIndexCagra : public GpuIndex {
|
|
245
245
|
faiss::MetricType metric = faiss::METRIC_L2,
|
246
246
|
GpuIndexCagraConfig config = GpuIndexCagraConfig());
|
247
247
|
|
248
|
-
/// Trains CAGRA based on the given vector data
|
248
|
+
/// Trains CAGRA based on the given vector data and add them along with ids.
|
249
|
+
/// NB: The use of the add function here is to build the CAGRA graph on
|
250
|
+
/// the base dataset. Use this function when you want to add vectors with
|
251
|
+
/// ids. Ref: https://github.com/facebookresearch/faiss/issues/4107
|
252
|
+
void add(idx_t n, const float* x) override;
|
253
|
+
|
254
|
+
/// Trains CAGRA based on the given vector data.
|
255
|
+
/// NB: The use of the train function here is to build the CAGRA graph on
|
256
|
+
/// the base dataset and is currently the only function to add the full set
|
257
|
+
/// of vectors (without IDs) to the index. There is no external quantizer to
|
258
|
+
/// be trained here.
|
249
259
|
void train(idx_t n, const float* x) override;
|
250
260
|
|
251
261
|
/// Initialize ourselves from the given CPU index; will overwrite
|
@@ -411,7 +411,7 @@ void StandardGpuResourcesImpl::initializeForDevice(int device) {
|
|
411
411
|
raftHandles_.emplace(std::make_pair(device, defaultStream));
|
412
412
|
#endif
|
413
413
|
|
414
|
-
cudaStream_t asyncCopyStream =
|
414
|
+
cudaStream_t asyncCopyStream = nullptr;
|
415
415
|
CUDA_VERIFY(
|
416
416
|
cudaStreamCreateWithFlags(&asyncCopyStream, cudaStreamNonBlocking));
|
417
417
|
|
@@ -162,7 +162,7 @@ class StandardGpuResourcesImpl : public GpuResources {
|
|
162
162
|
/**
|
163
163
|
* FIXME: Integrating these in a separate code path for now. Ultimately,
|
164
164
|
* it would be nice if we use a simple memory resource abstraction
|
165
|
-
* in
|
165
|
+
* in Faiss so we could plug in whether to use RMM's memory resources
|
166
166
|
* or the default.
|
167
167
|
*
|
168
168
|
* There's enough duplicated logic that it doesn't *seem* to make sense
|
@@ -0,0 +1,112 @@
|
|
1
|
+
#include <faiss/gpu/GpuIcmEncoder.h>
|
2
|
+
#include <faiss/gpu/StandardGpuResources.h>
|
3
|
+
#include <faiss/gpu/test/TestUtils.h>
|
4
|
+
#include <faiss/impl/LocalSearchQuantizer.h>
|
5
|
+
|
6
|
+
#include <gtest/gtest.h>
|
7
|
+
#include <tuple>
|
8
|
+
#include <vector>
|
9
|
+
|
10
|
+
using faiss::LocalSearchQuantizer;
|
11
|
+
using faiss::gpu::GpuIcmEncoder;
|
12
|
+
using faiss::gpu::GpuResourcesProvider;
|
13
|
+
using faiss::gpu::StandardGpuResources;
|
14
|
+
|
15
|
+
struct ShardingTestParams {
|
16
|
+
size_t n;
|
17
|
+
size_t nshards;
|
18
|
+
};
|
19
|
+
|
20
|
+
class GpuIcmEncoderShardingTest
|
21
|
+
: public ::testing::TestWithParam<ShardingTestParams> {
|
22
|
+
protected:
|
23
|
+
void SetUp() override {
|
24
|
+
params = GetParam();
|
25
|
+
|
26
|
+
lsq.M = 4;
|
27
|
+
lsq.K = 16;
|
28
|
+
lsq.d = 32;
|
29
|
+
|
30
|
+
std::uniform_real_distribution<float> dist(-1.0f, 1.0f);
|
31
|
+
lsq.codebooks.resize(lsq.M * lsq.K * lsq.d);
|
32
|
+
for (auto& v : lsq.codebooks) {
|
33
|
+
v = dist(gen);
|
34
|
+
}
|
35
|
+
|
36
|
+
x.resize(params.n * lsq.d);
|
37
|
+
codes.resize(params.n * lsq.M);
|
38
|
+
|
39
|
+
for (auto& v : x) {
|
40
|
+
v = dist(gen);
|
41
|
+
}
|
42
|
+
|
43
|
+
std::uniform_int_distribution<int32_t> codeDist(0, lsq.K - 1);
|
44
|
+
for (auto& c : codes) {
|
45
|
+
c = codeDist(gen);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
LocalSearchQuantizer lsq;
|
50
|
+
std::vector<float> x;
|
51
|
+
std::vector<int32_t> codes;
|
52
|
+
std::mt19937 gen;
|
53
|
+
ShardingTestParams params;
|
54
|
+
static constexpr size_t ils_iters = 4;
|
55
|
+
};
|
56
|
+
|
57
|
+
TEST_P(GpuIcmEncoderShardingTest, DataShardingCorrectness) {
|
58
|
+
std::vector<StandardGpuResources> resources(params.nshards);
|
59
|
+
std::vector<GpuResourcesProvider*> provs;
|
60
|
+
std::vector<int> devices;
|
61
|
+
|
62
|
+
for (size_t i = 0; i < params.nshards; ++i) {
|
63
|
+
resources[i].noTempMemory();
|
64
|
+
provs.push_back(&resources[i]);
|
65
|
+
devices.push_back(0); // use GPU 0 for testing all shards
|
66
|
+
}
|
67
|
+
|
68
|
+
GpuIcmEncoder encoder(&lsq, provs, devices);
|
69
|
+
encoder.set_binary_term();
|
70
|
+
|
71
|
+
gen.seed(42);
|
72
|
+
EXPECT_NO_THROW(
|
73
|
+
encoder.encode(codes.data(), x.data(), gen, params.n, ils_iters));
|
74
|
+
|
75
|
+
for (auto c : codes) {
|
76
|
+
EXPECT_GE(c, 0);
|
77
|
+
EXPECT_LT(c, lsq.K);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
std::vector<ShardingTestParams> GetShardingTestCases() {
|
82
|
+
return {
|
83
|
+
{1, 8},
|
84
|
+
|
85
|
+
{5, 4},
|
86
|
+
|
87
|
+
{10, 2},
|
88
|
+
{10, 3},
|
89
|
+
{10, 5},
|
90
|
+
{10, 8},
|
91
|
+
|
92
|
+
{20, 8},
|
93
|
+
};
|
94
|
+
}
|
95
|
+
|
96
|
+
INSTANTIATE_TEST_SUITE_P(
|
97
|
+
MultiGpuShardingTests,
|
98
|
+
GpuIcmEncoderShardingTest,
|
99
|
+
::testing::ValuesIn(GetShardingTestCases()),
|
100
|
+
[](const ::testing::TestParamInfo<ShardingTestParams>& info) {
|
101
|
+
return "n" + std::to_string(info.param.n) + "_shards" +
|
102
|
+
std::to_string(info.param.nshards);
|
103
|
+
});
|
104
|
+
|
105
|
+
int main(int argc, char** argv) {
|
106
|
+
testing::InitGoogleTest(&argc, argv);
|
107
|
+
|
108
|
+
// just run with a fixed test seed
|
109
|
+
faiss::gpu::setTestSeed(100);
|
110
|
+
|
111
|
+
return RUN_ALL_TESTS();
|
112
|
+
}
|
@@ -8,7 +8,6 @@
|
|
8
8
|
#include <faiss/impl/HNSW.h>
|
9
9
|
|
10
10
|
#include <cstddef>
|
11
|
-
#include <string>
|
12
11
|
|
13
12
|
#include <faiss/impl/AuxIndexStructures.h>
|
14
13
|
#include <faiss/impl/DistanceComputer.h>
|
@@ -32,6 +31,7 @@ namespace faiss {
|
|
32
31
|
**************************************************************/
|
33
32
|
|
34
33
|
int HNSW::nb_neighbors(int layer_no) const {
|
34
|
+
FAISS_THROW_IF_NOT(layer_no + 1 < cum_nneighbor_per_level.size());
|
35
35
|
return cum_nneighbor_per_level[layer_no + 1] -
|
36
36
|
cum_nneighbor_per_level[layer_no];
|
37
37
|
}
|
@@ -590,15 +590,22 @@ int search_from_candidates(
|
|
590
590
|
HNSWStats& stats,
|
591
591
|
int level,
|
592
592
|
int nres_in,
|
593
|
-
const
|
593
|
+
const SearchParameters* params) {
|
594
594
|
int nres = nres_in;
|
595
595
|
int ndis = 0;
|
596
596
|
|
597
597
|
// can be overridden by search params
|
598
|
-
bool do_dis_check =
|
599
|
-
|
600
|
-
|
601
|
-
|
598
|
+
bool do_dis_check = hnsw.check_relative_distance;
|
599
|
+
int efSearch = hnsw.efSearch;
|
600
|
+
const IDSelector* sel = nullptr;
|
601
|
+
if (params) {
|
602
|
+
if (const SearchParametersHNSW* hnsw_params =
|
603
|
+
dynamic_cast<const SearchParametersHNSW*>(params)) {
|
604
|
+
do_dis_check = hnsw_params->check_relative_distance;
|
605
|
+
efSearch = hnsw_params->efSearch;
|
606
|
+
}
|
607
|
+
sel = params->sel;
|
608
|
+
}
|
602
609
|
|
603
610
|
C::T threshold = res.threshold;
|
604
611
|
for (int i = 0; i < candidates.size(); i++) {
|
@@ -920,15 +927,22 @@ HNSWStats HNSW::search(
|
|
920
927
|
DistanceComputer& qdis,
|
921
928
|
ResultHandler<C>& res,
|
922
929
|
VisitedTable& vt,
|
923
|
-
const
|
930
|
+
const SearchParameters* params) const {
|
924
931
|
HNSWStats stats;
|
925
932
|
if (entry_point == -1) {
|
926
933
|
return stats;
|
927
934
|
}
|
928
935
|
int k = extract_k_from_ResultHandler(res);
|
929
936
|
|
930
|
-
bool bounded_queue =
|
931
|
-
|
937
|
+
bool bounded_queue = this->search_bounded_queue;
|
938
|
+
int efSearch = this->efSearch;
|
939
|
+
if (params) {
|
940
|
+
if (const SearchParametersHNSW* hnsw_params =
|
941
|
+
dynamic_cast<const SearchParametersHNSW*>(params)) {
|
942
|
+
bounded_queue = hnsw_params->bounded_queue;
|
943
|
+
efSearch = hnsw_params->efSearch;
|
944
|
+
}
|
945
|
+
}
|
932
946
|
|
933
947
|
// greedy search on upper levels
|
934
948
|
storage_idx_t nearest = entry_point;
|
@@ -940,7 +954,7 @@ HNSWStats HNSW::search(
|
|
940
954
|
stats.combine(local_stats);
|
941
955
|
}
|
942
956
|
|
943
|
-
int ef = std::max(
|
957
|
+
int ef = std::max(efSearch, k);
|
944
958
|
if (bounded_queue) { // this is the most common branch
|
945
959
|
MinimaxHeap candidates(ef);
|
946
960
|
|
@@ -980,9 +994,17 @@ void HNSW::search_level_0(
|
|
980
994
|
int search_type,
|
981
995
|
HNSWStats& search_stats,
|
982
996
|
VisitedTable& vt,
|
983
|
-
const
|
997
|
+
const SearchParameters* params) const {
|
984
998
|
const HNSW& hnsw = *this;
|
985
|
-
|
999
|
+
|
1000
|
+
auto efSearch = hnsw.efSearch;
|
1001
|
+
if (params) {
|
1002
|
+
if (const SearchParametersHNSW* hnsw_params =
|
1003
|
+
dynamic_cast<const SearchParametersHNSW*>(params)) {
|
1004
|
+
efSearch = hnsw_params->efSearch;
|
1005
|
+
}
|
1006
|
+
}
|
1007
|
+
|
986
1008
|
int k = extract_k_from_ResultHandler(res);
|
987
1009
|
|
988
1010
|
if (search_type == 1) {
|
@@ -1062,7 +1084,7 @@ void HNSW::permute_entries(const idx_t* map) {
|
|
1062
1084
|
// swap everyone
|
1063
1085
|
std::swap(levels, new_levels);
|
1064
1086
|
std::swap(offsets, new_offsets);
|
1065
|
-
std::
|
1087
|
+
neighbors = std::move(new_neighbors);
|
1066
1088
|
}
|
1067
1089
|
|
1068
1090
|
/**************************************************************
|
@@ -15,6 +15,7 @@
|
|
15
15
|
|
16
16
|
#include <faiss/Index.h>
|
17
17
|
#include <faiss/impl/FaissAssert.h>
|
18
|
+
#include <faiss/impl/maybe_owned_vector.h>
|
18
19
|
#include <faiss/impl/platform_macros.h>
|
19
20
|
#include <faiss/utils/Heap.h>
|
20
21
|
#include <faiss/utils/random.h>
|
@@ -121,7 +122,7 @@ struct HNSW {
|
|
121
122
|
|
122
123
|
/// neighbors[offsets[i]:offsets[i+1]] is the list of neighbors of vector i
|
123
124
|
/// for all levels. this is where all storage goes.
|
124
|
-
|
125
|
+
MaybeOwnedVector<storage_idx_t> neighbors;
|
125
126
|
|
126
127
|
/// entry point in the search structure (one of the points with maximum
|
127
128
|
/// level
|
@@ -200,7 +201,7 @@ struct HNSW {
|
|
200
201
|
DistanceComputer& qdis,
|
201
202
|
ResultHandler<C>& res,
|
202
203
|
VisitedTable& vt,
|
203
|
-
const
|
204
|
+
const SearchParameters* params = nullptr) const;
|
204
205
|
|
205
206
|
/// search only in level 0 from a given vertex
|
206
207
|
void search_level_0(
|
@@ -212,7 +213,7 @@ struct HNSW {
|
|
212
213
|
int search_type,
|
213
214
|
HNSWStats& search_stats,
|
214
215
|
VisitedTable& vt,
|
215
|
-
const
|
216
|
+
const SearchParameters* params = nullptr) const;
|
216
217
|
|
217
218
|
void reset();
|
218
219
|
|
@@ -264,7 +265,7 @@ int search_from_candidates(
|
|
264
265
|
HNSWStats& stats,
|
265
266
|
int level,
|
266
267
|
int nres_in = 0,
|
267
|
-
const
|
268
|
+
const SearchParameters* params = nullptr);
|
268
269
|
|
269
270
|
HNSWStats greedy_update_nearest(
|
270
271
|
const HNSW& hnsw,
|
@@ -400,7 +400,7 @@ void NNDescent::build(DistanceComputer& qdis, const int n, bool verbose) {
|
|
400
400
|
init_graph(qdis);
|
401
401
|
nndescent(qdis, verbose);
|
402
402
|
|
403
|
-
final_graph.resize(ntotal * K);
|
403
|
+
final_graph.resize(uint64_t(ntotal) * K);
|
404
404
|
|
405
405
|
// Store the neighbor link structure into final_graph
|
406
406
|
// Clear the old graph
|