faiss 0.1.2 → 0.1.3

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 (192) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/ext/faiss/extconf.rb +1 -1
  4. data/lib/faiss/version.rb +1 -1
  5. data/vendor/faiss/benchs/bench_6bit_codec.cpp +80 -0
  6. data/vendor/faiss/c_api/AutoTune_c.h +2 -0
  7. data/vendor/faiss/c_api/IndexShards_c.cpp +0 -6
  8. data/vendor/faiss/c_api/IndexShards_c.h +1 -4
  9. data/vendor/faiss/c_api/gpu/GpuAutoTune_c.cpp +4 -2
  10. data/vendor/faiss/c_api/gpu/GpuClonerOptions_c.cpp +1 -1
  11. data/vendor/faiss/c_api/gpu/GpuIndex_c.cpp +1 -1
  12. data/vendor/faiss/c_api/gpu/GpuResources_c.cpp +1 -1
  13. data/vendor/faiss/c_api/gpu/StandardGpuResources_c.cpp +1 -1
  14. data/vendor/faiss/demos/demo_imi_flat.cpp +5 -2
  15. data/vendor/faiss/demos/demo_imi_pq.cpp +6 -2
  16. data/vendor/faiss/demos/demo_ivfpq_indexing.cpp +7 -2
  17. data/vendor/faiss/{AutoTune.cpp → faiss/AutoTune.cpp} +9 -9
  18. data/vendor/faiss/{AutoTune.h → faiss/AutoTune.h} +0 -0
  19. data/vendor/faiss/{Clustering.cpp → faiss/Clustering.cpp} +13 -12
  20. data/vendor/faiss/{Clustering.h → faiss/Clustering.h} +0 -0
  21. data/vendor/faiss/{DirectMap.cpp → faiss/DirectMap.cpp} +0 -0
  22. data/vendor/faiss/{DirectMap.h → faiss/DirectMap.h} +0 -0
  23. data/vendor/faiss/{IVFlib.cpp → faiss/IVFlib.cpp} +86 -11
  24. data/vendor/faiss/{IVFlib.h → faiss/IVFlib.h} +26 -8
  25. data/vendor/faiss/{Index.cpp → faiss/Index.cpp} +0 -0
  26. data/vendor/faiss/{Index.h → faiss/Index.h} +1 -1
  27. data/vendor/faiss/{Index2Layer.cpp → faiss/Index2Layer.cpp} +12 -11
  28. data/vendor/faiss/{Index2Layer.h → faiss/Index2Layer.h} +0 -0
  29. data/vendor/faiss/{IndexBinary.cpp → faiss/IndexBinary.cpp} +2 -1
  30. data/vendor/faiss/{IndexBinary.h → faiss/IndexBinary.h} +0 -0
  31. data/vendor/faiss/{IndexBinaryFlat.cpp → faiss/IndexBinaryFlat.cpp} +0 -0
  32. data/vendor/faiss/{IndexBinaryFlat.h → faiss/IndexBinaryFlat.h} +0 -0
  33. data/vendor/faiss/{IndexBinaryFromFloat.cpp → faiss/IndexBinaryFromFloat.cpp} +1 -0
  34. data/vendor/faiss/{IndexBinaryFromFloat.h → faiss/IndexBinaryFromFloat.h} +0 -0
  35. data/vendor/faiss/{IndexBinaryHNSW.cpp → faiss/IndexBinaryHNSW.cpp} +1 -2
  36. data/vendor/faiss/{IndexBinaryHNSW.h → faiss/IndexBinaryHNSW.h} +0 -0
  37. data/vendor/faiss/{IndexBinaryHash.cpp → faiss/IndexBinaryHash.cpp} +16 -7
  38. data/vendor/faiss/{IndexBinaryHash.h → faiss/IndexBinaryHash.h} +2 -1
  39. data/vendor/faiss/{IndexBinaryIVF.cpp → faiss/IndexBinaryIVF.cpp} +10 -16
  40. data/vendor/faiss/{IndexBinaryIVF.h → faiss/IndexBinaryIVF.h} +1 -1
  41. data/vendor/faiss/{IndexFlat.cpp → faiss/IndexFlat.cpp} +0 -0
  42. data/vendor/faiss/{IndexFlat.h → faiss/IndexFlat.h} +0 -0
  43. data/vendor/faiss/{IndexHNSW.cpp → faiss/IndexHNSW.cpp} +63 -32
  44. data/vendor/faiss/{IndexHNSW.h → faiss/IndexHNSW.h} +0 -0
  45. data/vendor/faiss/{IndexIVF.cpp → faiss/IndexIVF.cpp} +129 -46
  46. data/vendor/faiss/{IndexIVF.h → faiss/IndexIVF.h} +7 -3
  47. data/vendor/faiss/{IndexIVFFlat.cpp → faiss/IndexIVFFlat.cpp} +6 -5
  48. data/vendor/faiss/{IndexIVFFlat.h → faiss/IndexIVFFlat.h} +0 -0
  49. data/vendor/faiss/{IndexIVFPQ.cpp → faiss/IndexIVFPQ.cpp} +9 -8
  50. data/vendor/faiss/{IndexIVFPQ.h → faiss/IndexIVFPQ.h} +4 -2
  51. data/vendor/faiss/{IndexIVFPQR.cpp → faiss/IndexIVFPQR.cpp} +3 -1
  52. data/vendor/faiss/{IndexIVFPQR.h → faiss/IndexIVFPQR.h} +0 -0
  53. data/vendor/faiss/{IndexIVFSpectralHash.cpp → faiss/IndexIVFSpectralHash.cpp} +1 -1
  54. data/vendor/faiss/{IndexIVFSpectralHash.h → faiss/IndexIVFSpectralHash.h} +0 -0
  55. data/vendor/faiss/{IndexLSH.cpp → faiss/IndexLSH.cpp} +0 -0
  56. data/vendor/faiss/{IndexLSH.h → faiss/IndexLSH.h} +0 -0
  57. data/vendor/faiss/{IndexLattice.cpp → faiss/IndexLattice.cpp} +0 -0
  58. data/vendor/faiss/{IndexLattice.h → faiss/IndexLattice.h} +0 -0
  59. data/vendor/faiss/{IndexPQ.cpp → faiss/IndexPQ.cpp} +6 -6
  60. data/vendor/faiss/{IndexPQ.h → faiss/IndexPQ.h} +3 -1
  61. data/vendor/faiss/{IndexPreTransform.cpp → faiss/IndexPreTransform.cpp} +0 -0
  62. data/vendor/faiss/{IndexPreTransform.h → faiss/IndexPreTransform.h} +0 -0
  63. data/vendor/faiss/{IndexReplicas.cpp → faiss/IndexReplicas.cpp} +102 -10
  64. data/vendor/faiss/{IndexReplicas.h → faiss/IndexReplicas.h} +6 -0
  65. data/vendor/faiss/{IndexScalarQuantizer.cpp → faiss/IndexScalarQuantizer.cpp} +3 -3
  66. data/vendor/faiss/{IndexScalarQuantizer.h → faiss/IndexScalarQuantizer.h} +0 -0
  67. data/vendor/faiss/{IndexShards.cpp → faiss/IndexShards.cpp} +37 -12
  68. data/vendor/faiss/{IndexShards.h → faiss/IndexShards.h} +3 -4
  69. data/vendor/faiss/{InvertedLists.cpp → faiss/InvertedLists.cpp} +2 -2
  70. data/vendor/faiss/{InvertedLists.h → faiss/InvertedLists.h} +1 -0
  71. data/vendor/faiss/{MatrixStats.cpp → faiss/MatrixStats.cpp} +0 -0
  72. data/vendor/faiss/{MatrixStats.h → faiss/MatrixStats.h} +0 -0
  73. data/vendor/faiss/{MetaIndexes.cpp → faiss/MetaIndexes.cpp} +5 -3
  74. data/vendor/faiss/{MetaIndexes.h → faiss/MetaIndexes.h} +0 -0
  75. data/vendor/faiss/{MetricType.h → faiss/MetricType.h} +0 -0
  76. data/vendor/faiss/{OnDiskInvertedLists.cpp → faiss/OnDiskInvertedLists.cpp} +141 -3
  77. data/vendor/faiss/{OnDiskInvertedLists.h → faiss/OnDiskInvertedLists.h} +27 -7
  78. data/vendor/faiss/{VectorTransform.cpp → faiss/VectorTransform.cpp} +4 -3
  79. data/vendor/faiss/{VectorTransform.h → faiss/VectorTransform.h} +0 -0
  80. data/vendor/faiss/{clone_index.cpp → faiss/clone_index.cpp} +0 -0
  81. data/vendor/faiss/{clone_index.h → faiss/clone_index.h} +0 -0
  82. data/vendor/faiss/{gpu → faiss/gpu}/GpuAutoTune.cpp +0 -0
  83. data/vendor/faiss/{gpu → faiss/gpu}/GpuAutoTune.h +0 -0
  84. data/vendor/faiss/{gpu → faiss/gpu}/GpuCloner.cpp +14 -14
  85. data/vendor/faiss/{gpu → faiss/gpu}/GpuCloner.h +6 -7
  86. data/vendor/faiss/{gpu → faiss/gpu}/GpuClonerOptions.cpp +0 -0
  87. data/vendor/faiss/{gpu → faiss/gpu}/GpuClonerOptions.h +0 -0
  88. data/vendor/faiss/{gpu → faiss/gpu}/GpuDistance.h +12 -4
  89. data/vendor/faiss/{gpu → faiss/gpu}/GpuFaissAssert.h +0 -0
  90. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndex.h +3 -9
  91. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndexBinaryFlat.h +7 -7
  92. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndexFlat.h +35 -10
  93. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndexIVF.h +1 -2
  94. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndexIVFFlat.h +4 -3
  95. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndexIVFPQ.h +21 -4
  96. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndexIVFScalarQuantizer.h +4 -3
  97. data/vendor/faiss/{gpu → faiss/gpu}/GpuIndicesOptions.h +0 -0
  98. data/vendor/faiss/faiss/gpu/GpuResources.cpp +200 -0
  99. data/vendor/faiss/faiss/gpu/GpuResources.h +264 -0
  100. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +572 -0
  101. data/vendor/faiss/{gpu → faiss/gpu}/StandardGpuResources.h +83 -15
  102. data/vendor/faiss/{gpu → faiss/gpu}/impl/RemapIndices.cpp +0 -0
  103. data/vendor/faiss/{gpu → faiss/gpu}/impl/RemapIndices.h +0 -0
  104. data/vendor/faiss/{gpu → faiss/gpu}/perf/IndexWrapper-inl.h +1 -1
  105. data/vendor/faiss/{gpu → faiss/gpu}/perf/IndexWrapper.h +1 -1
  106. data/vendor/faiss/{gpu → faiss/gpu}/perf/PerfClustering.cpp +1 -1
  107. data/vendor/faiss/{gpu → faiss/gpu}/perf/PerfIVFPQAdd.cpp +0 -0
  108. data/vendor/faiss/{gpu → faiss/gpu}/perf/WriteIndex.cpp +0 -0
  109. data/vendor/faiss/{gpu → faiss/gpu}/test/TestGpuIndexBinaryFlat.cpp +0 -0
  110. data/vendor/faiss/{gpu → faiss/gpu}/test/TestGpuIndexFlat.cpp +1 -1
  111. data/vendor/faiss/{gpu → faiss/gpu}/test/TestGpuIndexIVFFlat.cpp +0 -0
  112. data/vendor/faiss/{gpu → faiss/gpu}/test/TestGpuIndexIVFPQ.cpp +141 -52
  113. data/vendor/faiss/{gpu → faiss/gpu}/test/TestGpuMemoryException.cpp +0 -0
  114. data/vendor/faiss/{gpu → faiss/gpu}/test/TestUtils.cpp +4 -2
  115. data/vendor/faiss/{gpu → faiss/gpu}/test/TestUtils.h +0 -0
  116. data/vendor/faiss/{gpu → faiss/gpu}/test/demo_ivfpq_indexing_gpu.cpp +7 -5
  117. data/vendor/faiss/{gpu → faiss/gpu}/utils/DeviceUtils.h +1 -1
  118. data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +213 -0
  119. data/vendor/faiss/{gpu → faiss/gpu}/utils/StackDeviceMemory.h +25 -40
  120. data/vendor/faiss/{gpu → faiss/gpu}/utils/StaticUtils.h +0 -0
  121. data/vendor/faiss/{gpu → faiss/gpu}/utils/Timer.cpp +0 -0
  122. data/vendor/faiss/{gpu → faiss/gpu}/utils/Timer.h +0 -0
  123. data/vendor/faiss/{impl → faiss/impl}/AuxIndexStructures.cpp +1 -0
  124. data/vendor/faiss/{impl → faiss/impl}/AuxIndexStructures.h +3 -1
  125. data/vendor/faiss/{impl → faiss/impl}/FaissAssert.h +1 -0
  126. data/vendor/faiss/{impl → faiss/impl}/FaissException.cpp +26 -0
  127. data/vendor/faiss/{impl → faiss/impl}/FaissException.h +4 -0
  128. data/vendor/faiss/{impl → faiss/impl}/HNSW.cpp +26 -26
  129. data/vendor/faiss/{impl → faiss/impl}/HNSW.h +19 -11
  130. data/vendor/faiss/{impl → faiss/impl}/PolysemousTraining.cpp +1 -1
  131. data/vendor/faiss/{impl → faiss/impl}/PolysemousTraining.h +1 -1
  132. data/vendor/faiss/{impl → faiss/impl}/ProductQuantizer-inl.h +0 -1
  133. data/vendor/faiss/{impl → faiss/impl}/ProductQuantizer.cpp +9 -9
  134. data/vendor/faiss/{impl → faiss/impl}/ProductQuantizer.h +0 -0
  135. data/vendor/faiss/{impl → faiss/impl}/ScalarQuantizer.cpp +63 -39
  136. data/vendor/faiss/{impl → faiss/impl}/ScalarQuantizer.h +1 -1
  137. data/vendor/faiss/{impl → faiss/impl}/ThreadedIndex-inl.h +0 -0
  138. data/vendor/faiss/{impl → faiss/impl}/ThreadedIndex.h +0 -0
  139. data/vendor/faiss/{impl → faiss/impl}/index_read.cpp +99 -116
  140. data/vendor/faiss/{impl → faiss/impl}/index_write.cpp +15 -50
  141. data/vendor/faiss/{impl → faiss/impl}/io.cpp +15 -10
  142. data/vendor/faiss/{impl → faiss/impl}/io.h +22 -8
  143. data/vendor/faiss/faiss/impl/io_macros.h +57 -0
  144. data/vendor/faiss/{impl → faiss/impl}/lattice_Zn.cpp +52 -36
  145. data/vendor/faiss/{impl → faiss/impl}/lattice_Zn.h +3 -3
  146. data/vendor/faiss/faiss/impl/platform_macros.h +24 -0
  147. data/vendor/faiss/{index_factory.cpp → faiss/index_factory.cpp} +33 -12
  148. data/vendor/faiss/{index_factory.h → faiss/index_factory.h} +0 -0
  149. data/vendor/faiss/{index_io.h → faiss/index_io.h} +55 -1
  150. data/vendor/faiss/faiss/python/python_callbacks.cpp +112 -0
  151. data/vendor/faiss/faiss/python/python_callbacks.h +45 -0
  152. data/vendor/faiss/{utils → faiss/utils}/Heap.cpp +5 -5
  153. data/vendor/faiss/{utils → faiss/utils}/Heap.h +1 -3
  154. data/vendor/faiss/{utils → faiss/utils}/WorkerThread.cpp +0 -0
  155. data/vendor/faiss/{utils → faiss/utils}/WorkerThread.h +0 -0
  156. data/vendor/faiss/{utils → faiss/utils}/distances.cpp +28 -13
  157. data/vendor/faiss/{utils → faiss/utils}/distances.h +2 -1
  158. data/vendor/faiss/{utils → faiss/utils}/distances_simd.cpp +5 -5
  159. data/vendor/faiss/{utils → faiss/utils}/extra_distances.cpp +8 -7
  160. data/vendor/faiss/{utils → faiss/utils}/extra_distances.h +0 -0
  161. data/vendor/faiss/{utils → faiss/utils}/hamming-inl.h +1 -3
  162. data/vendor/faiss/{utils → faiss/utils}/hamming.cpp +8 -7
  163. data/vendor/faiss/{utils → faiss/utils}/hamming.h +7 -1
  164. data/vendor/faiss/{utils → faiss/utils}/random.cpp +5 -5
  165. data/vendor/faiss/{utils → faiss/utils}/random.h +0 -0
  166. data/vendor/faiss/{utils → faiss/utils}/utils.cpp +27 -28
  167. data/vendor/faiss/{utils → faiss/utils}/utils.h +4 -0
  168. data/vendor/faiss/misc/test_blas.cpp +4 -1
  169. data/vendor/faiss/tests/test_binary_flat.cpp +0 -2
  170. data/vendor/faiss/tests/test_dealloc_invlists.cpp +6 -1
  171. data/vendor/faiss/tests/test_ivfpq_codec.cpp +4 -1
  172. data/vendor/faiss/tests/test_ivfpq_indexing.cpp +6 -4
  173. data/vendor/faiss/tests/test_lowlevel_ivf.cpp +12 -5
  174. data/vendor/faiss/tests/test_merge.cpp +6 -3
  175. data/vendor/faiss/tests/test_ondisk_ivf.cpp +7 -2
  176. data/vendor/faiss/tests/test_pairs_decoding.cpp +5 -1
  177. data/vendor/faiss/tests/test_params_override.cpp +7 -2
  178. data/vendor/faiss/tests/test_sliding_ivf.cpp +10 -4
  179. data/vendor/faiss/tutorial/cpp/1-Flat.cpp +14 -8
  180. data/vendor/faiss/tutorial/cpp/2-IVFFlat.cpp +11 -7
  181. data/vendor/faiss/tutorial/cpp/3-IVFPQ.cpp +12 -7
  182. data/vendor/faiss/tutorial/cpp/4-GPU.cpp +6 -3
  183. data/vendor/faiss/tutorial/cpp/5-Multiple-GPUs.cpp +7 -3
  184. metadata +154 -153
  185. data/vendor/faiss/gpu/GpuResources.cpp +0 -52
  186. data/vendor/faiss/gpu/GpuResources.h +0 -73
  187. data/vendor/faiss/gpu/StandardGpuResources.cpp +0 -303
  188. data/vendor/faiss/gpu/utils/DeviceMemory.cpp +0 -77
  189. data/vendor/faiss/gpu/utils/DeviceMemory.h +0 -71
  190. data/vendor/faiss/gpu/utils/MemorySpace.cpp +0 -89
  191. data/vendor/faiss/gpu/utils/MemorySpace.h +0 -44
  192. data/vendor/faiss/gpu/utils/StackDeviceMemory.cpp +0 -239
@@ -5,11 +5,11 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- // Copyright 2004-present Facebook. All Rights Reserved
9
8
  // -*- c++ -*-
10
9
 
11
10
  #include <faiss/IndexBinaryIVF.h>
12
11
 
12
+ #include <cinttypes>
13
13
  #include <cstdio>
14
14
  #include <omp.h>
15
15
 
@@ -97,7 +97,7 @@ void IndexBinaryIVF::add_core(idx_t n, const uint8_t *x, const idx_t *xids,
97
97
  n_add++;
98
98
  }
99
99
  if (verbose) {
100
- printf("IndexBinaryIVF::add_with_ids: added %ld / %ld vectors\n",
100
+ printf("IndexBinaryIVF::add_with_ids: added %ld / %" PRId64 " vectors\n",
101
101
  n_add, n);
102
102
  }
103
103
  ntotal += n_add;
@@ -222,7 +222,7 @@ void IndexBinaryIVF::train(idx_t n, const uint8_t *x) {
222
222
  }
223
223
  } else {
224
224
  if (verbose) {
225
- printf("Training quantizer on %ld vectors in %dD\n", n, d);
225
+ printf("Training quantizer on %" PRId64 " vectors in %dD\n", n, d);
226
226
  }
227
227
 
228
228
  Clustering clus(d, nlist, cp);
@@ -333,7 +333,7 @@ struct IVFBinaryScannerL2: BinaryInvertedListScanner {
333
333
  const uint8_t *codes,
334
334
  const idx_t *ids,
335
335
  int radius,
336
- RangeQueryResult &result) const
336
+ RangeQueryResult &result) const override
337
337
  {
338
338
  size_t nup = 0;
339
339
  for (size_t j = 0; j < n; j++) {
@@ -351,12 +351,6 @@ struct IVFBinaryScannerL2: BinaryInvertedListScanner {
351
351
  };
352
352
 
353
353
 
354
- template <bool store_pairs>
355
- BinaryInvertedListScanner *select_IVFBinaryScannerL2 (size_t code_size) {
356
-
357
- }
358
-
359
-
360
354
  void search_knn_hamming_heap(const IndexBinaryIVF& ivf,
361
355
  size_t n,
362
356
  const uint8_t *x,
@@ -383,7 +377,7 @@ void search_knn_hamming_heap(const IndexBinaryIVF& ivf,
383
377
  (ivf.get_InvertedListScanner (store_pairs));
384
378
 
385
379
  #pragma omp for
386
- for (size_t i = 0; i < n; i++) {
380
+ for (idx_t i = 0; i < n; i++) {
387
381
  const uint8_t *xi = x + i * ivf.code_size;
388
382
  scanner->set_query(xi);
389
383
 
@@ -407,7 +401,7 @@ void search_knn_hamming_heap(const IndexBinaryIVF& ivf,
407
401
  }
408
402
  FAISS_THROW_IF_NOT_FMT
409
403
  (key < (idx_t) ivf.nlist,
410
- "Invalid key=%ld at ik=%ld nlist=%ld\n",
404
+ "Invalid key=%" PRId64 " at ik=%zd nlist=%zd\n",
411
405
  key, ik, ivf.nlist);
412
406
 
413
407
  scanner->set_list (key, coarse_dis[i * nprobe + ik]);
@@ -481,7 +475,7 @@ void search_knn_hamming_count(const IndexBinaryIVF& ivf,
481
475
  size_t nlistv = 0, ndis = 0;
482
476
 
483
477
  #pragma omp parallel for reduction(+: nlistv, ndis)
484
- for (size_t i = 0; i < nx; i++) {
478
+ for (int64_t i = 0; i < nx; i++) {
485
479
  const idx_t * keysi = keys + i * nprobe;
486
480
  HCounterState<HammingComputer>& csi = cs[i];
487
481
 
@@ -495,7 +489,7 @@ void search_knn_hamming_count(const IndexBinaryIVF& ivf,
495
489
  }
496
490
  FAISS_THROW_IF_NOT_FMT (
497
491
  key < (idx_t) ivf.nlist,
498
- "Invalid key=%ld at ik=%ld nlist=%ld\n",
492
+ "Invalid key=%" PRId64 " at ik=%zd nlist=%zd\n",
499
493
  key, ik, ivf.nlist);
500
494
 
501
495
  nlistv++;
@@ -669,7 +663,7 @@ void IndexBinaryIVF::range_search(
669
663
  if (key < 0) return;
670
664
  FAISS_THROW_IF_NOT_FMT (
671
665
  key < (idx_t) nlist,
672
- "Invalid key=%ld at ik=%ld nlist=%ld\n",
666
+ "Invalid key=%" PRId64 " at ik=%zd nlist=%zd\n",
673
667
  key, ik, nlist);
674
668
  const size_t list_size = invlists->list_size(key);
675
669
 
@@ -686,7 +680,7 @@ void IndexBinaryIVF::range_search(
686
680
  };
687
681
 
688
682
  #pragma omp for
689
- for (size_t i = 0; i < n; i++) {
683
+ for (idx_t i = 0; i < n; i++) {
690
684
  scanner->set_query (x + i * code_size);
691
685
 
692
686
  RangeQueryResult & qres = pres.new_result (i);
@@ -33,7 +33,7 @@ struct BinaryInvertedListScanner;
33
33
  * Otherwise the object is similar to the IndexIVF
34
34
  */
35
35
  struct IndexBinaryIVF : IndexBinary {
36
- /// Acess to the actual data
36
+ /// Access to the actual data
37
37
  InvertedLists *invlists;
38
38
  bool own_invlists;
39
39
 
@@ -14,6 +14,7 @@
14
14
  #include <cassert>
15
15
  #include <cstring>
16
16
  #include <cstdio>
17
+ #include <cinttypes>
17
18
  #include <cmath>
18
19
  #include <omp.h>
19
20
 
@@ -22,7 +23,6 @@
22
23
 
23
24
  #include <sys/types.h>
24
25
  #include <sys/stat.h>
25
- #include <unistd.h>
26
26
  #include <stdint.h>
27
27
 
28
28
  #ifdef __SSE__
@@ -119,7 +119,7 @@ void hnsw_add_vertices(IndexHNSW &index_hnsw,
119
119
  size_t ntotal = n0 + n;
120
120
  double t0 = getmillisecs();
121
121
  if (verbose) {
122
- printf("hnsw_add_vertices: adding %ld elements on top of %ld "
122
+ printf("hnsw_add_vertices: adding %zd elements on top of %zd "
123
123
  "(preset_levels=%d)\n",
124
124
  n, n0, int(preset_levels));
125
125
  }
@@ -289,7 +289,7 @@ void IndexHNSW::search (idx_t n, const float *x, idx_t k,
289
289
  {
290
290
  FAISS_THROW_IF_NOT_MSG(storage,
291
291
  "Please use IndexHSNWFlat (or variants) instead of IndexHNSW directly");
292
- size_t nreorder = 0;
292
+ size_t n1 = 0, n2 = 0, n3 = 0, ndis = 0, nreorder = 0;
293
293
 
294
294
  idx_t check_period = InterruptCallback::get_period_hint (
295
295
  hnsw.max_level * d * hnsw.efSearch);
@@ -297,22 +297,26 @@ void IndexHNSW::search (idx_t n, const float *x, idx_t k,
297
297
  for (idx_t i0 = 0; i0 < n; i0 += check_period) {
298
298
  idx_t i1 = std::min(i0 + check_period, n);
299
299
 
300
- #pragma omp parallel reduction(+ : nreorder)
300
+ #pragma omp parallel
301
301
  {
302
302
  VisitedTable vt (ntotal);
303
303
 
304
304
  DistanceComputer *dis = storage_distance_computer(storage);
305
305
  ScopeDeleter1<DistanceComputer> del(dis);
306
306
 
307
- #pragma omp for
307
+ #pragma omp for reduction (+ : n1, n2, n3, ndis, nreorder)
308
308
  for(idx_t i = i0; i < i1; i++) {
309
309
  idx_t * idxi = labels + i * k;
310
310
  float * simi = distances + i * k;
311
311
  dis->set_query(x + i * d);
312
312
 
313
313
  maxheap_heapify (k, simi, idxi);
314
- hnsw.search(*dis, k, idxi, simi, vt);
315
-
314
+ HNSWStats stats = hnsw.search(*dis, k, idxi, simi, vt);
315
+ n1 += stats.n1;
316
+ n2 += stats.n2;
317
+ n3 += stats.n3;
318
+ ndis += stats.ndis;
319
+ nreorder += stats.nreorder;
316
320
  maxheap_reorder (k, simi, idxi);
317
321
 
318
322
  if (reconstruct_from_neighbors &&
@@ -341,7 +345,7 @@ void IndexHNSW::search (idx_t n, const float *x, idx_t k,
341
345
  }
342
346
  }
343
347
 
344
- hnsw_stats.nreorder += nreorder;
348
+ hnsw_stats.combine({n1, n2, n3, ndis, nreorder});
345
349
  }
346
350
 
347
351
 
@@ -416,6 +420,8 @@ void IndexHNSW::search_level_0(
416
420
  {
417
421
 
418
422
  storage_idx_t ntotal = hnsw.levels.size();
423
+ size_t n1 = 0, n2 = 0, n3 = 0, ndis = 0, nreorder = 0;
424
+
419
425
  #pragma omp parallel
420
426
  {
421
427
  DistanceComputer *qdis = storage_distance_computer(storage);
@@ -423,7 +429,7 @@ void IndexHNSW::search_level_0(
423
429
 
424
430
  VisitedTable vt (ntotal);
425
431
 
426
- #pragma omp for
432
+ #pragma omp for reduction (+ : n1, n2, n3, ndis, nreorder)
427
433
  for(idx_t i = 0; i < n; i++) {
428
434
  idx_t * idxi = labels + i * k;
429
435
  float * simi = distances + i * k;
@@ -447,10 +453,17 @@ void IndexHNSW::search_level_0(
447
453
 
448
454
  candidates.push(cj, nearest_d[i * nprobe + j]);
449
455
 
456
+ HNSWStats search_stats;
450
457
  nres = hnsw.search_from_candidates(
451
458
  *qdis, k, idxi, simi,
452
- candidates, vt, 0, nres
459
+ candidates, vt, search_stats, 0, nres
453
460
  );
461
+ n1 += search_stats.n1;
462
+ n2 += search_stats.n2;
463
+ n3 += search_stats.n3;
464
+ ndis += search_stats.ndis;
465
+ nreorder += search_stats.nreorder;
466
+
454
467
  }
455
468
  } else if (search_type == 2) {
456
469
 
@@ -464,10 +477,17 @@ void IndexHNSW::search_level_0(
464
477
  if (cj < 0) break;
465
478
  candidates.push(cj, nearest_d[i * nprobe + j]);
466
479
  }
480
+
481
+ HNSWStats search_stats;
467
482
  hnsw.search_from_candidates(
468
483
  *qdis, k, idxi, simi,
469
- candidates, vt, 0
484
+ candidates, vt, search_stats, 0
470
485
  );
486
+ n1 += search_stats.n1;
487
+ n2 += search_stats.n2;
488
+ n3 += search_stats.n3;
489
+ ndis += search_stats.ndis;
490
+ nreorder += search_stats.nreorder;
471
491
 
472
492
  }
473
493
  vt.advance();
@@ -477,7 +497,7 @@ void IndexHNSW::search_level_0(
477
497
  }
478
498
  }
479
499
 
480
-
500
+ hnsw_stats.combine({n1, n2, n3, ndis, nreorder});
481
501
  }
482
502
 
483
503
  void IndexHNSW::init_level_0_from_knngraph(
@@ -488,9 +508,9 @@ void IndexHNSW::init_level_0_from_knngraph(
488
508
  #pragma omp parallel for
489
509
  for (idx_t i = 0; i < ntotal; i++) {
490
510
  DistanceComputer *qdis = storage_distance_computer(storage);
491
- float vec[d];
492
- storage->reconstruct(i, vec);
493
- qdis->set_query(vec);
511
+ std::vector<float> vec(d);
512
+ storage->reconstruct(i, vec.data());
513
+ qdis->set_query(vec.data());
494
514
 
495
515
  std::priority_queue<NodeDistFarther> initial_list;
496
516
 
@@ -533,14 +553,14 @@ void IndexHNSW::init_level_0_from_entry_points(
533
553
 
534
554
  DistanceComputer *dis = storage_distance_computer(storage);
535
555
  ScopeDeleter1<DistanceComputer> del(dis);
536
- float vec[storage->d];
556
+ std::vector<float> vec(storage->d);
537
557
 
538
558
  #pragma omp for schedule(dynamic)
539
559
  for (int i = 0; i < n; i++) {
540
560
  storage_idx_t pt_id = points[i];
541
561
  storage_idx_t nearest = nearests[i];
542
- storage->reconstruct (pt_id, vec);
543
- dis->set_query (vec);
562
+ storage->reconstruct (pt_id, vec.data());
563
+ dis->set_query (vec.data());
544
564
 
545
565
  hnsw.add_links_starting_from(*dis, pt_id,
546
566
  nearest, (*dis)(nearest),
@@ -624,7 +644,7 @@ void IndexHNSW::link_singletons()
624
644
  }
625
645
  }
626
646
 
627
- printf(" Found %d / %ld singletons (%d appear in a level above)\n",
647
+ printf(" Found %d / %" PRId64 " singletons (%d appear in a level above)\n",
628
648
  n_sing, ntotal, n_sing_l1);
629
649
 
630
650
  std::vector<float>recons(singletons.size() * d);
@@ -721,7 +741,7 @@ void ReconstructFromNeighbors::reconstruct(storage_idx_t i, float *x, float *tmp
721
741
  x[l] += w * tmp[l];
722
742
  }
723
743
  } else {
724
- const float *betas[nsq];
744
+ std::vector<const float *> betas(nsq);
725
745
  {
726
746
  const float *b = codebook.data();
727
747
  const uint8_t *c = &codes[i * code_size];
@@ -948,6 +968,7 @@ int search_from_candidates_2(const HNSW & hnsw,
948
968
  idx_t *I, float * D,
949
969
  MinimaxHeap &candidates,
950
970
  VisitedTable &vt,
971
+ HNSWStats &stats,
951
972
  int level, int nres_in = 0)
952
973
  {
953
974
  int nres = nres_in;
@@ -996,15 +1017,9 @@ int search_from_candidates_2(const HNSW & hnsw,
996
1017
  }
997
1018
  }
998
1019
 
999
- if (level == 0) {
1000
- #pragma omp critical
1001
- {
1002
- hnsw_stats.n1 ++;
1003
- if (candidates.size() == 0)
1004
- hnsw_stats.n2 ++;
1005
- }
1006
- }
1007
-
1020
+ stats.n1 ++;
1021
+ if (candidates.size() == 0)
1022
+ stats.n2 ++;
1008
1023
 
1009
1024
  return nres;
1010
1025
  }
@@ -1019,6 +1034,7 @@ void IndexHNSW2Level::search (idx_t n, const float *x, idx_t k,
1019
1034
  IndexHNSW::search (n, x, k, distances, labels);
1020
1035
 
1021
1036
  } else { // "mixed" search
1037
+ size_t n1 = 0, n2 = 0, n3 = 0, ndis = 0, nreorder = 0;
1022
1038
 
1023
1039
  const IndexIVFPQ *index_ivfpq =
1024
1040
  dynamic_cast<const IndexIVFPQ*>(storage);
@@ -1044,7 +1060,7 @@ void IndexHNSW2Level::search (idx_t n, const float *x, idx_t k,
1044
1060
  int candidates_size = hnsw.upper_beam;
1045
1061
  MinimaxHeap candidates(candidates_size);
1046
1062
 
1047
- #pragma omp for
1063
+ #pragma omp for reduction (+ : n1, n2, n3, ndis, nreorder)
1048
1064
  for(idx_t i = 0; i < n; i++) {
1049
1065
  idx_t * idxi = labels + i * k;
1050
1066
  float * simi = distances + i * k;
@@ -1081,10 +1097,16 @@ void IndexHNSW2Level::search (idx_t n, const float *x, idx_t k,
1081
1097
  // reorder from sorted to heap
1082
1098
  maxheap_heapify (k, simi, idxi, simi, idxi, k);
1083
1099
 
1100
+ HNSWStats search_stats;
1084
1101
  hnsw.search_from_candidates(
1085
1102
  *dis, k, idxi, simi,
1086
- candidates, vt, 0, k
1103
+ candidates, vt, search_stats, 0, k
1087
1104
  );
1105
+ n1 += search_stats.n1;
1106
+ n2 += search_stats.n2;
1107
+ n3 += search_stats.n3;
1108
+ ndis += search_stats.ndis;
1109
+ nreorder += search_stats.nreorder;
1088
1110
 
1089
1111
  vt.advance();
1090
1112
 
@@ -1098,9 +1120,16 @@ void IndexHNSW2Level::search (idx_t n, const float *x, idx_t k,
1098
1120
  // reorder from sorted to heap
1099
1121
  maxheap_heapify (k, simi, idxi, simi, idxi, k);
1100
1122
 
1123
+ HNSWStats search_stats;
1101
1124
  search_from_candidates_2 (
1102
1125
  hnsw, *dis, k, idxi, simi,
1103
- candidates, vt, 0, k);
1126
+ candidates, vt, search_stats, 0, k);
1127
+ n1 += search_stats.n1;
1128
+ n2 += search_stats.n2;
1129
+ n3 += search_stats.n3;
1130
+ ndis += search_stats.ndis;
1131
+ nreorder += search_stats.nreorder;
1132
+
1104
1133
  vt.advance ();
1105
1134
  vt.advance ();
1106
1135
 
@@ -1109,6 +1138,8 @@ void IndexHNSW2Level::search (idx_t n, const float *x, idx_t k,
1109
1138
  maxheap_reorder (k, simi, idxi);
1110
1139
  }
1111
1140
  }
1141
+
1142
+ hnsw_stats.combine({n1, n2, n3, ndis, nreorder});
1112
1143
  }
1113
1144
 
1114
1145
 
@@ -11,7 +11,10 @@
11
11
 
12
12
 
13
13
  #include <omp.h>
14
+ #include <mutex>
14
15
 
16
+ #include <algorithm>
17
+ #include <cinttypes>
15
18
  #include <cstdio>
16
19
  #include <memory>
17
20
 
@@ -72,7 +75,7 @@ void Level1Quantizer::train_q1 (size_t n, const float *x, bool verbose, MetricTy
72
75
  "nlist not consistent with quantizer size");
73
76
  } else if (quantizer_trains_alone == 0) {
74
77
  if (verbose)
75
- printf ("Training level-1 quantizer on %ld vectors in %ldD\n",
78
+ printf ("Training level-1 quantizer on %zd vectors in %zdD\n",
76
79
  n, d);
77
80
 
78
81
  Clustering clus (d, nlist, cp);
@@ -87,7 +90,7 @@ void Level1Quantizer::train_q1 (size_t n, const float *x, bool verbose, MetricTy
87
90
  } else if (quantizer_trains_alone == 2) {
88
91
  if (verbose)
89
92
  printf (
90
- "Training L2 quantizer on %ld vectors in %ldD%s\n",
93
+ "Training L2 quantizer on %zd vectors in %zdD%s\n",
91
94
  n, d,
92
95
  clustering_index ? "(user provided index)" : "");
93
96
  FAISS_THROW_IF_NOT (metric_type == METRIC_L2);
@@ -188,7 +191,7 @@ void IndexIVF::add_with_ids (idx_t n, const float * x, const idx_t *xids)
188
191
  for (idx_t i0 = 0; i0 < n; i0 += bs) {
189
192
  idx_t i1 = std::min (n, i0 + bs);
190
193
  if (verbose) {
191
- printf(" IndexIVF::add_with_ids %ld:%ld\n", i0, i1);
194
+ printf(" IndexIVF::add_with_ids %" PRId64 ":%" PRId64 "\n", i0, i1);
192
195
  }
193
196
  add_with_ids (i1 - i0, x + i0 * d,
194
197
  xids ? xids + i0 : nullptr);
@@ -238,7 +241,7 @@ void IndexIVF::add_with_ids (idx_t n, const float * x, const idx_t *xids)
238
241
 
239
242
 
240
243
  if (verbose) {
241
- printf(" added %ld / %ld vectors (%ld -1s)\n", nadd, n, nminus1);
244
+ printf(" added %zd / %" PRId64 " vectors (%zd -1s)\n", nadd, n, nminus1);
242
245
  }
243
246
 
244
247
  ntotal += n;
@@ -253,6 +256,8 @@ void IndexIVF::make_direct_map (bool b)
253
256
  }
254
257
  }
255
258
 
259
+
260
+
256
261
  void IndexIVF::set_direct_map_type (DirectMap::Type type)
257
262
  {
258
263
  direct_map.set_type (type, invlists, ntotal);
@@ -278,7 +283,6 @@ void IndexIVF::search (idx_t n, const float *x, idx_t k,
278
283
  }
279
284
 
280
285
 
281
-
282
286
  void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
283
287
  const idx_t *keys,
284
288
  const float *coarse_dis ,
@@ -295,15 +299,18 @@ void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
295
299
  using HeapForL2 = CMax<float, idx_t>;
296
300
 
297
301
  bool interrupt = false;
302
+ std::mutex exception_mutex;
303
+ std::string exception_string;
298
304
 
299
305
  int pmode = this->parallel_mode & ~PARALLEL_MODE_NO_HEAP_INIT;
300
306
  bool do_heap_init = !(this->parallel_mode & PARALLEL_MODE_NO_HEAP_INIT);
301
307
 
302
308
  // don't start parallel section if single query
303
- bool do_parallel =
304
- pmode == 0 ? n > 1 :
305
- pmode == 1 ? nprobe > 1 :
306
- nprobe * n > 1;
309
+ bool do_parallel = omp_get_max_threads() >= 2 && (
310
+ pmode == 0 ? n > 1 :
311
+ pmode == 1 ? nprobe > 1 :
312
+ nprobe * n > 1);
313
+
307
314
 
308
315
  #pragma omp parallel if(do_parallel) reduction(+: nlistv, ndis, nheap)
309
316
  {
@@ -327,6 +334,19 @@ void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
327
334
  }
328
335
  };
329
336
 
337
+ auto add_local_results = [&](
338
+ const float * local_dis, const idx_t * local_idx,
339
+ float *simi, idx_t *idxi)
340
+ {
341
+ if (metric_type == METRIC_INNER_PRODUCT) {
342
+ heap_addn<HeapForIP>
343
+ (k, simi, idxi, local_dis, local_idx, k);
344
+ } else {
345
+ heap_addn<HeapForL2>
346
+ (k, simi, idxi, local_dis, local_idx, k);
347
+ }
348
+ };
349
+
330
350
  auto reorder_result = [&] (float *simi, idx_t *idxi) {
331
351
  if (!do_heap_init) return;
332
352
  if (metric_type == METRIC_INNER_PRODUCT) {
@@ -346,7 +366,7 @@ void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
346
366
  return (size_t)0;
347
367
  }
348
368
  FAISS_THROW_IF_NOT_FMT (key < (idx_t) nlist,
349
- "Invalid key=%ld nlist=%ld\n",
369
+ "Invalid key=%" PRId64 " nlist=%zd\n",
350
370
  key, nlist);
351
371
 
352
372
  size_t list_size = invlists->list_size(key);
@@ -360,18 +380,27 @@ void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
360
380
 
361
381
  nlistv++;
362
382
 
363
- InvertedLists::ScopedCodes scodes (invlists, key);
383
+ try {
384
+ InvertedLists::ScopedCodes scodes (invlists, key);
364
385
 
365
- std::unique_ptr<InvertedLists::ScopedIds> sids;
366
- const Index::idx_t * ids = nullptr;
386
+ std::unique_ptr<InvertedLists::ScopedIds> sids;
387
+ const Index::idx_t * ids = nullptr;
367
388
 
368
- if (!store_pairs) {
369
- sids.reset (new InvertedLists::ScopedIds (invlists, key));
370
- ids = sids->get();
371
- }
389
+ if (!store_pairs) {
390
+ sids.reset (new InvertedLists::ScopedIds (invlists, key));
391
+ ids = sids->get();
392
+ }
393
+
394
+ nheap += scanner->scan_codes (list_size, scodes.get(),
395
+ ids, simi, idxi, k);
372
396
 
373
- nheap += scanner->scan_codes (list_size, scodes.get(),
374
- ids, simi, idxi, k);
397
+ } catch(const std::exception & e) {
398
+ std::lock_guard<std::mutex> lock(exception_mutex);
399
+ exception_string =
400
+ demangle_cpp_symbol(typeid(e).name()) + " " + e.what();
401
+ interrupt = true;
402
+ return size_t(0);
403
+ }
375
404
 
376
405
  return list_size;
377
406
  };
@@ -383,7 +412,7 @@ void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
383
412
  if (pmode == 0) {
384
413
 
385
414
  #pragma omp for
386
- for (size_t i = 0; i < n; i++) {
415
+ for (idx_t i = 0; i < n; i++) {
387
416
 
388
417
  if (interrupt) {
389
418
  continue;
@@ -429,7 +458,7 @@ void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
429
458
  init_result (local_dis.data(), local_idx.data());
430
459
 
431
460
  #pragma omp for schedule(dynamic)
432
- for (size_t ik = 0; ik < nprobe; ik++) {
461
+ for (long ik = 0; ik < nprobe; ik++) {
433
462
  ndis += scan_one_list
434
463
  (keys [i * nprobe + ik],
435
464
  coarse_dis[i * nprobe + ik],
@@ -447,20 +476,42 @@ void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
447
476
  #pragma omp barrier
448
477
  #pragma omp critical
449
478
  {
450
- if (metric_type == METRIC_INNER_PRODUCT) {
451
- heap_addn<HeapForIP>
452
- (k, simi, idxi,
453
- local_dis.data(), local_idx.data(), k);
454
- } else {
455
- heap_addn<HeapForL2>
456
- (k, simi, idxi,
457
- local_dis.data(), local_idx.data(), k);
458
- }
479
+ add_local_results (local_dis.data(), local_idx.data(),
480
+ simi, idxi);
459
481
  }
460
482
  #pragma omp barrier
461
483
  #pragma omp single
462
484
  reorder_result (simi, idxi);
463
485
  }
486
+ } else if (pmode == 2) {
487
+ std::vector <idx_t> local_idx (k);
488
+ std::vector <float> local_dis (k);
489
+
490
+ #pragma omp single
491
+ for (int64_t i = 0; i < n; i++) {
492
+ init_result (distances + i * k, labels + i * k);
493
+ }
494
+
495
+ #pragma omp for schedule(dynamic)
496
+ for (int64_t ij = 0; ij < n * nprobe; ij++) {
497
+ size_t i = ij / nprobe;
498
+ size_t j = ij % nprobe;
499
+
500
+ scanner->set_query (x + i * d);
501
+ init_result (local_dis.data(), local_idx.data());
502
+ ndis += scan_one_list (
503
+ keys [ij], coarse_dis[ij],
504
+ local_dis.data(), local_idx.data());
505
+ #pragma omp critical
506
+ {
507
+ add_local_results (local_dis.data(), local_idx.data(),
508
+ distances + i * k, labels + i * k);
509
+ }
510
+ }
511
+ #pragma omp single
512
+ for (int64_t i = 0; i < n; i++) {
513
+ reorder_result (distances + i * k, labels + i * k);
514
+ }
464
515
  } else {
465
516
  FAISS_THROW_FMT ("parallel_mode %d not supported\n",
466
517
  pmode);
@@ -468,7 +519,12 @@ void IndexIVF::search_preassigned (idx_t n, const float *x, idx_t k,
468
519
  } // parallel section
469
520
 
470
521
  if (interrupt) {
471
- FAISS_THROW_MSG ("computation interrupted");
522
+ if (!exception_string.empty()) {
523
+ FAISS_THROW_FMT ("search interrupted with: %s",
524
+ exception_string.c_str());
525
+ } else {
526
+ FAISS_THROW_MSG ("computation interrupted");
527
+ }
472
528
  }
473
529
 
474
530
  indexIVF_stats.nq += n;
@@ -503,11 +559,18 @@ void IndexIVF::range_search (idx_t nx, const float *x, float radius,
503
559
  void IndexIVF::range_search_preassigned (
504
560
  idx_t nx, const float *x, float radius,
505
561
  const idx_t *keys, const float *coarse_dis,
506
- RangeSearchResult *result) const
562
+ RangeSearchResult *result,
563
+ bool store_pairs,
564
+ const IVFSearchParameters *params) const
507
565
  {
566
+ long nprobe = params ? params->nprobe : this->nprobe;
567
+ long max_codes = params ? params->max_codes : this->max_codes;
508
568
 
509
569
  size_t nlistv = 0, ndis = 0;
510
- bool store_pairs = false;
570
+
571
+ bool interrupt = false;
572
+ std::mutex exception_mutex;
573
+ std::string exception_string;
511
574
 
512
575
  std::vector<RangeSearchPartialResult *> all_pres (omp_get_max_threads());
513
576
 
@@ -527,26 +590,36 @@ void IndexIVF::range_search_preassigned (
527
590
  if (key < 0) return;
528
591
  FAISS_THROW_IF_NOT_FMT (
529
592
  key < (idx_t) nlist,
530
- "Invalid key=%ld at ik=%ld nlist=%ld\n",
593
+ "Invalid key=%" PRId64 " at ik=%zd nlist=%zd\n",
531
594
  key, ik, nlist);
532
595
  const size_t list_size = invlists->list_size(key);
533
596
 
534
597
  if (list_size == 0) return;
535
598
 
536
- InvertedLists::ScopedCodes scodes (invlists, key);
537
- InvertedLists::ScopedIds ids (invlists, key);
599
+ try {
600
+
601
+ InvertedLists::ScopedCodes scodes (invlists, key);
602
+ InvertedLists::ScopedIds ids (invlists, key);
603
+
604
+ scanner->set_list (key, coarse_dis[i * nprobe + ik]);
605
+ nlistv++;
606
+ ndis += list_size;
607
+ scanner->scan_codes_range (list_size, scodes.get(),
608
+ ids.get(), radius, qres);
609
+
610
+ } catch(const std::exception & e) {
611
+ std::lock_guard<std::mutex> lock(exception_mutex);
612
+ exception_string =
613
+ demangle_cpp_symbol(typeid(e).name()) + " " + e.what();
614
+ interrupt = true;
615
+ }
538
616
 
539
- scanner->set_list (key, coarse_dis[i * nprobe + ik]);
540
- nlistv++;
541
- ndis += list_size;
542
- scanner->scan_codes_range (list_size, scodes.get(),
543
- ids.get(), radius, qres);
544
617
  };
545
618
 
546
619
  if (parallel_mode == 0) {
547
620
 
548
621
  #pragma omp for
549
- for (size_t i = 0; i < nx; i++) {
622
+ for (idx_t i = 0; i < nx; i++) {
550
623
  scanner->set_query (x + i * d);
551
624
 
552
625
  RangeQueryResult & qres = pres.new_result (i);
@@ -565,7 +638,7 @@ void IndexIVF::range_search_preassigned (
565
638
  RangeQueryResult & qres = pres.new_result (i);
566
639
 
567
640
  #pragma omp for schedule(dynamic)
568
- for (size_t ik = 0; ik < nprobe; ik++) {
641
+ for (int64_t ik = 0; ik < nprobe; ik++) {
569
642
  scan_list_func (i, ik, qres);
570
643
  }
571
644
  }
@@ -574,9 +647,9 @@ void IndexIVF::range_search_preassigned (
574
647
  RangeQueryResult *qres = nullptr;
575
648
 
576
649
  #pragma omp for schedule(dynamic)
577
- for (size_t iik = 0; iik < nx * nprobe; iik++) {
578
- size_t i = iik / nprobe;
579
- size_t ik = iik % nprobe;
650
+ for (idx_t iik = 0; iik < nx * (idx_t)nprobe; iik++) {
651
+ idx_t i = iik / (idx_t)nprobe;
652
+ idx_t ik = iik % (idx_t)nprobe;
580
653
  if (qres == nullptr || qres->qno != i) {
581
654
  FAISS_ASSERT (!qres || i > qres->qno);
582
655
  qres = &pres.new_result (i);
@@ -597,6 +670,16 @@ void IndexIVF::range_search_preassigned (
597
670
 
598
671
  }
599
672
  }
673
+
674
+ if (interrupt) {
675
+ if (!exception_string.empty()) {
676
+ FAISS_THROW_FMT ("search interrupted with: %s",
677
+ exception_string.c_str());
678
+ } else {
679
+ FAISS_THROW_MSG ("computation interrupted");
680
+ }
681
+ }
682
+
600
683
  indexIVF_stats.nq += nx;
601
684
  indexIVF_stats.nlist += nlistv;
602
685
  indexIVF_stats.ndis += ndis;