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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/lib/faiss/version.rb +1 -1
  4. data/vendor/faiss/faiss/AutoTune.cpp +11 -8
  5. data/vendor/faiss/faiss/Clustering.cpp +0 -16
  6. data/vendor/faiss/faiss/IVFlib.cpp +213 -0
  7. data/vendor/faiss/faiss/IVFlib.h +42 -0
  8. data/vendor/faiss/faiss/Index.h +1 -1
  9. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +9 -7
  10. data/vendor/faiss/faiss/IndexBinaryFlat.h +2 -1
  11. data/vendor/faiss/faiss/IndexFlatCodes.cpp +1 -1
  12. data/vendor/faiss/faiss/IndexFlatCodes.h +4 -2
  13. data/vendor/faiss/faiss/IndexHNSW.cpp +13 -20
  14. data/vendor/faiss/faiss/IndexHNSW.h +1 -1
  15. data/vendor/faiss/faiss/IndexIVF.cpp +20 -3
  16. data/vendor/faiss/faiss/IndexIVF.h +5 -2
  17. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +2 -1
  18. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +2 -1
  19. data/vendor/faiss/faiss/IndexIVFFlat.cpp +2 -1
  20. data/vendor/faiss/faiss/IndexIVFFlat.h +2 -1
  21. data/vendor/faiss/faiss/IndexIVFPQ.cpp +2 -1
  22. data/vendor/faiss/faiss/IndexIVFPQ.h +2 -1
  23. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +277 -0
  24. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +70 -0
  25. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +2 -1
  26. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +2 -1
  27. data/vendor/faiss/faiss/IndexRaBitQ.cpp +148 -0
  28. data/vendor/faiss/faiss/IndexRaBitQ.h +65 -0
  29. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +2 -1
  30. data/vendor/faiss/faiss/IndexScalarQuantizer.h +2 -1
  31. data/vendor/faiss/faiss/clone_index.cpp +38 -3
  32. data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +19 -0
  33. data/vendor/faiss/faiss/cppcontrib/factory_tools.h +4 -11
  34. data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +2 -1
  35. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +13 -3
  36. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +1 -1
  37. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +1 -1
  38. data/vendor/faiss/faiss/gpu/test/TestGpuIcmEncoder.cpp +112 -0
  39. data/vendor/faiss/faiss/impl/HNSW.cpp +35 -13
  40. data/vendor/faiss/faiss/impl/HNSW.h +5 -4
  41. data/vendor/faiss/faiss/impl/NNDescent.cpp +1 -1
  42. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +519 -0
  43. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +78 -0
  44. data/vendor/faiss/faiss/impl/ResultHandler.h +2 -2
  45. data/vendor/faiss/faiss/impl/code_distance/code_distance-sve.h +3 -4
  46. data/vendor/faiss/faiss/impl/index_read.cpp +220 -25
  47. data/vendor/faiss/faiss/impl/index_write.cpp +29 -0
  48. data/vendor/faiss/faiss/impl/io.h +2 -2
  49. data/vendor/faiss/faiss/impl/io_macros.h +2 -0
  50. data/vendor/faiss/faiss/impl/mapped_io.cpp +313 -0
  51. data/vendor/faiss/faiss/impl/mapped_io.h +51 -0
  52. data/vendor/faiss/faiss/impl/maybe_owned_vector.h +316 -0
  53. data/vendor/faiss/faiss/impl/platform_macros.h +7 -3
  54. data/vendor/faiss/faiss/impl/simd_result_handlers.h +1 -1
  55. data/vendor/faiss/faiss/impl/zerocopy_io.cpp +67 -0
  56. data/vendor/faiss/faiss/impl/zerocopy_io.h +32 -0
  57. data/vendor/faiss/faiss/index_factory.cpp +16 -5
  58. data/vendor/faiss/faiss/index_io.h +4 -0
  59. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +3 -3
  60. data/vendor/faiss/faiss/invlists/InvertedLists.h +5 -3
  61. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +3 -3
  62. data/vendor/faiss/faiss/python/python_callbacks.cpp +24 -0
  63. data/vendor/faiss/faiss/python/python_callbacks.h +22 -0
  64. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +30 -12
  65. data/vendor/faiss/faiss/utils/hamming.cpp +45 -21
  66. data/vendor/faiss/faiss/utils/hamming.h +7 -3
  67. data/vendor/faiss/faiss/utils/hamming_distance/avx512-inl.h +1 -1
  68. data/vendor/faiss/faiss/utils/utils.cpp +4 -4
  69. data/vendor/faiss/faiss/utils/utils.h +3 -3
  70. 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& new_graph = res->nsg.final_graph;
327
- auto& old_graph = insg->nsg.final_graph;
328
- new_graph = std::make_shared<nsg::Graph<int>>(*old_graph);
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 <faiss/IndexBinaryFlat.h>
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) auto ix = dynamic_cast<const classname*>(index)
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* ivf_pq_params = nullptr;
177
- IVFPQSearchCagraConfig* ivf_pq_search_params = nullptr;
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 = 0;
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 FAISS so we could plug in whether to use RMM's memory resources
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 SearchParametersHNSW* params) {
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 = params ? params->check_relative_distance
599
- : hnsw.check_relative_distance;
600
- int efSearch = params ? params->efSearch : hnsw.efSearch;
601
- const IDSelector* sel = params ? params->sel : nullptr;
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 SearchParametersHNSW* params) 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
- params ? params->bounded_queue : this->search_bounded_queue;
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(params ? params->efSearch : efSearch, k);
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 SearchParametersHNSW* params) const {
997
+ const SearchParameters* params) const {
984
998
  const HNSW& hnsw = *this;
985
- auto efSearch = params ? params->efSearch : hnsw.efSearch;
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::swap(neighbors, new_neighbors);
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
- std::vector<storage_idx_t> neighbors;
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 SearchParametersHNSW* params = nullptr) 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 SearchParametersHNSW* params = nullptr) 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 SearchParametersHNSW* params = nullptr);
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