faiss 0.6.1 → 0.6.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 (186) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/lib/faiss/version.rb +1 -1
  4. data/vendor/faiss/faiss/AutoTune.cpp +3 -1
  5. data/vendor/faiss/faiss/Clustering.cpp +9 -1
  6. data/vendor/faiss/faiss/IVFlib.cpp +14 -3
  7. data/vendor/faiss/faiss/Index.h +2 -2
  8. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +9 -10
  9. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +2 -3
  10. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +1 -2
  11. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +10 -12
  12. data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
  13. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +5 -7
  14. data/vendor/faiss/faiss/IndexEDEN.cpp +273 -0
  15. data/vendor/faiss/faiss/IndexEDEN.h +57 -0
  16. data/vendor/faiss/faiss/IndexFastScan.cpp +15 -4
  17. data/vendor/faiss/faiss/IndexFlat.cpp +13 -50
  18. data/vendor/faiss/faiss/IndexHNSW.cpp +177 -148
  19. data/vendor/faiss/faiss/IndexIDMap.cpp +16 -3
  20. data/vendor/faiss/faiss/IndexIDMap.h +2 -0
  21. data/vendor/faiss/faiss/IndexIVF.cpp +19 -8
  22. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +3 -3
  23. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +3 -4
  24. data/vendor/faiss/faiss/IndexIVFEDEN.cpp +302 -0
  25. data/vendor/faiss/faiss/IndexIVFEDEN.h +70 -0
  26. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +5 -6
  27. data/vendor/faiss/faiss/IndexIVFFlat.cpp +6 -5
  28. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +3 -3
  29. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +1 -1
  30. data/vendor/faiss/faiss/IndexIVFPQ.cpp +42 -25
  31. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +0 -1
  32. data/vendor/faiss/faiss/IndexIVFPQR.cpp +2 -3
  33. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +23 -62
  34. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +180 -76
  35. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -4
  36. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +8 -6
  37. data/vendor/faiss/faiss/IndexLSH.cpp +2 -3
  38. data/vendor/faiss/faiss/IndexLattice.cpp +5 -0
  39. data/vendor/faiss/faiss/IndexNNDescent.cpp +10 -3
  40. data/vendor/faiss/faiss/IndexNSG.cpp +8 -4
  41. data/vendor/faiss/faiss/IndexPQ.cpp +6 -8
  42. data/vendor/faiss/faiss/IndexPreTransform.cpp +15 -0
  43. data/vendor/faiss/faiss/IndexRaBitQ.cpp +2 -2
  44. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +1 -2
  45. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +5 -1
  46. data/vendor/faiss/faiss/IndexRefine.cpp +30 -1
  47. data/vendor/faiss/faiss/IndexReplicas.cpp +1 -2
  48. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +68 -6
  49. data/vendor/faiss/faiss/IndexScalarQuantizer.h +10 -0
  50. data/vendor/faiss/faiss/IndexShards.cpp +2 -2
  51. data/vendor/faiss/faiss/IndexShardsIVF.cpp +2 -2
  52. data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
  53. data/vendor/faiss/faiss/SuperKMeans.cpp +256 -240
  54. data/vendor/faiss/faiss/SuperKMeans.h +30 -0
  55. data/vendor/faiss/faiss/VectorTransform.cpp +33 -2
  56. data/vendor/faiss/faiss/clone_index.cpp +5 -0
  57. data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +1 -1
  58. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +902 -12
  59. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +702 -10
  60. data/vendor/faiss/faiss/factory_tools.cpp +51 -4
  61. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
  62. data/vendor/faiss/faiss/gpu/GpuIndex.h +34 -11
  63. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +47 -0
  64. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +17 -0
  65. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +16 -0
  66. data/vendor/faiss/faiss/gpu/GpuResources.h +3 -2
  67. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +11 -12
  68. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +3 -3
  69. data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +1 -1
  70. data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +2 -2
  71. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +180 -0
  72. data/vendor/faiss/faiss/gpu_metal/MetalDistance.h +87 -0
  73. data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +7 -0
  74. data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +177 -0
  75. data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +88 -0
  76. data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +48 -3
  77. data/vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h +45 -0
  78. data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFFlat.h +193 -0
  79. data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFPQ.h +134 -0
  80. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +2 -2
  81. data/vendor/faiss/faiss/impl/DistanceComputer.h +34 -0
  82. data/vendor/faiss/faiss/impl/EDENQuantizer.h +119 -0
  83. data/vendor/faiss/faiss/impl/HNSW.cpp +658 -344
  84. data/vendor/faiss/faiss/impl/HNSW.h +51 -13
  85. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
  86. data/vendor/faiss/faiss/impl/NSG.cpp +18 -12
  87. data/vendor/faiss/faiss/impl/Panorama.h +20 -7
  88. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
  89. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +59 -24
  90. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +45 -37
  91. data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
  92. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +175 -68
  93. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +19 -0
  94. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +2 -11
  95. data/vendor/faiss/faiss/impl/ResultHandler.h +26 -31
  96. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +522 -58
  97. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +70 -0
  98. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
  99. data/vendor/faiss/faiss/impl/VisitedTable.cpp +33 -13
  100. data/vendor/faiss/faiss/impl/VisitedTable.h +88 -33
  101. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +1 -1
  102. data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
  103. data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +38 -3
  104. data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +1 -1
  105. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +35 -43
  106. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +64 -15
  107. data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +86 -40
  108. data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +81 -50
  109. data/vendor/faiss/faiss/impl/index_read.cpp +476 -75
  110. data/vendor/faiss/faiss/impl/index_write.cpp +56 -4
  111. data/vendor/faiss/faiss/impl/io_macros.h +25 -0
  112. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +8 -9
  113. data/vendor/faiss/faiss/impl/platform_macros.h +15 -9
  114. data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +284 -0
  115. data/vendor/faiss/faiss/impl/polysemous_training/dispatch.h +115 -0
  116. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +0 -1
  117. data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +26 -15
  118. data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +6 -4
  119. data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +2 -0
  120. data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +2 -0
  121. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +20 -0
  122. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +36 -0
  123. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +5 -0
  124. data/vendor/faiss/faiss/impl/pq_code_distance/pq_scan_impl.h +105 -0
  125. data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +2 -0
  126. data/vendor/faiss/faiss/impl/result_handler/ResultHandler.cpp +195 -0
  127. data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +133 -0
  128. data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +281 -0
  129. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +72 -0
  130. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +228 -0
  131. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp +882 -0
  132. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +6 -0
  133. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +336 -26
  134. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +331 -32
  135. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +553 -0
  136. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +558 -0
  137. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +284 -45
  138. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +502 -3
  139. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +157 -32
  140. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +26 -0
  141. data/vendor/faiss/faiss/impl/simd_dispatch.h +86 -8
  142. data/vendor/faiss/faiss/index_factory.cpp +37 -7
  143. data/vendor/faiss/faiss/index_io.h +16 -0
  144. data/vendor/faiss/faiss/invlists/DirectMap.cpp +5 -2
  145. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +15 -15
  146. data/vendor/faiss/faiss/invlists/InvertedLists.h +2 -2
  147. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +19 -4
  148. data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -1
  149. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +60 -0
  150. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +26 -1
  151. data/vendor/faiss/faiss/svs/IndexSVSFlat.h +13 -0
  152. data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +1 -1
  153. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +1 -1
  154. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +150 -23
  155. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +30 -7
  156. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +3 -2
  157. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +2 -1
  158. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +65 -25
  159. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +3 -2
  160. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
  161. data/vendor/faiss/faiss/utils/bf16.h +34 -0
  162. data/vendor/faiss/faiss/utils/distances.cpp +14 -2
  163. data/vendor/faiss/faiss/utils/distances_simd.cpp +4 -4
  164. data/vendor/faiss/faiss/utils/extra_distances.cpp +4 -14
  165. data/vendor/faiss/faiss/utils/extra_distances.h +1 -2
  166. data/vendor/faiss/faiss/utils/hamming.cpp +9 -9
  167. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +2 -1
  168. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_spr.cpp +15 -0
  169. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +6 -30
  170. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512_spr.h +171 -0
  171. data/vendor/faiss/faiss/utils/partitioning.cpp +0 -2
  172. data/vendor/faiss/faiss/utils/quantize_lut.cpp +29 -8
  173. data/vendor/faiss/faiss/utils/rabitq_simd.h +202 -0
  174. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +0 -1
  175. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +263 -15
  176. data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +160 -18
  177. data/vendor/faiss/faiss/utils/simd_impl/partitioning_simdlib256.h +14 -68
  178. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
  179. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +273 -0
  180. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_spr.cpp +435 -0
  181. data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +11 -0
  182. data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +143 -6
  183. data/vendor/faiss/faiss/utils/simd_levels.cpp +56 -2
  184. data/vendor/faiss/faiss/utils/simd_levels.h +14 -0
  185. data/vendor/faiss/faiss/utils/utils.cpp +9 -27
  186. metadata +27 -2
@@ -14,8 +14,10 @@
14
14
  #include <faiss/IndexBinaryFlat.h>
15
15
  #include <faiss/IndexBinaryHNSW.h>
16
16
  #include <faiss/IndexBinaryIVF.h>
17
+ #include <faiss/IndexEDEN.h>
17
18
  #include <faiss/IndexHNSW.h>
18
19
  #include <faiss/IndexIDMap.h>
20
+ #include <faiss/IndexIVFEDEN.h>
19
21
  #include <faiss/IndexIVFFlat.h>
20
22
  #include <faiss/IndexIVFPQFastScan.h>
21
23
  #include <faiss/IndexIVFRaBitQ.h>
@@ -33,16 +35,26 @@ namespace {
33
35
  const std::map<faiss::ScalarQuantizer::QuantizerType, std::string> sq_types = {
34
36
  {faiss::ScalarQuantizer::QT_8bit, "SQ8"},
35
37
  {faiss::ScalarQuantizer::QT_4bit, "SQ4"},
38
+ // QT_8bit_uniform and QT_4bit_uniform have no round-trippable
39
+ // index_factory string; the names below are synthetic identifiers used
40
+ // for telemetry logging only.
41
+ {faiss::ScalarQuantizer::QT_8bit_uniform, "SQ8u"},
42
+ {faiss::ScalarQuantizer::QT_4bit_uniform, "SQ4u"},
36
43
  {faiss::ScalarQuantizer::QT_6bit, "SQ6"},
37
44
  {faiss::ScalarQuantizer::QT_fp16, "SQfp16"},
38
45
  {faiss::ScalarQuantizer::QT_bf16, "SQbf16"},
39
46
  {faiss::ScalarQuantizer::QT_8bit_direct_signed, "SQ8_direct_signed"},
40
47
  {faiss::ScalarQuantizer::QT_8bit_direct, "SQ8_direct"},
48
+ {faiss::ScalarQuantizer::QT_0bit, "SQ0"},
41
49
  {faiss::ScalarQuantizer::QT_1bit_tqmse, "SQtqmse1"},
42
50
  {faiss::ScalarQuantizer::QT_2bit_tqmse, "SQtqmse2"},
43
51
  {faiss::ScalarQuantizer::QT_3bit_tqmse, "SQtqmse3"},
44
52
  {faiss::ScalarQuantizer::QT_4bit_tqmse, "SQtqmse4"},
45
53
  {faiss::ScalarQuantizer::QT_8bit_tqmse, "SQtqmse8"},
54
+ {faiss::ScalarQuantizer::QT_2bit_tq, "SQtq2"},
55
+ {faiss::ScalarQuantizer::QT_3bit_tq, "SQtq3"},
56
+ {faiss::ScalarQuantizer::QT_4bit_tq, "SQtq4"},
57
+ {faiss::ScalarQuantizer::QT_5bit_tq, "SQtq5"},
46
58
  };
47
59
 
48
60
  int get_hnsw_M(const faiss::IndexHNSW* index) {
@@ -61,6 +73,19 @@ int get_hnsw_M(const faiss::IndexBinaryHNSW* index) {
61
73
  return 0;
62
74
  }
63
75
 
76
+ std::string eden_factory_string(
77
+ const faiss::ScalarQuantizer& sq,
78
+ faiss::EDENScaleType scale_type) {
79
+ std::string result = "EDEN";
80
+ if (sq.bits != 1) {
81
+ result += std::to_string(sq.bits);
82
+ }
83
+ if (scale_type == faiss::EDENScaleType_BIASED) {
84
+ result += "BIASED";
85
+ }
86
+ return result;
87
+ }
88
+
64
89
  } // namespace
65
90
 
66
91
  // Reference for reverse_index_factory:
@@ -110,8 +135,17 @@ std::string reverse_index_factory(const faiss::Index* index) {
110
135
  ivf_index)) {
111
136
  return prefix + ",PQ" + std::to_string(ivfpqfs_index->pq.M) + "x" +
112
137
  std::to_string(ivfpqfs_index->pq.nbits) + "fs";
113
- } else if (dynamic_cast<const faiss::IndexIVFRaBitQ*>(ivf_index)) {
114
- return prefix + ",RaBitQ";
138
+ } else if (
139
+ const faiss::IndexIVFRaBitQ* ivfrabitq_index =
140
+ dynamic_cast<const faiss::IndexIVFRaBitQ*>(ivf_index)) {
141
+ size_t nb_bits = ivfrabitq_index->rabitq.nb_bits;
142
+ return prefix + ",RaBitQ" +
143
+ (nb_bits == 1 ? "" : std::to_string(nb_bits));
144
+ } else if (
145
+ const faiss::IndexIVFEDEN* ivf_eden =
146
+ dynamic_cast<const faiss::IndexIVFEDEN*>(ivf_index)) {
147
+ return prefix + "," +
148
+ eden_factory_string(ivf_eden->sq, ivf_eden->scale_type);
115
149
  }
116
150
  } else if (
117
151
  const faiss::IndexPreTransform* pretransform_index =
@@ -180,12 +214,25 @@ std::string reverse_index_factory(const faiss::Index* index) {
180
214
  const faiss::IndexScalarQuantizer* sq_index =
181
215
  dynamic_cast<const faiss::IndexScalarQuantizer*>(index)) {
182
216
  return sq_types.at(sq_index->sq.qtype);
217
+ } else if (
218
+ // IndexIDMap2 inherits IndexIDMap — check subclass first.
219
+ const faiss::IndexIDMap2* idmap2 =
220
+ dynamic_cast<const faiss::IndexIDMap2*>(index)) {
221
+ return std::string("IDMap2,") + reverse_index_factory(idmap2->index);
183
222
  } else if (
184
223
  const faiss::IndexIDMap* idmap =
185
224
  dynamic_cast<const faiss::IndexIDMap*>(index)) {
186
225
  return std::string("IDMap,") + reverse_index_factory(idmap->index);
187
- } else if (dynamic_cast<const faiss::IndexRaBitQ*>(index)) {
188
- return "RaBitQ";
226
+ } else if (
227
+ const faiss::IndexRaBitQ* rabitq_index =
228
+ dynamic_cast<const faiss::IndexRaBitQ*>(index)) {
229
+ size_t nb_bits = rabitq_index->rabitq.nb_bits;
230
+ return "RaBitQ" +
231
+ (nb_bits == 1 ? std::string() : std::to_string(nb_bits));
232
+ } else if (
233
+ const faiss::IndexEDEN* eden =
234
+ dynamic_cast<const faiss::IndexEDEN*>(index)) {
235
+ return eden_factory_string(eden->sq, eden->scale_type);
189
236
  }
190
237
  // Avoid runtime error, just return empty string for logging.
191
238
  return "";
@@ -14,7 +14,7 @@
14
14
 
15
15
  #include <faiss/IndexBinaryFlat.h>
16
16
  #include <faiss/IndexFlat.h>
17
- #if defined USE_NVIDIA_CUVS
17
+ #if defined(USE_NVIDIA_CUVS) && !defined(FAISS_CUVS_NO_CAGRA)
18
18
  #include <faiss/IndexBinaryHNSW.h>
19
19
  #include <faiss/IndexHNSW.h>
20
20
  #endif
@@ -28,7 +28,7 @@
28
28
  #include <faiss/MetaIndexes.h>
29
29
  #include <faiss/gpu/GpuIndex.h>
30
30
  #include <faiss/gpu/GpuIndexBinaryFlat.h>
31
- #if defined USE_NVIDIA_CUVS
31
+ #if defined(USE_NVIDIA_CUVS) && !defined(FAISS_CUVS_NO_CAGRA)
32
32
  #include <faiss/gpu/GpuIndexBinaryCagra.h>
33
33
  #include <faiss/gpu/GpuIndexCagra.h>
34
34
  #endif
@@ -92,7 +92,7 @@ Index* ToCPUCloner::clone_Index(const Index* index) {
92
92
  // (inverse op of ToGpuClonerMultiple)
93
93
 
94
94
  }
95
- #if defined USE_NVIDIA_CUVS
95
+ #if defined(USE_NVIDIA_CUVS) && !defined(FAISS_CUVS_NO_CAGRA)
96
96
  else if (auto icg = dynamic_cast<const GpuIndexCagra*>(index)) {
97
97
  IndexHNSWCagra* res = new IndexHNSWCagra();
98
98
  if (icg->get_numeric_type() != faiss::NumericType::Float32) {
@@ -150,8 +150,8 @@ Index* ToGpuCloner::clone_Index(const Index* index) {
150
150
  GpuIndexFlatConfig config;
151
151
  config.device = device;
152
152
  config.useFloat16 = true;
153
- FAISS_THROW_IF_NOT_MSG(
154
- !use_cuvs, "this type of index is not implemented for cuVS");
153
+ FAISS_THROW_IF_MSG(
154
+ use_cuvs, "this type of index is not implemented for cuVS");
155
155
  GpuIndexFlat* gif = new GpuIndexFlat(
156
156
  provider, index->d, index->metric_type, config);
157
157
  // transfer data by blocks
@@ -187,8 +187,8 @@ Index* ToGpuCloner::clone_Index(const Index* index) {
187
187
  config.device = device;
188
188
  config.indicesOptions = indicesOptions;
189
189
  config.flatConfig.useFloat16 = useFloat16CoarseQuantizer;
190
- FAISS_THROW_IF_NOT_MSG(
191
- !use_cuvs, "this type of index is not implemented for cuVS");
190
+ config.use_cuvs = use_cuvs;
191
+ config.allowCpuCoarseQuantizer = allowCpuCoarseQuantizer;
192
192
 
193
193
  GpuIndexIVFScalarQuantizer* res = new GpuIndexIVFScalarQuantizer(
194
194
  provider,
@@ -233,7 +233,7 @@ Index* ToGpuCloner::clone_Index(const Index* index) {
233
233
 
234
234
  return res;
235
235
  }
236
- #if defined USE_NVIDIA_CUVS
236
+ #if defined(USE_NVIDIA_CUVS) && !defined(FAISS_CUVS_NO_CAGRA)
237
237
  else if (auto icg = dynamic_cast<const faiss::IndexHNSWCagra*>(index)) {
238
238
  GpuIndexCagraConfig config;
239
239
  config.device = device;
@@ -533,7 +533,7 @@ faiss::IndexBinary* index_binary_gpu_to_cpu(
533
533
  ii->copyTo(ret);
534
534
  return ret;
535
535
  }
536
- #if defined USE_NVIDIA_CUVS
536
+ #if defined(USE_NVIDIA_CUVS) && !defined(FAISS_CUVS_NO_CAGRA)
537
537
  else if (auto ii = dynamic_cast<const GpuIndexBinaryCagra*>(gpu_index)) {
538
538
  IndexBinaryHNSWCagra* ret = new IndexBinaryHNSWCagra();
539
539
  ii->copyTo(ret);
@@ -549,13 +549,13 @@ faiss::IndexBinary* index_binary_cpu_to_gpu(
549
549
  GpuResourcesProvider* provider,
550
550
  int device,
551
551
  const faiss::IndexBinary* index,
552
- const GpuClonerOptions* options) {
552
+ const GpuClonerOptions* /*options*/) {
553
553
  if (auto ii = dynamic_cast<const IndexBinaryFlat*>(index)) {
554
554
  GpuIndexBinaryFlatConfig config;
555
555
  config.device = device;
556
556
  return new GpuIndexBinaryFlat(provider, ii, config);
557
557
  }
558
- #if defined USE_NVIDIA_CUVS
558
+ #if defined(USE_NVIDIA_CUVS) && !defined(FAISS_CUVS_NO_CAGRA)
559
559
  else if (
560
560
  auto ii = dynamic_cast<const faiss::IndexBinaryHNSWCagra*>(index)) {
561
561
  GpuIndexCagraConfig config;
@@ -177,6 +177,33 @@ class GpuIndex : public faiss::Index {
177
177
  }
178
178
  };
179
179
 
180
+ virtual void addImplPrecomputed_(
181
+ idx_t n,
182
+ const float* x,
183
+ const idx_t* ids,
184
+ const idx_t* precomputed_idx);
185
+
186
+ virtual void addImplPrecomputed_ex_(
187
+ idx_t n,
188
+ const void* x,
189
+ NumericType numeric_type,
190
+ const idx_t* ids,
191
+ const idx_t* precomputed_idx);
192
+
193
+ /// Handles paged adds if the add set is too large, passes to
194
+ /// addImpl_ to actually perform the add for the current page
195
+ void addPaged_(
196
+ idx_t n,
197
+ const float* x,
198
+ const idx_t* ids,
199
+ const idx_t* precomputed_idx = nullptr);
200
+ void addPaged_ex_(
201
+ idx_t n,
202
+ const void* x,
203
+ NumericType numeric_type,
204
+ const idx_t* ids,
205
+ const idx_t* precomputed_idx = nullptr);
206
+
180
207
  /// Overridden to actually perform the search
181
208
  /// All data is guaranteed to be resident on our device
182
209
  virtual void searchImpl_(
@@ -209,22 +236,18 @@ class GpuIndex : public faiss::Index {
209
236
  }
210
237
 
211
238
  private:
212
- /// Handles paged adds if the add set is too large, passes to
213
- /// addImpl_ to actually perform the add for the current page
214
- void addPaged_(idx_t n, const float* x, const idx_t* ids);
215
- void addPaged_ex_(
216
- idx_t n,
217
- const void* x,
218
- NumericType numeric_type,
219
- const idx_t* ids);
220
-
221
239
  /// Calls addImpl_ for a single page of GPU-resident data
222
- void addPage_(idx_t n, const float* x, const idx_t* ids);
240
+ void addPage_(
241
+ idx_t n,
242
+ const float* x,
243
+ const idx_t* ids,
244
+ const idx_t* precomputed_idx = nullptr);
223
245
  void addPage_ex_(
224
246
  idx_t n,
225
247
  const void* x,
226
248
  NumericType numeric_type,
227
- const idx_t* ids);
249
+ const idx_t* ids,
250
+ const idx_t* precomputed_idx = nullptr);
228
251
 
229
252
  /// Calls searchImpl_ for a single page of GPU-resident data
230
253
  void searchNonPaged_(
@@ -284,6 +284,46 @@ struct GpuIndexCagra : public GpuIndex {
284
284
  /// in the index instance
285
285
  void copyTo(faiss::IndexHNSWCagra* index) const;
286
286
 
287
+ /// Train CAGRA using multiple GPUs by sharding the dataset.
288
+ /// Uses cuVS native SNMG (single-node multi-GPU) CAGRA build.
289
+ /// Each device builds one shard in parallel via OpenMP.
290
+ /// Float32 only. After training, call copyTo() to produce a CPU
291
+ /// IndexHNSWCagra with full HNSW upper levels.
292
+ /// The training data pointer must remain valid until copyTo() completes.
293
+ /// stitch_mode: 0=CPU HNSW (Approach C), 1=GPU brute-force (Approach B)
294
+ void trainMultiGpu(
295
+ idx_t n,
296
+ const float* x,
297
+ std::vector<GpuResourcesProvider*>& providers,
298
+ std::vector<int>& devices,
299
+ idx_t stitch_per_shard = 0,
300
+ int stitch_k = 2,
301
+ int stitch_mode = 0);
302
+
303
+ /// Build a unified CAGRA graph using cuVS all_neighbors
304
+ /// (multi-GPU kNN graph construction with overlapping clusters) followed
305
+ /// by cagra::optimize (graph pruning). Produces a single unified graph
306
+ /// without stitching. The training data pointer must remain valid until
307
+ /// copyTo() completes.
308
+ /// build_algo: 0=NN-descent (default), 1=brute-force, 2=IVF-PQ
309
+ /// refinement_rate: IVF-PQ refinement multiplier (only used when
310
+ /// build_algo==2). Higher values trade build time for recall; the cuVS
311
+ /// default is 2.0.
312
+ /// ivfpq_search_batch: cap the IVF-PQ search `max_internal_batch_size` used
313
+ /// during the all_neighbors kNN build (build_algo==2). 0 = cuVS default
314
+ /// (128*1024), which can OOM at 100M; a smaller value (e.g. 8192) bounds
315
+ /// the GPU search workspace with no effect on results (recall-neutral).
316
+ void trainAllNeighbors(
317
+ idx_t n,
318
+ const float* x,
319
+ std::vector<int>& devices,
320
+ int n_clusters = 0,
321
+ int overlap_factor = 0,
322
+ bool multi_gpu_optimize = false,
323
+ int build_algo = 0,
324
+ float refinement_rate = 2.0f,
325
+ int ivfpq_search_batch = 0);
326
+
287
327
  void reset() override;
288
328
 
289
329
  std::vector<idx_t> get_knngraph() const;
@@ -317,6 +357,8 @@ struct GpuIndexCagra : public GpuIndex {
317
357
  idx_t* labels,
318
358
  const SearchParameters* search_params) const override;
319
359
 
360
+ void copyToMultiGpu_(faiss::IndexHNSWCagra* index) const;
361
+
320
362
  /// Our configuration options
321
363
  const GpuIndexCagraConfig cagraConfig_;
322
364
 
@@ -329,6 +371,11 @@ struct GpuIndexCagra : public GpuIndex {
329
371
  std::shared_ptr<CuvsCagra<half>>,
330
372
  std::shared_ptr<CuvsCagra<int8_t>>>
331
373
  index_;
374
+
375
+ /// Multi-GPU state: populated by trainMultiGpu(), used by copyTo()
376
+ std::vector<idx_t> merged_knngraph_;
377
+ idx_t merged_knngraph_degree_ = 0;
378
+ const float* multi_gpu_dataset_ = nullptr;
332
379
  };
333
380
 
334
381
  } // namespace gpu
@@ -98,6 +98,17 @@ class GpuIndexIVF : public GpuIndex, public IndexIVFInterface {
98
98
  /// debugging purposes.
99
99
  virtual std::vector<idx_t> getListIndices(idx_t listId) const;
100
100
 
101
+ /// Add vectors with precomputed IVF list assignments.
102
+ /// Same naming and argument order as IndexIVF::add_core.
103
+ /// `x`, `xids`, and `precomputed_idx` can be resident on the CPU or any
104
+ /// GPU; copies are performed as needed.
105
+ void add_core(
106
+ idx_t n,
107
+ const float* x,
108
+ const idx_t* xids,
109
+ const idx_t* precomputed_idx,
110
+ void* inverted_list_context = nullptr);
111
+
101
112
  void search_preassigned(
102
113
  idx_t n,
103
114
  const float* x,
@@ -133,6 +144,12 @@ class GpuIndexIVF : public GpuIndex, public IndexIVFInterface {
133
144
  /// Called from GpuIndex for add/add_with_ids
134
145
  void addImpl_(idx_t n, const float* x, const idx_t* ids) override;
135
146
 
147
+ void addImplPrecomputed_(
148
+ idx_t n,
149
+ const float* x,
150
+ const idx_t* xids,
151
+ const idx_t* precomputed_idx) override;
152
+
136
153
  /// Called from GpuIndex for search
137
154
  void searchImpl_(
138
155
  idx_t n,
@@ -93,6 +93,22 @@ class GpuIndexIVFScalarQuantizer : public GpuIndexIVF {
93
93
  /// Validates index SQ parameters
94
94
  void verifySQSettings_() const;
95
95
 
96
+ /// Whether this index configuration can use cuVS IVF-SQ
97
+ bool shouldUseCuvs_() const;
98
+
99
+ /// Construct the backing IVF implementation
100
+ void setIndex_(
101
+ GpuResources* resources,
102
+ int dim,
103
+ idx_t nlist,
104
+ faiss::MetricType metric,
105
+ float metricArg,
106
+ bool useResidual,
107
+ faiss::ScalarQuantizer* scalarQ,
108
+ bool interleavedLayout,
109
+ IndicesOptions indicesOptions,
110
+ MemorySpace space);
111
+
96
112
  /// Called from train to handle SQ residual training
97
113
  void trainResiduals_(idx_t n, const float* x);
98
114
 
@@ -33,7 +33,8 @@
33
33
 
34
34
  #if defined USE_NVIDIA_CUVS
35
35
  #include <raft/core/device_resources.hpp>
36
- #include <rmm/mr/device_memory_resource.hpp>
36
+ #include <cuda/memory_resource>
37
+ #include <optional>
37
38
  #endif
38
39
 
39
40
  namespace faiss {
@@ -163,7 +164,7 @@ struct AllocRequest : public AllocInfo {
163
164
  size_t size = 0;
164
165
 
165
166
  #if defined USE_NVIDIA_CUVS
166
- rmm::mr::device_memory_resource* mr = nullptr;
167
+ std::optional<cuda::mr::any_resource<cuda::mr::device_accessible>> mr;
167
168
  #endif
168
169
  };
169
170
 
@@ -92,8 +92,8 @@ std::string allocsToString(const std::unordered_map<void*, AllocRequest>& map) {
92
92
  StandardGpuResourcesImpl::StandardGpuResourcesImpl()
93
93
  :
94
94
  #if defined USE_NVIDIA_CUVS
95
- mmr_(new rmm::mr::managed_memory_resource),
96
- pmr_(new rmm::mr::pinned_host_memory_resource),
95
+ mmr_{},
96
+ pmr_{},
97
97
  #endif
98
98
  pinnedMemAlloc_(nullptr),
99
99
  pinnedMemAllocSize_(0),
@@ -164,7 +164,7 @@ StandardGpuResourcesImpl::~StandardGpuResourcesImpl() {
164
164
 
165
165
  if (pinnedMemAlloc_) {
166
166
  #if defined USE_NVIDIA_CUVS
167
- pmr_->deallocate_sync(pinnedMemAlloc_, pinnedMemAllocSize_);
167
+ pmr_.deallocate_sync(pinnedMemAlloc_, pinnedMemAllocSize_);
168
168
  #else
169
169
  auto err = cudaFreeHost(pinnedMemAlloc_);
170
170
  FAISS_ASSERT_FMT(
@@ -350,7 +350,7 @@ void StandardGpuResourcesImpl::initializeForDevice(int device) {
350
350
  // pinned memory allocation
351
351
  if (defaultStreams_.empty() && pinnedMemSize_ > 0) {
352
352
  try {
353
- pinnedMemAlloc_ = pmr_->allocate_sync(pinnedMemSize_);
353
+ pinnedMemAlloc_ = pmr_.allocate_sync(pinnedMemSize_);
354
354
  } catch (const std::bad_alloc& rmm_ex) {
355
355
  FAISS_THROW_MSG("CUDA memory allocation error");
356
356
  }
@@ -546,10 +546,9 @@ void* StandardGpuResourcesImpl::allocMemory(const AllocRequest& req) {
546
546
  } else if (adjReq.space == MemorySpace::Device) {
547
547
  #if defined USE_NVIDIA_CUVS
548
548
  try {
549
- rmm::mr::device_memory_resource* current_mr =
550
- rmm::mr::get_per_device_resource(
551
- rmm::cuda_device_id{adjReq.device});
552
- p = current_mr->allocate(adjReq.stream, adjReq.size);
549
+ auto current_mr = rmm::mr::get_per_device_resource_ref(
550
+ rmm::cuda_device_id{adjReq.device});
551
+ p = current_mr.allocate(adjReq.stream, adjReq.size);
553
552
  adjReq.mr = current_mr;
554
553
  } catch (const std::bad_alloc& rmm_ex) {
555
554
  FAISS_THROW_MSG("CUDA memory allocation error");
@@ -562,7 +561,7 @@ void* StandardGpuResourcesImpl::allocMemory(const AllocRequest& req) {
562
561
  // FIXME: as of CUDA 11, a memory allocation error appears to be
563
562
  // presented via cudaGetLastError as well, and needs to be
564
563
  // cleared. Just call the function to clear it
565
- cudaGetLastError();
564
+ (void)cudaGetLastError();
566
565
 
567
566
  std::stringstream ss;
568
567
  ss << "StandardGpuResources: alloc fail " << adjReq.toString()
@@ -584,8 +583,8 @@ void* StandardGpuResourcesImpl::allocMemory(const AllocRequest& req) {
584
583
  // TODO: change this to use the current device resource once RMM has
585
584
  // a way to retrieve a "guaranteed" managed memory resource for a
586
585
  // device.
587
- p = mmr_->allocate(adjReq.stream, adjReq.size);
588
- adjReq.mr = mmr_.get();
586
+ p = mmr_.allocate(adjReq.stream, adjReq.size);
587
+ adjReq.mr = mmr_;
589
588
  } catch (const std::bad_alloc& rmm_ex) {
590
589
  FAISS_THROW_MSG("CUDA memory allocation error");
591
590
  }
@@ -596,7 +595,7 @@ void* StandardGpuResourcesImpl::allocMemory(const AllocRequest& req) {
596
595
  // FIXME: as of CUDA 11, a memory allocation error appears to be
597
596
  // presented via cudaGetLastError as well, and needs to be cleared.
598
597
  // Just call the function to clear it
599
- cudaGetLastError();
598
+ (void)cudaGetLastError();
600
599
 
601
600
  std::stringstream ss;
602
601
  ss << "StandardGpuResources: alloc fail " << adjReq.toString()
@@ -25,7 +25,7 @@
25
25
 
26
26
  #if defined USE_NVIDIA_CUVS
27
27
  #include <raft/core/device_resources.hpp>
28
- #include <rmm/mr/device_memory_resource.hpp>
28
+ #include <rmm/mr/managed_memory_resource.hpp>
29
29
  #include <rmm/mr/pinned_host_memory_resource.hpp>
30
30
  #endif
31
31
 
@@ -171,10 +171,10 @@ class StandardGpuResourcesImpl : public GpuResources {
171
171
  */
172
172
 
173
173
  // managed_memory_resource
174
- std::unique_ptr<rmm::mr::device_memory_resource> mmr_;
174
+ rmm::mr::managed_memory_resource mmr_;
175
175
 
176
176
  // pinned_host_memory_resource
177
- std::unique_ptr<rmm::mr::pinned_host_memory_resource> pmr_;
177
+ rmm::mr::pinned_host_memory_resource pmr_;
178
178
  #endif
179
179
 
180
180
  /// Pinned memory allocation for use with this GPU
@@ -42,7 +42,7 @@ using namespace faiss::gpu;
42
42
  int main(int argc, char** argv) {
43
43
  gflags::ParseCommandLineFlags(&argc, &argv, true);
44
44
 
45
- cudaProfilerStop();
45
+ CUDA_VERIFY(cudaProfilerStop());
46
46
 
47
47
  auto seed = FLAGS_seed != -1 ? FLAGS_seed : time(nullptr);
48
48
  printf("using seed %ld\n", seed);
@@ -31,7 +31,7 @@ DEFINE_bool(reserve_memory, false, "whether or not to pre-reserve memory");
31
31
  int main(int argc, char** argv) {
32
32
  gflags::ParseCommandLineFlags(&argc, &argv, true);
33
33
 
34
- cudaProfilerStop();
34
+ CUDA_VERIFY(cudaProfilerStop());
35
35
 
36
36
  int dim = FLAGS_dim;
37
37
  int numCentroids = FLAGS_centroids;
@@ -72,7 +72,7 @@ int main(int argc, char** argv) {
72
72
  }
73
73
  }
74
74
 
75
- cudaDeviceSynchronize();
75
+ CUDA_VERIFY(cudaDeviceSynchronize());
76
76
  CUDA_VERIFY(cudaProfilerStart());
77
77
 
78
78
  float totalGpuTime = 0.0f;