faiss 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +23 -21
  4. data/ext/faiss/extconf.rb +11 -0
  5. data/ext/faiss/index.cpp +4 -4
  6. data/ext/faiss/index_binary.cpp +6 -6
  7. data/ext/faiss/product_quantizer.cpp +4 -4
  8. data/lib/faiss/version.rb +1 -1
  9. data/vendor/faiss/faiss/AutoTune.cpp +13 -0
  10. data/vendor/faiss/faiss/IVFlib.cpp +101 -2
  11. data/vendor/faiss/faiss/IVFlib.h +26 -2
  12. data/vendor/faiss/faiss/Index.cpp +36 -3
  13. data/vendor/faiss/faiss/Index.h +43 -6
  14. data/vendor/faiss/faiss/Index2Layer.cpp +6 -2
  15. data/vendor/faiss/faiss/Index2Layer.h +6 -1
  16. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +219 -16
  17. data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +63 -5
  18. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +299 -0
  19. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +199 -0
  20. data/vendor/faiss/faiss/IndexBinary.cpp +20 -4
  21. data/vendor/faiss/faiss/IndexBinary.h +18 -3
  22. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +9 -2
  23. data/vendor/faiss/faiss/IndexBinaryFlat.h +4 -2
  24. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +4 -1
  25. data/vendor/faiss/faiss/IndexBinaryFromFloat.h +2 -1
  26. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +5 -1
  27. data/vendor/faiss/faiss/IndexBinaryHNSW.h +2 -1
  28. data/vendor/faiss/faiss/IndexBinaryHash.cpp +17 -4
  29. data/vendor/faiss/faiss/IndexBinaryHash.h +8 -4
  30. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +28 -13
  31. data/vendor/faiss/faiss/IndexBinaryIVF.h +10 -7
  32. data/vendor/faiss/faiss/IndexFastScan.cpp +626 -0
  33. data/vendor/faiss/faiss/IndexFastScan.h +145 -0
  34. data/vendor/faiss/faiss/IndexFlat.cpp +34 -21
  35. data/vendor/faiss/faiss/IndexFlat.h +7 -4
  36. data/vendor/faiss/faiss/IndexFlatCodes.cpp +35 -1
  37. data/vendor/faiss/faiss/IndexFlatCodes.h +12 -0
  38. data/vendor/faiss/faiss/IndexHNSW.cpp +66 -138
  39. data/vendor/faiss/faiss/IndexHNSW.h +4 -2
  40. data/vendor/faiss/faiss/IndexIDMap.cpp +247 -0
  41. data/vendor/faiss/faiss/IndexIDMap.h +107 -0
  42. data/vendor/faiss/faiss/IndexIVF.cpp +121 -33
  43. data/vendor/faiss/faiss/IndexIVF.h +35 -16
  44. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +84 -7
  45. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +63 -1
  46. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +590 -0
  47. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +171 -0
  48. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +1290 -0
  49. data/vendor/faiss/faiss/IndexIVFFastScan.h +213 -0
  50. data/vendor/faiss/faiss/IndexIVFFlat.cpp +37 -17
  51. data/vendor/faiss/faiss/IndexIVFFlat.h +4 -2
  52. data/vendor/faiss/faiss/IndexIVFPQ.cpp +234 -50
  53. data/vendor/faiss/faiss/IndexIVFPQ.h +5 -1
  54. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +23 -852
  55. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +7 -112
  56. data/vendor/faiss/faiss/IndexIVFPQR.cpp +3 -3
  57. data/vendor/faiss/faiss/IndexIVFPQR.h +1 -1
  58. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +3 -1
  59. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +2 -1
  60. data/vendor/faiss/faiss/IndexLSH.cpp +4 -2
  61. data/vendor/faiss/faiss/IndexLSH.h +2 -1
  62. data/vendor/faiss/faiss/IndexLattice.cpp +7 -1
  63. data/vendor/faiss/faiss/IndexLattice.h +3 -1
  64. data/vendor/faiss/faiss/IndexNNDescent.cpp +4 -3
  65. data/vendor/faiss/faiss/IndexNNDescent.h +2 -1
  66. data/vendor/faiss/faiss/IndexNSG.cpp +37 -3
  67. data/vendor/faiss/faiss/IndexNSG.h +25 -1
  68. data/vendor/faiss/faiss/IndexPQ.cpp +106 -69
  69. data/vendor/faiss/faiss/IndexPQ.h +19 -5
  70. data/vendor/faiss/faiss/IndexPQFastScan.cpp +15 -450
  71. data/vendor/faiss/faiss/IndexPQFastScan.h +15 -78
  72. data/vendor/faiss/faiss/IndexPreTransform.cpp +47 -8
  73. data/vendor/faiss/faiss/IndexPreTransform.h +15 -3
  74. data/vendor/faiss/faiss/IndexRefine.cpp +8 -4
  75. data/vendor/faiss/faiss/IndexRefine.h +4 -2
  76. data/vendor/faiss/faiss/IndexReplicas.cpp +4 -2
  77. data/vendor/faiss/faiss/IndexReplicas.h +2 -1
  78. data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +438 -0
  79. data/vendor/faiss/faiss/IndexRowwiseMinMax.h +92 -0
  80. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +26 -15
  81. data/vendor/faiss/faiss/IndexScalarQuantizer.h +6 -7
  82. data/vendor/faiss/faiss/IndexShards.cpp +4 -1
  83. data/vendor/faiss/faiss/IndexShards.h +2 -1
  84. data/vendor/faiss/faiss/MetaIndexes.cpp +5 -178
  85. data/vendor/faiss/faiss/MetaIndexes.h +3 -81
  86. data/vendor/faiss/faiss/VectorTransform.cpp +43 -0
  87. data/vendor/faiss/faiss/VectorTransform.h +22 -4
  88. data/vendor/faiss/faiss/clone_index.cpp +23 -1
  89. data/vendor/faiss/faiss/clone_index.h +3 -0
  90. data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +300 -0
  91. data/vendor/faiss/faiss/cppcontrib/detail/CoarseBitType.h +24 -0
  92. data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +195 -0
  93. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +2058 -0
  94. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +408 -0
  95. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +2147 -0
  96. data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMax-inl.h +460 -0
  97. data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMaxFP16-inl.h +465 -0
  98. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +1618 -0
  99. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +251 -0
  100. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +1452 -0
  101. data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +1 -0
  102. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +0 -4
  103. data/vendor/faiss/faiss/gpu/GpuIndex.h +28 -4
  104. data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +2 -1
  105. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +10 -8
  106. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +75 -14
  107. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +19 -32
  108. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +22 -31
  109. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +22 -28
  110. data/vendor/faiss/faiss/gpu/GpuResources.cpp +14 -0
  111. data/vendor/faiss/faiss/gpu/GpuResources.h +16 -3
  112. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +3 -3
  113. data/vendor/faiss/faiss/gpu/impl/IndexUtils.h +32 -0
  114. data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +1 -0
  115. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +311 -75
  116. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +10 -0
  117. data/vendor/faiss/faiss/gpu/test/TestUtils.h +3 -0
  118. data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +2 -2
  119. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +5 -4
  120. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +116 -47
  121. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +44 -13
  122. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +0 -54
  123. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +0 -76
  124. data/vendor/faiss/faiss/impl/DistanceComputer.h +64 -0
  125. data/vendor/faiss/faiss/impl/HNSW.cpp +123 -27
  126. data/vendor/faiss/faiss/impl/HNSW.h +19 -16
  127. data/vendor/faiss/faiss/impl/IDSelector.cpp +125 -0
  128. data/vendor/faiss/faiss/impl/IDSelector.h +135 -0
  129. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +6 -28
  130. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +6 -1
  131. data/vendor/faiss/faiss/impl/LookupTableScaler.h +77 -0
  132. data/vendor/faiss/faiss/impl/NNDescent.cpp +1 -0
  133. data/vendor/faiss/faiss/impl/NSG.cpp +1 -1
  134. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +383 -0
  135. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.h +154 -0
  136. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +225 -145
  137. data/vendor/faiss/faiss/impl/ProductQuantizer.h +29 -10
  138. data/vendor/faiss/faiss/impl/Quantizer.h +43 -0
  139. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +192 -36
  140. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +40 -20
  141. data/vendor/faiss/faiss/impl/ResultHandler.h +96 -0
  142. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +97 -173
  143. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +18 -18
  144. data/vendor/faiss/faiss/impl/index_read.cpp +240 -9
  145. data/vendor/faiss/faiss/impl/index_write.cpp +237 -5
  146. data/vendor/faiss/faiss/impl/kmeans1d.cpp +6 -4
  147. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +56 -16
  148. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +25 -8
  149. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +66 -25
  150. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +75 -27
  151. data/vendor/faiss/faiss/index_factory.cpp +196 -7
  152. data/vendor/faiss/faiss/index_io.h +5 -0
  153. data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -0
  154. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +4 -1
  155. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +2 -1
  156. data/vendor/faiss/faiss/python/python_callbacks.cpp +27 -0
  157. data/vendor/faiss/faiss/python/python_callbacks.h +15 -0
  158. data/vendor/faiss/faiss/utils/Heap.h +31 -15
  159. data/vendor/faiss/faiss/utils/distances.cpp +380 -56
  160. data/vendor/faiss/faiss/utils/distances.h +113 -15
  161. data/vendor/faiss/faiss/utils/distances_simd.cpp +726 -6
  162. data/vendor/faiss/faiss/utils/extra_distances.cpp +12 -7
  163. data/vendor/faiss/faiss/utils/extra_distances.h +3 -1
  164. data/vendor/faiss/faiss/utils/fp16-fp16c.h +21 -0
  165. data/vendor/faiss/faiss/utils/fp16-inl.h +101 -0
  166. data/vendor/faiss/faiss/utils/fp16.h +11 -0
  167. data/vendor/faiss/faiss/utils/hamming-inl.h +54 -0
  168. data/vendor/faiss/faiss/utils/hamming.cpp +0 -48
  169. data/vendor/faiss/faiss/utils/ordered_key_value.h +10 -0
  170. data/vendor/faiss/faiss/utils/quantize_lut.cpp +62 -0
  171. data/vendor/faiss/faiss/utils/quantize_lut.h +20 -0
  172. data/vendor/faiss/faiss/utils/random.cpp +53 -0
  173. data/vendor/faiss/faiss/utils/random.h +5 -0
  174. data/vendor/faiss/faiss/utils/simdlib_avx2.h +4 -0
  175. data/vendor/faiss/faiss/utils/simdlib_emulated.h +6 -1
  176. data/vendor/faiss/faiss/utils/simdlib_neon.h +7 -2
  177. metadata +37 -3
@@ -29,6 +29,13 @@
29
29
  #include <faiss/impl/FaissAssert.h>
30
30
 
31
31
  #include <faiss/impl/AuxIndexStructures.h>
32
+ #include <faiss/impl/IDSelector.h>
33
+
34
+ #include <faiss/impl/ProductQuantizer.h>
35
+
36
+ #ifdef __AVX2__
37
+ #include <immintrin.h>
38
+ #endif
32
39
 
33
40
  namespace faiss {
34
41
 
@@ -254,13 +261,16 @@ void IndexIVFPQ::sa_decode(idx_t n, const uint8_t* codes, float* x) const {
254
261
  }
255
262
  }
256
263
 
264
+ // block size used in IndexIVFPQ::add_core_o
265
+ int index_ivfpq_add_core_o_bs = 32768;
266
+
257
267
  void IndexIVFPQ::add_core_o(
258
268
  idx_t n,
259
269
  const float* x,
260
270
  const idx_t* xids,
261
271
  float* residuals_2,
262
272
  const idx_t* precomputed_idx) {
263
- idx_t bs = 32768;
273
+ idx_t bs = index_ivfpq_add_core_o_bs;
264
274
  if (n > bs) {
265
275
  for (idx_t i0 = 0; i0 < n; i0 += bs) {
266
276
  idx_t i1 = std::min(i0 + bs, n);
@@ -793,10 +803,13 @@ struct QueryTables {
793
803
  }
794
804
  };
795
805
 
796
- template <class C>
806
+ // This way of handling the sleector is not optimal since all distances
807
+ // are computed even if the id would filter it out.
808
+ template <class C, bool use_sel>
797
809
  struct KnnSearchResults {
798
810
  idx_t key;
799
811
  const idx_t* ids;
812
+ const IDSelector* sel;
800
813
 
801
814
  // heap params
802
815
  size_t k;
@@ -805,6 +818,10 @@ struct KnnSearchResults {
805
818
 
806
819
  size_t nup;
807
820
 
821
+ inline bool skip_entry(idx_t j) {
822
+ return use_sel && !sel->is_member(ids[j]);
823
+ }
824
+
808
825
  inline void add(idx_t j, float dis) {
809
826
  if (C::cmp(heap_sim[0], dis)) {
810
827
  idx_t id = ids ? ids[j] : lo_build(key, j);
@@ -814,15 +831,20 @@ struct KnnSearchResults {
814
831
  }
815
832
  };
816
833
 
817
- template <class C>
834
+ template <class C, bool use_sel>
818
835
  struct RangeSearchResults {
819
836
  idx_t key;
820
837
  const idx_t* ids;
838
+ const IDSelector* sel;
821
839
 
822
840
  // wrapped result structure
823
841
  float radius;
824
842
  RangeQueryResult& rres;
825
843
 
844
+ inline bool skip_entry(idx_t j) {
845
+ return use_sel && !sel->is_member(ids[j]);
846
+ }
847
+
826
848
  inline void add(idx_t j, float dis) {
827
849
  if (C::cmp(radius, dis)) {
828
850
  idx_t id = ids ? ids[j] : lo_build(key, j);
@@ -864,23 +886,152 @@ struct IVFPQScannerT : QueryTables {
864
886
  * Scaning the codes: simple PQ scan.
865
887
  *****************************************************/
866
888
 
867
- /// version of the scan where we use precomputed tables
889
+ #ifdef __AVX2__
890
+ /// Returns the distance to a single code.
891
+ /// General-purpose version.
892
+ template <class SearchResultType, typename T = PQDecoder>
893
+ typename std::enable_if<!(std::is_same<T, PQDecoder8>::value), float>::
894
+ type inline distance_single_code(const uint8_t* code) const {
895
+ PQDecoder decoder(code, pq.nbits);
896
+
897
+ const float* tab = sim_table;
898
+ float result = 0;
899
+
900
+ for (size_t m = 0; m < pq.M; m++) {
901
+ result += tab[decoder.decode()];
902
+ tab += pq.ksub;
903
+ }
904
+
905
+ return result;
906
+ }
907
+
908
+ /// Returns the distance to a single code.
909
+ /// Specialized AVX2 PQDecoder8 version.
910
+ template <class SearchResultType, typename T = PQDecoder>
911
+ typename std::enable_if<(std::is_same<T, PQDecoder8>::value), float>::
912
+ type inline distance_single_code(const uint8_t* code) const {
913
+ float result = 0;
914
+
915
+ size_t m = 0;
916
+ const size_t pqM16 = pq.M / 16;
917
+
918
+ const float* tab = sim_table;
919
+
920
+ if (pqM16 > 0) {
921
+ // process 16 values per loop
922
+
923
+ const __m256i ksub = _mm256_set1_epi32(pq.ksub);
924
+ __m256i offsets_0 = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7);
925
+ offsets_0 = _mm256_mullo_epi32(offsets_0, ksub);
926
+
927
+ // accumulators of partial sums
928
+ __m256 partialSum = _mm256_setzero_ps();
929
+
930
+ // loop
931
+ for (m = 0; m < pqM16 * 16; m += 16) {
932
+ // load 16 uint8 values
933
+ const __m128i mm1 =
934
+ _mm_loadu_si128((const __m128i_u*)(code + m));
935
+ {
936
+ // convert uint8 values (low part of __m128i) to int32
937
+ // values
938
+ const __m256i idx1 = _mm256_cvtepu8_epi32(mm1);
939
+
940
+ // add offsets
941
+ const __m256i indices_to_read_from =
942
+ _mm256_add_epi32(idx1, offsets_0);
943
+
944
+ // gather 8 values, similar to 8 operations of tab[idx]
945
+ __m256 collected = _mm256_i32gather_ps(
946
+ tab, indices_to_read_from, sizeof(float));
947
+ tab += pq.ksub * 8;
948
+
949
+ // collect partial sums
950
+ partialSum = _mm256_add_ps(partialSum, collected);
951
+ }
952
+
953
+ // move high 8 uint8 to low ones
954
+ const __m128i mm2 =
955
+ _mm_unpackhi_epi64(mm1, _mm_setzero_si128());
956
+ {
957
+ // convert uint8 values (low part of __m128i) to int32
958
+ // values
959
+ const __m256i idx1 = _mm256_cvtepu8_epi32(mm2);
960
+
961
+ // add offsets
962
+ const __m256i indices_to_read_from =
963
+ _mm256_add_epi32(idx1, offsets_0);
964
+
965
+ // gather 8 values, similar to 8 operations of tab[idx]
966
+ __m256 collected = _mm256_i32gather_ps(
967
+ tab, indices_to_read_from, sizeof(float));
968
+ tab += pq.ksub * 8;
969
+
970
+ // collect partial sums
971
+ partialSum = _mm256_add_ps(partialSum, collected);
972
+ }
973
+ }
974
+
975
+ // horizontal sum for partialSum
976
+ const __m256 h0 = _mm256_hadd_ps(partialSum, partialSum);
977
+ const __m256 h1 = _mm256_hadd_ps(h0, h0);
978
+
979
+ // extract high and low __m128 regs from __m256
980
+ const __m128 h2 = _mm256_extractf128_ps(h1, 1);
981
+ const __m128 h3 = _mm256_castps256_ps128(h1);
982
+
983
+ // get a final hsum into all 4 regs
984
+ const __m128 h4 = _mm_add_ss(h2, h3);
985
+
986
+ // extract f[0] from __m128
987
+ const float hsum = _mm_cvtss_f32(h4);
988
+ result += hsum;
989
+ }
990
+
991
+ //
992
+ if (m < pq.M) {
993
+ // process leftovers
994
+ PQDecoder decoder(code + m, pq.nbits);
995
+
996
+ for (; m < pq.M; m++) {
997
+ result += tab[decoder.decode()];
998
+ tab += pq.ksub;
999
+ }
1000
+ }
1001
+
1002
+ return result;
1003
+ }
1004
+
1005
+ #else
1006
+ /// Returns the distance to a single code.
1007
+ /// General-purpose version.
1008
+ template <class SearchResultType>
1009
+ inline float distance_single_code(const uint8_t* code) const {
1010
+ PQDecoder decoder(code, pq.nbits);
1011
+
1012
+ const float* tab = sim_table;
1013
+ float result = 0;
1014
+
1015
+ for (size_t m = 0; m < pq.M; m++) {
1016
+ result += tab[decoder.decode()];
1017
+ tab += pq.ksub;
1018
+ }
1019
+
1020
+ return result;
1021
+ }
1022
+ #endif
1023
+
1024
+ /// version of the scan where we use precomputed tables.
868
1025
  template <class SearchResultType>
869
1026
  void scan_list_with_table(
870
1027
  size_t ncode,
871
1028
  const uint8_t* codes,
872
1029
  SearchResultType& res) const {
873
- for (size_t j = 0; j < ncode; j++) {
874
- PQDecoder decoder(codes, pq.nbits);
875
- codes += pq.code_size;
876
- float dis = dis0;
877
- const float* tab = sim_table;
878
-
879
- for (size_t m = 0; m < pq.M; m++) {
880
- dis += tab[decoder.decode()];
881
- tab += pq.ksub;
1030
+ for (size_t j = 0; j < ncode; j++, codes += pq.code_size) {
1031
+ if (res.skip_entry(j)) {
1032
+ continue;
882
1033
  }
883
-
1034
+ float dis = dis0 + distance_single_code<SearchResultType>(codes);
884
1035
  res.add(j, dis);
885
1036
  }
886
1037
  }
@@ -892,10 +1043,11 @@ struct IVFPQScannerT : QueryTables {
892
1043
  size_t ncode,
893
1044
  const uint8_t* codes,
894
1045
  SearchResultType& res) const {
895
- for (size_t j = 0; j < ncode; j++) {
1046
+ for (size_t j = 0; j < ncode; j++, codes += pq.code_size) {
1047
+ if (res.skip_entry(j)) {
1048
+ continue;
1049
+ }
896
1050
  PQDecoder decoder(codes, pq.nbits);
897
- codes += pq.code_size;
898
-
899
1051
  float dis = dis0;
900
1052
  const float* tab = sim_table_2;
901
1053
 
@@ -929,9 +1081,11 @@ struct IVFPQScannerT : QueryTables {
929
1081
  dis0 = 0;
930
1082
  }
931
1083
 
932
- for (size_t j = 0; j < ncode; j++) {
1084
+ for (size_t j = 0; j < ncode; j++, codes += pq.code_size) {
1085
+ if (res.skip_entry(j)) {
1086
+ continue;
1087
+ }
933
1088
  pq.decode(codes, decoded_vec);
934
- codes += pq.code_size;
935
1089
 
936
1090
  float dis;
937
1091
  if (METRIC_TYPE == METRIC_INNER_PRODUCT) {
@@ -959,24 +1113,20 @@ struct IVFPQScannerT : QueryTables {
959
1113
 
960
1114
  HammingComputer hc(q_code.data(), code_size);
961
1115
 
962
- for (size_t j = 0; j < ncode; j++) {
1116
+ for (size_t j = 0; j < ncode; j++, codes += code_size) {
1117
+ if (res.skip_entry(j)) {
1118
+ continue;
1119
+ }
963
1120
  const uint8_t* b_code = codes;
964
1121
  int hd = hc.hamming(b_code);
965
1122
  if (hd < ht) {
966
1123
  n_hamming_pass++;
967
- PQDecoder decoder(codes, pq.nbits);
968
1124
 
969
- float dis = dis0;
970
- const float* tab = sim_table;
971
-
972
- for (size_t m = 0; m < pq.M; m++) {
973
- dis += tab[decoder.decode()];
974
- tab += pq.ksub;
975
- }
1125
+ float dis =
1126
+ dis0 + distance_single_code<SearchResultType>(codes);
976
1127
 
977
1128
  res.add(j, dis);
978
1129
  }
979
- codes += code_size;
980
1130
  }
981
1131
  #pragma omp critical
982
1132
  { indexIVFPQ_stats.n_hamming_pass += n_hamming_pass; }
@@ -1010,21 +1160,32 @@ struct IVFPQScannerT : QueryTables {
1010
1160
  };
1011
1161
 
1012
1162
  /* We put as many parameters as possible in template. Hopefully the
1013
- * gain in runtime is worth the code bloat. C is the comparator < or
1014
- * >, it is directly related to METRIC_TYPE. precompute_mode is how
1015
- * much we precompute (2 = precompute distance tables, 1 = precompute
1016
- * pointers to distances, 0 = compute distances one by one).
1017
- * Currently only 2 is supported */
1018
- template <MetricType METRIC_TYPE, class C, class PQDecoder>
1163
+ * gain in runtime is worth the code bloat.
1164
+ *
1165
+ * C is the comparator < or >, it is directly related to METRIC_TYPE.
1166
+ *
1167
+ * precompute_mode is how much we precompute (2 = precompute distance tables,
1168
+ * 1 = precompute pointers to distances, 0 = compute distances one by one).
1169
+ * Currently only 2 is supported
1170
+ *
1171
+ * use_sel: store or ignore the IDSelector
1172
+ */
1173
+ template <MetricType METRIC_TYPE, class C, class PQDecoder, bool use_sel>
1019
1174
  struct IVFPQScanner : IVFPQScannerT<Index::idx_t, METRIC_TYPE, PQDecoder>,
1020
1175
  InvertedListScanner {
1021
1176
  int precompute_mode;
1177
+ const IDSelector* sel;
1022
1178
 
1023
- IVFPQScanner(const IndexIVFPQ& ivfpq, bool store_pairs, int precompute_mode)
1179
+ IVFPQScanner(
1180
+ const IndexIVFPQ& ivfpq,
1181
+ bool store_pairs,
1182
+ int precompute_mode,
1183
+ const IDSelector* sel)
1024
1184
  : IVFPQScannerT<Index::idx_t, METRIC_TYPE, PQDecoder>(
1025
1185
  ivfpq,
1026
1186
  nullptr),
1027
- precompute_mode(precompute_mode) {
1187
+ precompute_mode(precompute_mode),
1188
+ sel(sel) {
1028
1189
  this->store_pairs = store_pairs;
1029
1190
  }
1030
1191
 
@@ -1057,9 +1218,10 @@ struct IVFPQScanner : IVFPQScannerT<Index::idx_t, METRIC_TYPE, PQDecoder>,
1057
1218
  float* heap_sim,
1058
1219
  idx_t* heap_ids,
1059
1220
  size_t k) const override {
1060
- KnnSearchResults<C> res = {
1221
+ KnnSearchResults<C, use_sel> res = {
1061
1222
  /* key */ this->key,
1062
1223
  /* ids */ this->store_pairs ? nullptr : ids,
1224
+ /* sel */ this->sel,
1063
1225
  /* k */ k,
1064
1226
  /* heap_sim */ heap_sim,
1065
1227
  /* heap_ids */ heap_ids,
@@ -1086,9 +1248,10 @@ struct IVFPQScanner : IVFPQScannerT<Index::idx_t, METRIC_TYPE, PQDecoder>,
1086
1248
  const idx_t* ids,
1087
1249
  float radius,
1088
1250
  RangeQueryResult& rres) const override {
1089
- RangeSearchResults<C> res = {
1251
+ RangeSearchResults<C, use_sel> res = {
1090
1252
  /* key */ this->key,
1091
1253
  /* ids */ this->store_pairs ? nullptr : ids,
1254
+ /* sel */ this->sel,
1092
1255
  /* radius */ radius,
1093
1256
  /* rres */ rres};
1094
1257
 
@@ -1107,32 +1270,53 @@ struct IVFPQScanner : IVFPQScannerT<Index::idx_t, METRIC_TYPE, PQDecoder>,
1107
1270
  }
1108
1271
  };
1109
1272
 
1110
- template <class PQDecoder>
1273
+ template <class PQDecoder, bool use_sel>
1111
1274
  InvertedListScanner* get_InvertedListScanner1(
1112
1275
  const IndexIVFPQ& index,
1113
- bool store_pairs) {
1276
+ bool store_pairs,
1277
+ const IDSelector* sel) {
1114
1278
  if (index.metric_type == METRIC_INNER_PRODUCT) {
1115
1279
  return new IVFPQScanner<
1116
1280
  METRIC_INNER_PRODUCT,
1117
1281
  CMin<float, idx_t>,
1118
- PQDecoder>(index, store_pairs, 2);
1282
+ PQDecoder,
1283
+ use_sel>(index, store_pairs, 2, sel);
1119
1284
  } else if (index.metric_type == METRIC_L2) {
1120
- return new IVFPQScanner<METRIC_L2, CMax<float, idx_t>, PQDecoder>(
1121
- index, store_pairs, 2);
1285
+ return new IVFPQScanner<
1286
+ METRIC_L2,
1287
+ CMax<float, idx_t>,
1288
+ PQDecoder,
1289
+ use_sel>(index, store_pairs, 2, sel);
1122
1290
  }
1123
1291
  return nullptr;
1124
1292
  }
1125
1293
 
1294
+ template <bool use_sel>
1295
+ InvertedListScanner* get_InvertedListScanner2(
1296
+ const IndexIVFPQ& index,
1297
+ bool store_pairs,
1298
+ const IDSelector* sel) {
1299
+ if (index.pq.nbits == 8) {
1300
+ return get_InvertedListScanner1<PQDecoder8, use_sel>(
1301
+ index, store_pairs, sel);
1302
+ } else if (index.pq.nbits == 16) {
1303
+ return get_InvertedListScanner1<PQDecoder16, use_sel>(
1304
+ index, store_pairs, sel);
1305
+ } else {
1306
+ return get_InvertedListScanner1<PQDecoderGeneric, use_sel>(
1307
+ index, store_pairs, sel);
1308
+ }
1309
+ }
1310
+
1126
1311
  } // anonymous namespace
1127
1312
 
1128
1313
  InvertedListScanner* IndexIVFPQ::get_InvertedListScanner(
1129
- bool store_pairs) const {
1130
- if (pq.nbits == 8) {
1131
- return get_InvertedListScanner1<PQDecoder8>(*this, store_pairs);
1132
- } else if (pq.nbits == 16) {
1133
- return get_InvertedListScanner1<PQDecoder16>(*this, store_pairs);
1314
+ bool store_pairs,
1315
+ const IDSelector* sel) const {
1316
+ if (sel) {
1317
+ return get_InvertedListScanner2<true>(*this, store_pairs, sel);
1134
1318
  } else {
1135
- return get_InvertedListScanner1<PQDecoderGeneric>(*this, store_pairs);
1319
+ return get_InvertedListScanner2<false>(*this, store_pairs, sel);
1136
1320
  }
1137
1321
  return nullptr;
1138
1322
  }
@@ -134,7 +134,8 @@ struct IndexIVFPQ : IndexIVF {
134
134
  float* x) const;
135
135
 
136
136
  InvertedListScanner* get_InvertedListScanner(
137
- bool store_pairs) const override;
137
+ bool store_pairs,
138
+ const IDSelector* sel) const override;
138
139
 
139
140
  /// build precomputed table
140
141
  void precompute_table();
@@ -142,6 +143,9 @@ struct IndexIVFPQ : IndexIVF {
142
143
  IndexIVFPQ();
143
144
  };
144
145
 
146
+ // block size used in IndexIVFPQ::add_core_o
147
+ FAISS_API extern int index_ivfpq_add_core_o_bs;
148
+
145
149
  /** Pre-compute distance tables for IVFPQ with by-residual and METRIC_L2
146
150
  *
147
151
  * @param use_precomputed_table (I/O)