faiss 0.4.3 → 0.5.1

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 +10 -0
  3. data/README.md +2 -0
  4. data/ext/faiss/index.cpp +33 -6
  5. data/ext/faiss/index_binary.cpp +17 -4
  6. data/ext/faiss/kmeans.cpp +6 -6
  7. data/lib/faiss/version.rb +1 -1
  8. data/vendor/faiss/faiss/AutoTune.cpp +2 -3
  9. data/vendor/faiss/faiss/AutoTune.h +1 -1
  10. data/vendor/faiss/faiss/Clustering.cpp +2 -2
  11. data/vendor/faiss/faiss/Clustering.h +2 -2
  12. data/vendor/faiss/faiss/IVFlib.cpp +26 -51
  13. data/vendor/faiss/faiss/IVFlib.h +1 -1
  14. data/vendor/faiss/faiss/Index.cpp +11 -0
  15. data/vendor/faiss/faiss/Index.h +34 -11
  16. data/vendor/faiss/faiss/Index2Layer.cpp +1 -1
  17. data/vendor/faiss/faiss/Index2Layer.h +2 -2
  18. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +1 -0
  19. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +9 -4
  20. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +5 -1
  21. data/vendor/faiss/faiss/IndexBinary.h +7 -7
  22. data/vendor/faiss/faiss/IndexBinaryFromFloat.h +1 -1
  23. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +8 -2
  24. data/vendor/faiss/faiss/IndexBinaryHNSW.h +1 -1
  25. data/vendor/faiss/faiss/IndexBinaryHash.cpp +3 -3
  26. data/vendor/faiss/faiss/IndexBinaryHash.h +5 -5
  27. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +7 -6
  28. data/vendor/faiss/faiss/IndexFastScan.cpp +125 -49
  29. data/vendor/faiss/faiss/IndexFastScan.h +102 -7
  30. data/vendor/faiss/faiss/IndexFlat.cpp +374 -4
  31. data/vendor/faiss/faiss/IndexFlat.h +81 -1
  32. data/vendor/faiss/faiss/IndexHNSW.cpp +93 -2
  33. data/vendor/faiss/faiss/IndexHNSW.h +58 -2
  34. data/vendor/faiss/faiss/IndexIDMap.cpp +14 -13
  35. data/vendor/faiss/faiss/IndexIDMap.h +6 -6
  36. data/vendor/faiss/faiss/IndexIVF.cpp +1 -1
  37. data/vendor/faiss/faiss/IndexIVF.h +5 -5
  38. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +1 -1
  39. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +9 -3
  40. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +3 -1
  41. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +176 -90
  42. data/vendor/faiss/faiss/IndexIVFFastScan.h +173 -18
  43. data/vendor/faiss/faiss/IndexIVFFlat.cpp +1 -0
  44. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +251 -0
  45. data/vendor/faiss/faiss/IndexIVFFlatPanorama.h +64 -0
  46. data/vendor/faiss/faiss/IndexIVFPQ.cpp +3 -1
  47. data/vendor/faiss/faiss/IndexIVFPQ.h +1 -1
  48. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +134 -2
  49. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +7 -1
  50. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +99 -8
  51. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +4 -1
  52. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +828 -0
  53. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +252 -0
  54. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +1 -1
  55. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +1 -1
  56. data/vendor/faiss/faiss/IndexNNDescent.cpp +1 -1
  57. data/vendor/faiss/faiss/IndexNSG.cpp +1 -1
  58. data/vendor/faiss/faiss/IndexNeuralNetCodec.h +1 -1
  59. data/vendor/faiss/faiss/IndexPQ.cpp +4 -1
  60. data/vendor/faiss/faiss/IndexPQ.h +1 -1
  61. data/vendor/faiss/faiss/IndexPQFastScan.cpp +6 -2
  62. data/vendor/faiss/faiss/IndexPQFastScan.h +5 -1
  63. data/vendor/faiss/faiss/IndexPreTransform.cpp +14 -0
  64. data/vendor/faiss/faiss/IndexPreTransform.h +9 -0
  65. data/vendor/faiss/faiss/IndexRaBitQ.cpp +96 -13
  66. data/vendor/faiss/faiss/IndexRaBitQ.h +11 -2
  67. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +731 -0
  68. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +175 -0
  69. data/vendor/faiss/faiss/IndexRefine.cpp +49 -0
  70. data/vendor/faiss/faiss/IndexRefine.h +17 -0
  71. data/vendor/faiss/faiss/IndexShards.cpp +1 -1
  72. data/vendor/faiss/faiss/MatrixStats.cpp +3 -3
  73. data/vendor/faiss/faiss/MetricType.h +1 -1
  74. data/vendor/faiss/faiss/VectorTransform.h +2 -2
  75. data/vendor/faiss/faiss/clone_index.cpp +5 -1
  76. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +1 -1
  77. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +3 -1
  78. data/vendor/faiss/faiss/gpu/GpuIndex.h +11 -11
  79. data/vendor/faiss/faiss/gpu/GpuIndexBinaryCagra.h +1 -1
  80. data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +1 -1
  81. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +11 -7
  82. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +1 -1
  83. data/vendor/faiss/faiss/gpu/perf/IndexWrapper-inl.h +2 -0
  84. data/vendor/faiss/faiss/gpu/test/TestGpuIcmEncoder.cpp +7 -0
  85. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +1 -1
  86. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +1 -1
  87. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +1 -1
  88. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +2 -2
  89. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +1 -1
  90. data/vendor/faiss/faiss/impl/CodePacker.h +2 -2
  91. data/vendor/faiss/faiss/impl/DistanceComputer.h +77 -6
  92. data/vendor/faiss/faiss/impl/FastScanDistancePostProcessing.h +53 -0
  93. data/vendor/faiss/faiss/impl/HNSW.cpp +295 -16
  94. data/vendor/faiss/faiss/impl/HNSW.h +35 -6
  95. data/vendor/faiss/faiss/impl/IDSelector.cpp +2 -2
  96. data/vendor/faiss/faiss/impl/IDSelector.h +4 -4
  97. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +4 -4
  98. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +1 -1
  99. data/vendor/faiss/faiss/impl/LookupTableScaler.h +1 -1
  100. data/vendor/faiss/faiss/impl/NNDescent.cpp +1 -1
  101. data/vendor/faiss/faiss/impl/NNDescent.h +2 -2
  102. data/vendor/faiss/faiss/impl/NSG.cpp +1 -1
  103. data/vendor/faiss/faiss/impl/Panorama.cpp +193 -0
  104. data/vendor/faiss/faiss/impl/Panorama.h +204 -0
  105. data/vendor/faiss/faiss/impl/PanoramaStats.cpp +33 -0
  106. data/vendor/faiss/faiss/impl/PanoramaStats.h +38 -0
  107. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +5 -5
  108. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +1 -1
  109. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.h +1 -1
  110. data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +2 -0
  111. data/vendor/faiss/faiss/impl/ProductQuantizer.h +1 -1
  112. data/vendor/faiss/faiss/impl/RaBitQStats.cpp +29 -0
  113. data/vendor/faiss/faiss/impl/RaBitQStats.h +56 -0
  114. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +294 -0
  115. data/vendor/faiss/faiss/impl/RaBitQUtils.h +330 -0
  116. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +304 -223
  117. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +72 -4
  118. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +362 -0
  119. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.h +112 -0
  120. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +1 -1
  121. data/vendor/faiss/faiss/impl/ResultHandler.h +4 -4
  122. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +7 -10
  123. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +2 -4
  124. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +7 -4
  125. data/vendor/faiss/faiss/impl/index_read.cpp +238 -10
  126. data/vendor/faiss/faiss/impl/index_write.cpp +212 -19
  127. data/vendor/faiss/faiss/impl/io.cpp +2 -2
  128. data/vendor/faiss/faiss/impl/io.h +4 -4
  129. data/vendor/faiss/faiss/impl/kmeans1d.cpp +1 -1
  130. data/vendor/faiss/faiss/impl/kmeans1d.h +1 -1
  131. data/vendor/faiss/faiss/impl/lattice_Zn.h +2 -2
  132. data/vendor/faiss/faiss/impl/mapped_io.cpp +2 -2
  133. data/vendor/faiss/faiss/impl/mapped_io.h +4 -3
  134. data/vendor/faiss/faiss/impl/maybe_owned_vector.h +8 -1
  135. data/vendor/faiss/faiss/impl/platform_macros.h +12 -0
  136. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +30 -4
  137. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +14 -8
  138. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +5 -6
  139. data/vendor/faiss/faiss/impl/simd_result_handlers.h +55 -11
  140. data/vendor/faiss/faiss/impl/svs_io.cpp +86 -0
  141. data/vendor/faiss/faiss/impl/svs_io.h +67 -0
  142. data/vendor/faiss/faiss/impl/zerocopy_io.h +1 -1
  143. data/vendor/faiss/faiss/index_factory.cpp +217 -8
  144. data/vendor/faiss/faiss/index_factory.h +1 -1
  145. data/vendor/faiss/faiss/index_io.h +1 -1
  146. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +1 -1
  147. data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
  148. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +115 -1
  149. data/vendor/faiss/faiss/invlists/InvertedLists.h +46 -0
  150. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +1 -1
  151. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
  152. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +261 -0
  153. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +117 -0
  154. data/vendor/faiss/faiss/svs/IndexSVSFlat.h +66 -0
  155. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +245 -0
  156. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +137 -0
  157. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +39 -0
  158. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +42 -0
  159. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +149 -0
  160. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +58 -0
  161. data/vendor/faiss/faiss/utils/AlignedTable.h +1 -1
  162. data/vendor/faiss/faiss/utils/Heap.cpp +2 -2
  163. data/vendor/faiss/faiss/utils/Heap.h +3 -3
  164. data/vendor/faiss/faiss/utils/NeuralNet.cpp +1 -1
  165. data/vendor/faiss/faiss/utils/NeuralNet.h +3 -3
  166. data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +2 -2
  167. data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +2 -2
  168. data/vendor/faiss/faiss/utils/approx_topk/mode.h +1 -1
  169. data/vendor/faiss/faiss/utils/distances.cpp +0 -3
  170. data/vendor/faiss/faiss/utils/distances.h +2 -2
  171. data/vendor/faiss/faiss/utils/extra_distances-inl.h +3 -1
  172. data/vendor/faiss/faiss/utils/hamming-inl.h +2 -0
  173. data/vendor/faiss/faiss/utils/hamming.cpp +7 -6
  174. data/vendor/faiss/faiss/utils/hamming.h +1 -1
  175. data/vendor/faiss/faiss/utils/hamming_distance/common.h +1 -2
  176. data/vendor/faiss/faiss/utils/partitioning.cpp +5 -5
  177. data/vendor/faiss/faiss/utils/partitioning.h +2 -2
  178. data/vendor/faiss/faiss/utils/rabitq_simd.h +222 -336
  179. data/vendor/faiss/faiss/utils/random.cpp +1 -1
  180. data/vendor/faiss/faiss/utils/simdlib_avx2.h +1 -1
  181. data/vendor/faiss/faiss/utils/simdlib_avx512.h +1 -1
  182. data/vendor/faiss/faiss/utils/simdlib_neon.h +2 -2
  183. data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +1 -1
  184. data/vendor/faiss/faiss/utils/utils.cpp +9 -2
  185. data/vendor/faiss/faiss/utils/utils.h +2 -2
  186. metadata +29 -1
@@ -53,7 +53,7 @@ void DirectMap::set_type(
53
53
  for (long ofs = 0; ofs < list_size; ofs++) {
54
54
  FAISS_THROW_IF_NOT_MSG(
55
55
  0 <= idlist[ofs] && idlist[ofs] < ntotal,
56
- "direct map supported only for seuquential ids");
56
+ "direct map supported only for sequential ids");
57
57
  array[idlist[ofs]] = lo_build(key, ofs);
58
58
  }
59
59
  } else if (new_type == Hashtable) {
@@ -229,7 +229,7 @@ bool InvertedLists::is_empty(size_t list_no, void* inverted_list_context)
229
229
  }
230
230
  }
231
231
 
232
- // implemnent iterator on top of get_codes / get_ids
232
+ // implement iterator on top of get_codes / get_ids
233
233
  namespace {
234
234
 
235
235
  struct CodeArrayIterator : InvertedListsIterator {
@@ -346,6 +346,120 @@ void ArrayInvertedLists::permute_invlists(const idx_t* map) {
346
346
 
347
347
  ArrayInvertedLists::~ArrayInvertedLists() {}
348
348
 
349
+ /***********************************************
350
+ * ArrayInvertedListsPanorama implementation
351
+ **********************************************/
352
+
353
+ ArrayInvertedListsPanorama::ArrayInvertedListsPanorama(
354
+ size_t nlist,
355
+ size_t code_size,
356
+ size_t n_levels)
357
+ : ArrayInvertedLists(nlist, code_size),
358
+ n_levels(n_levels),
359
+ level_width(
360
+ (((code_size / sizeof(float)) + n_levels - 1) / n_levels) *
361
+ sizeof(float)),
362
+ pano(code_size, n_levels, kBatchSize) {
363
+ FAISS_THROW_IF_NOT(n_levels > 0);
364
+ FAISS_THROW_IF_NOT(code_size % sizeof(float) == 0);
365
+ FAISS_THROW_IF_NOT_MSG(
366
+ !use_iterator,
367
+ "IndexIVFFlatPanorama does not support iterators, use vanilla IndexIVFFlat instead");
368
+ FAISS_ASSERT(level_width % sizeof(float) == 0);
369
+
370
+ cum_sums.resize(nlist);
371
+ }
372
+
373
+ const float* ArrayInvertedListsPanorama::get_cum_sums(size_t list_no) const {
374
+ assert(list_no < nlist);
375
+ return cum_sums[list_no].data();
376
+ }
377
+
378
+ size_t ArrayInvertedListsPanorama::add_entries(
379
+ size_t list_no,
380
+ size_t n_entry,
381
+ const idx_t* ids_in,
382
+ const uint8_t* code) {
383
+ assert(list_no < nlist);
384
+ size_t o = ids[list_no].size();
385
+
386
+ ids[list_no].resize(o + n_entry);
387
+ memcpy(&ids[list_no][o], ids_in, sizeof(ids_in[0]) * n_entry);
388
+
389
+ size_t new_size = o + n_entry;
390
+ size_t num_batches = (new_size + kBatchSize - 1) / kBatchSize;
391
+ codes[list_no].resize(num_batches * kBatchSize * code_size);
392
+ cum_sums[list_no].resize(num_batches * kBatchSize * (n_levels + 1));
393
+
394
+ // Cast to float* is safe here as we guarantee codes are always float
395
+ // vectors for `IndexIVFFlatPanorama` (verified by the constructor).
396
+ const float* vectors = reinterpret_cast<const float*>(code);
397
+ pano.copy_codes_to_level_layout(codes[list_no].data(), o, n_entry, code);
398
+ pano.compute_cumulative_sums(cum_sums[list_no].data(), o, n_entry, vectors);
399
+
400
+ return o;
401
+ }
402
+
403
+ void ArrayInvertedListsPanorama::update_entries(
404
+ size_t list_no,
405
+ size_t offset,
406
+ size_t n_entry,
407
+ const idx_t* ids_in,
408
+ const uint8_t* code) {
409
+ assert(list_no < nlist);
410
+ assert(n_entry + offset <= ids[list_no].size());
411
+
412
+ memcpy(&ids[list_no][offset], ids_in, sizeof(ids_in[0]) * n_entry);
413
+
414
+ // Cast to float* is safe here as we guarantee codes are always float
415
+ // vectors for `IndexIVFFlatPanorama` (verified by the constructor).
416
+ const float* vectors = reinterpret_cast<const float*>(code);
417
+ pano.copy_codes_to_level_layout(
418
+ codes[list_no].data(), offset, n_entry, code);
419
+ pano.compute_cumulative_sums(
420
+ cum_sums[list_no].data(), offset, n_entry, vectors);
421
+ }
422
+
423
+ void ArrayInvertedListsPanorama::resize(size_t list_no, size_t new_size) {
424
+ ids[list_no].resize(new_size);
425
+
426
+ size_t num_batches = (new_size + kBatchSize - 1) / kBatchSize;
427
+ codes[list_no].resize(num_batches * kBatchSize * code_size);
428
+ cum_sums[list_no].resize(num_batches * kBatchSize * (n_levels + 1));
429
+ }
430
+
431
+ const uint8_t* ArrayInvertedListsPanorama::get_single_code(
432
+ size_t list_no,
433
+ size_t offset) const {
434
+ assert(list_no < nlist);
435
+ assert(offset < ids[list_no].size());
436
+
437
+ uint8_t* recons_buffer = new uint8_t[code_size];
438
+
439
+ float* recons = reinterpret_cast<float*>(recons_buffer);
440
+ pano.reconstruct(offset, recons, codes[list_no].data());
441
+
442
+ return recons_buffer;
443
+ }
444
+
445
+ void ArrayInvertedListsPanorama::release_codes(
446
+ size_t list_no,
447
+ const uint8_t* codes) const {
448
+ // Only delete if it's heap-allocated (from get_single_code).
449
+ // If it's from get_codes (raw storage), it will be codes[list_no].data()
450
+ if (codes != this->codes[list_no].data()) {
451
+ delete[] codes;
452
+ }
453
+ }
454
+
455
+ InvertedListsIterator* ArrayInvertedListsPanorama::get_iterator(
456
+ size_t /* list_no */,
457
+ void* /* inverted_list_context */) const {
458
+ FAISS_THROW_MSG(
459
+ "IndexIVFFlatPanorama does not support iterators, use vanilla IndexIVFFlat instead");
460
+ return nullptr;
461
+ }
462
+
349
463
  /*****************************************************************
350
464
  * Meta-inverted list implementations
351
465
  *****************************************************************/
@@ -18,6 +18,7 @@
18
18
  #include <vector>
19
19
 
20
20
  #include <faiss/MetricType.h>
21
+ #include <faiss/impl/Panorama.h>
21
22
  #include <faiss/impl/maybe_owned_vector.h>
22
23
 
23
24
  namespace faiss {
@@ -276,6 +277,51 @@ struct ArrayInvertedLists : InvertedLists {
276
277
  ~ArrayInvertedLists() override;
277
278
  };
278
279
 
280
+ /// Level-oriented storage as defined in the IVFFlat section of Panorama
281
+ /// (https://www.arxiv.org/pdf/2510.00566).
282
+ struct ArrayInvertedListsPanorama : ArrayInvertedLists {
283
+ static constexpr size_t kBatchSize = 128;
284
+ std::vector<MaybeOwnedVector<float>> cum_sums;
285
+ const size_t n_levels;
286
+ const size_t level_width; // in code units
287
+ Panorama pano;
288
+
289
+ ArrayInvertedListsPanorama(size_t nlist, size_t code_size, size_t n_levels);
290
+
291
+ const float* get_cum_sums(size_t list_no) const;
292
+
293
+ size_t add_entries(
294
+ size_t list_no,
295
+ size_t n_entry,
296
+ const idx_t* ids,
297
+ const uint8_t* code) override;
298
+
299
+ void update_entries(
300
+ size_t list_no,
301
+ size_t offset,
302
+ size_t n_entry,
303
+ const idx_t* ids,
304
+ const uint8_t* code) override;
305
+
306
+ void resize(size_t list_no, size_t new_size) override;
307
+
308
+ /// Panorama's layout make it impractical to support iterators as defined
309
+ /// by Faiss (i.e. `InvertedListsIterator` API). The iterator would require
310
+ /// to allocate and reassemble the vector at each call.
311
+ /// Hence, we override this method to throw an error, this effectively
312
+ /// disables the `iterate_codes` and `iterate_codes_range` methods.
313
+ InvertedListsIterator* get_iterator(
314
+ size_t list_no,
315
+ void* inverted_list_context = nullptr) const override;
316
+
317
+ /// Reconstructs a single code from level-oriented storage to flat format.
318
+ const uint8_t* get_single_code(size_t list_no, size_t offset)
319
+ const override;
320
+
321
+ /// Frees codes returned by `get_single_code`.
322
+ void release_codes(size_t list_no, const uint8_t* codes) const override;
323
+ };
324
+
279
325
  /*****************************************************************
280
326
  * Meta-inverted lists
281
327
  *
@@ -372,7 +372,7 @@ OnDiskInvertedLists::~OnDiskInvertedLists() {
372
372
  if (ptr != nullptr) {
373
373
  int err = munmap(ptr, totsize);
374
374
  if (err != 0) {
375
- fprintf(stderr, "mumap error: %s", strerror(errno));
375
+ fprintf(stderr, "munmap error: %s", strerror(errno));
376
376
  }
377
377
  }
378
378
  delete locks;
@@ -121,7 +121,7 @@ struct OnDiskInvertedLists : InvertedLists {
121
121
 
122
122
  LockLevels* locks;
123
123
 
124
- // encapsulates the threads that are busy prefeteching
124
+ // encapsulates the threads that are busy prefetching
125
125
  struct OngoingPrefetch;
126
126
  OngoingPrefetch* pf;
127
127
  int prefetch_nthread;
@@ -0,0 +1,261 @@
1
+ /*
2
+ * Portions Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ /*
9
+ * Portions Copyright 2025 Intel Corporation
10
+ *
11
+ * Licensed under the Apache License, Version 2.0 (the "License");
12
+ * you may not use this file except in compliance with the License.
13
+ * You may obtain a copy of the License at
14
+ *
15
+ * http://www.apache.org/licenses/LICENSE-2.0
16
+ *
17
+ * Unless required by applicable law or agreed to in writing, software
18
+ * distributed under the License is distributed on an "AS IS" BASIS,
19
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
+ * See the License for the specific language governing permissions and
21
+ * limitations under the License.
22
+ */
23
+
24
+ #pragma once
25
+
26
+ #include <svs/runtime/api_defs.h>
27
+
28
+ #include <faiss/Index.h>
29
+ #include <faiss/MetricType.h>
30
+ #include <faiss/impl/AuxIndexStructures.h>
31
+ #include <faiss/impl/FaissAssert.h>
32
+ #include <faiss/impl/IDSelector.h>
33
+
34
+ #include <algorithm>
35
+ #include <concepts>
36
+ #include <memory>
37
+ #include <span>
38
+ #include <type_traits>
39
+ #include <vector>
40
+
41
+ // validate FAISS_SVS_RUNTIME_VERSION is set
42
+ #ifndef FAISS_SVS_RUNTIME_VERSION
43
+ #error "FAISS_SVS_RUNTIME_VERSION is not defined"
44
+ #endif
45
+ // create svs_runtime as alias for svs::runtime::FAISS_SVS_RUNTIME_VERSION
46
+ SVS_RUNTIME_CREATE_API_ALIAS(svs_runtime, FAISS_SVS_RUNTIME_VERSION);
47
+
48
+ // SVS forward declarations
49
+ namespace svs {
50
+ namespace runtime {
51
+ inline namespace v0 {
52
+ struct FlatIndex;
53
+ struct VamanaIndex;
54
+ struct DynamicVamanaIndex;
55
+ struct LeanVecTrainingData;
56
+ } // namespace v0
57
+ } // namespace runtime
58
+ } // namespace svs
59
+
60
+ namespace faiss {
61
+
62
+ inline svs_runtime::MetricType to_svs_metric(faiss::MetricType metric) {
63
+ switch (metric) {
64
+ case METRIC_INNER_PRODUCT:
65
+ return svs_runtime::MetricType::INNER_PRODUCT;
66
+ case METRIC_L2:
67
+ return svs_runtime::MetricType::L2;
68
+ default:
69
+ FAISS_ASSERT(!"not supported SVS distance");
70
+ }
71
+ }
72
+
73
+ struct FaissIDFilter : public svs_runtime::IDFilter {
74
+ FaissIDFilter(const faiss::IDSelector& sel) : selector(sel) {}
75
+
76
+ bool is_member(size_t id) const override {
77
+ return selector.is_member(static_cast<faiss::idx_t>(id));
78
+ }
79
+
80
+ private:
81
+ const faiss::IDSelector& selector;
82
+ };
83
+
84
+ inline std::unique_ptr<FaissIDFilter> make_faiss_id_filter(
85
+ const SearchParameters* params = nullptr) {
86
+ if (params && params->sel) {
87
+ return std::make_unique<FaissIDFilter>(*params->sel);
88
+ }
89
+ return nullptr;
90
+ }
91
+
92
+ template <typename T, typename U, typename = void>
93
+ struct InputBufferConverter {
94
+ InputBufferConverter(std::span<const U> data = {}) : buffer(data.size()) {
95
+ FAISS_ASSERT(
96
+ !"InputBufferConverter: there is no suitable user code for this type conversion");
97
+ std::transform(
98
+ data.begin(), data.end(), buffer.begin(), [](const U& val) {
99
+ return static_cast<T>(val);
100
+ });
101
+ }
102
+
103
+ operator T*() {
104
+ return buffer.data();
105
+ }
106
+ operator const T*() const {
107
+ return buffer.data();
108
+ }
109
+
110
+ operator std::span<T>() {
111
+ return buffer;
112
+ }
113
+ operator std::span<const T>() const {
114
+ return buffer;
115
+ }
116
+
117
+ private:
118
+ std::vector<T> buffer;
119
+ };
120
+
121
+ // Specialization for reinterpret cast when types are integral and have the same
122
+ // size
123
+ template <typename T, typename U>
124
+ struct InputBufferConverter<
125
+ T,
126
+ U,
127
+ std::enable_if_t<
128
+ std::is_same_v<T, U> ||
129
+ (std::is_integral_v<T> && std::is_integral_v<U> &&
130
+ sizeof(T) == sizeof(U))>> {
131
+ InputBufferConverter(std::span<const U> data = {}) : data_span(data) {}
132
+ operator T*() {
133
+ return reinterpret_cast<T*>(data_span.data());
134
+ }
135
+ operator const T*() const {
136
+ return reinterpret_cast<const T*>(data_span.data());
137
+ }
138
+ operator std::span<T>() {
139
+ return std::span<T>(
140
+ reinterpret_cast<T*>(data_span.data()), data_span.size());
141
+ }
142
+ operator std::span<const T>() const {
143
+ return std::span<const T>(
144
+ reinterpret_cast<const T*>(data_span.data()), data_span.size());
145
+ }
146
+
147
+ private:
148
+ std::span<const U> data_span;
149
+ };
150
+
151
+ template <typename T, typename U, typename = void>
152
+ struct OutputBufferConverter {
153
+ OutputBufferConverter(std::span<U> data = {})
154
+ : data_span(data), buffer(data.size()) {
155
+ FAISS_ASSERT(
156
+ !"OutputBufferConverter: there is no suitable user code for this type conversion");
157
+ }
158
+
159
+ ~OutputBufferConverter() {
160
+ std::transform(
161
+ buffer.begin(),
162
+ buffer.end(),
163
+ data_span.begin(),
164
+ [](const T& val) { return static_cast<U>(val); });
165
+ }
166
+
167
+ operator T*() {
168
+ return buffer.data();
169
+ }
170
+ operator std::span<T>() {
171
+ return buffer;
172
+ }
173
+
174
+ private:
175
+ std::span<U> data_span;
176
+ std::vector<T> buffer;
177
+ };
178
+
179
+ // Specialization for reinterpret cast when types are integral and have the same
180
+ // size
181
+ template <typename T, typename U>
182
+ struct OutputBufferConverter<
183
+ T,
184
+ U,
185
+ std::enable_if_t<
186
+ std::is_same_v<T, U> ||
187
+ (std::is_integral_v<T> && std::is_integral_v<U> &&
188
+ sizeof(T) == sizeof(U))>> {
189
+ OutputBufferConverter(std::span<U> data = {}) : data_span(data) {}
190
+ operator T*() {
191
+ return reinterpret_cast<T*>(data_span.data());
192
+ }
193
+ operator std::span<T>() {
194
+ return std::span<T>(
195
+ reinterpret_cast<T*>(data_span.data()), data_span.size());
196
+ }
197
+
198
+ private:
199
+ std::span<U> data_span;
200
+ };
201
+
202
+ template <typename T, typename U>
203
+ auto convert_input_buffer(std::span<const U> data) {
204
+ // Create temporary buffer and convert input data
205
+ // to target type T in the temporary buffer
206
+ // The temporary buffer will be destroyed
207
+ // when going out of scope
208
+ return InputBufferConverter<T, U>(data);
209
+ }
210
+
211
+ template <typename T, typename U>
212
+ auto convert_input_buffer(const U* data, size_t size) {
213
+ return convert_input_buffer<T, U>(std::span<const U>(data, size));
214
+ }
215
+
216
+ // Output buffer conversion
217
+ template <typename T, typename U>
218
+ auto convert_output_buffer(std::span<U> data) {
219
+ // Create temporary buffer for output data
220
+ // The temporary buffer will be destroyed
221
+ // when going out of scope, copying back
222
+ // the converted data to original buffer
223
+ return OutputBufferConverter<T, U>(data);
224
+ }
225
+
226
+ template <typename T, typename U>
227
+ auto convert_output_buffer(U* data, size_t size) {
228
+ return convert_output_buffer<T, U>(std::span<U>(data, size));
229
+ }
230
+
231
+ struct FaissResultsAllocator : public svs_runtime::ResultsAllocator {
232
+ FaissResultsAllocator(faiss::RangeSearchResult* result) : result(result) {
233
+ FAISS_ASSERT(result != nullptr);
234
+ }
235
+
236
+ svs_runtime::SearchResultsStorage allocate(
237
+ std::span<size_t> result_counts) const override {
238
+ FAISS_ASSERT(result != nullptr);
239
+ FAISS_ASSERT(result_counts.size() == result->nq);
240
+
241
+ // RangeSearchResult .ctor() allows unallocated lims
242
+ if (result->lims == nullptr) {
243
+ result->lims = new size_t[result->nq + 1];
244
+ }
245
+
246
+ std::copy(result_counts.begin(), result_counts.end(), result->lims);
247
+ result->do_allocation();
248
+ this->labels_converter = LabelsConverter{
249
+ std::span(result->labels, result->lims[result_counts.size()])};
250
+ return svs_runtime::SearchResultsStorage{
251
+ labels_converter,
252
+ std::span<float>(
253
+ result->distances, result->lims[result_counts.size()])};
254
+ }
255
+
256
+ private:
257
+ faiss::RangeSearchResult* result;
258
+ using LabelsConverter = OutputBufferConverter<size_t, faiss::idx_t>;
259
+ mutable LabelsConverter labels_converter;
260
+ };
261
+ } // namespace faiss
@@ -0,0 +1,117 @@
1
+ /*
2
+ * Portions Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ /*
9
+ * Portions Copyright 2025 Intel Corporation
10
+ *
11
+ * Licensed under the Apache License, Version 2.0 (the "License");
12
+ * you may not use this file except in compliance with the License.
13
+ * You may obtain a copy of the License at
14
+ *
15
+ * http://www.apache.org/licenses/LICENSE-2.0
16
+ *
17
+ * Unless required by applicable law or agreed to in writing, software
18
+ * distributed under the License is distributed on an "AS IS" BASIS,
19
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
+ * See the License for the specific language governing permissions and
21
+ * limitations under the License.
22
+ */
23
+
24
+ #include <faiss/Index.h>
25
+ #include <faiss/svs/IndexSVSFaissUtils.h>
26
+ #include <faiss/svs/IndexSVSFlat.h>
27
+
28
+ #include <svs/runtime/flat_index.h>
29
+
30
+ #include <iostream>
31
+
32
+ namespace faiss {
33
+
34
+ IndexSVSFlat::IndexSVSFlat(idx_t d, MetricType metric) : Index(d, metric) {}
35
+
36
+ IndexSVSFlat::~IndexSVSFlat() {
37
+ if (impl) {
38
+ auto status = svs_runtime::FlatIndex::destroy(impl);
39
+ FAISS_ASSERT(status.ok());
40
+ impl = nullptr;
41
+ }
42
+ }
43
+
44
+ void IndexSVSFlat::add(idx_t n, const float* x) {
45
+ if (!impl) {
46
+ create_impl();
47
+ }
48
+
49
+ auto status = impl->add(n, x);
50
+ if (!status.ok()) {
51
+ FAISS_THROW_MSG(status.message());
52
+ }
53
+ ntotal += n;
54
+ }
55
+
56
+ void IndexSVSFlat::reset() {
57
+ if (impl) {
58
+ auto status = impl->reset();
59
+ if (!status.ok()) {
60
+ FAISS_THROW_MSG(status.message());
61
+ }
62
+ }
63
+ ntotal = 0;
64
+ }
65
+
66
+ void IndexSVSFlat::search(
67
+ idx_t n,
68
+ const float* x,
69
+ idx_t k,
70
+ float* distances,
71
+ idx_t* labels,
72
+ const SearchParameters* params) const {
73
+ FAISS_THROW_IF_NOT(impl);
74
+ auto status = impl->search(
75
+ n,
76
+ x,
77
+ static_cast<size_t>(k),
78
+ distances,
79
+ reinterpret_cast<size_t*>(labels));
80
+ if (!status.ok()) {
81
+ FAISS_THROW_MSG(status.message());
82
+ }
83
+ }
84
+
85
+ /* Initializes the implementation*/
86
+ void IndexSVSFlat::create_impl() {
87
+ FAISS_ASSERT(impl == nullptr);
88
+ auto svs_metric = to_svs_metric(metric_type);
89
+ auto status = svs_runtime::FlatIndex::build(&impl, d, svs_metric);
90
+ if (!status.ok()) {
91
+ FAISS_THROW_MSG(status.message());
92
+ }
93
+ FAISS_THROW_IF_NOT(impl);
94
+ }
95
+
96
+ /* Serialization */
97
+ void IndexSVSFlat::serialize_impl(std::ostream& out) const {
98
+ FAISS_THROW_IF_NOT_MSG(
99
+ impl, "Cannot serialize: SVS index not initialized.");
100
+
101
+ auto status = impl->save(out);
102
+ if (!status.ok()) {
103
+ FAISS_THROW_MSG(status.message());
104
+ }
105
+ }
106
+
107
+ void IndexSVSFlat::deserialize_impl(std::istream& in) {
108
+ FAISS_THROW_IF_MSG(impl, "Cannot deserialize: SVS index already loaded.");
109
+ auto metric = to_svs_metric(metric_type);
110
+ auto status = impl->load(&impl, in, metric);
111
+ if (!status.ok()) {
112
+ FAISS_THROW_MSG(status.message());
113
+ }
114
+ FAISS_THROW_IF_NOT(impl);
115
+ }
116
+
117
+ } // namespace faiss
@@ -0,0 +1,66 @@
1
+ /*
2
+ * Portions Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ /*
9
+ * Portions Copyright 2025 Intel Corporation
10
+ *
11
+ * Licensed under the Apache License, Version 2.0 (the "License");
12
+ * you may not use this file except in compliance with the License.
13
+ * You may obtain a copy of the License at
14
+ *
15
+ * http://www.apache.org/licenses/LICENSE-2.0
16
+ *
17
+ * Unless required by applicable law or agreed to in writing, software
18
+ * distributed under the License is distributed on an "AS IS" BASIS,
19
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
+ * See the License for the specific language governing permissions and
21
+ * limitations under the License.
22
+ */
23
+
24
+ #pragma once
25
+
26
+ #include <faiss/Index.h>
27
+ #include <faiss/svs/IndexSVSFaissUtils.h>
28
+
29
+ #include <iostream>
30
+
31
+ namespace faiss {
32
+
33
+ struct IndexSVSFlat : Index {
34
+ // sequential labels
35
+ size_t nlabels{0};
36
+
37
+ IndexSVSFlat() = default;
38
+ IndexSVSFlat(idx_t d, MetricType metric = METRIC_L2);
39
+
40
+ ~IndexSVSFlat() override;
41
+
42
+ void add(idx_t n, const float* x) override;
43
+
44
+ void search(
45
+ idx_t n,
46
+ const float* x,
47
+ idx_t k,
48
+ float* distances,
49
+ idx_t* labels,
50
+ const SearchParameters* params = nullptr) const override;
51
+
52
+ void reset() override;
53
+
54
+ /* The actual SVS implementation */
55
+ svs_runtime::FlatIndex* impl{nullptr};
56
+
57
+ /* Serialization */
58
+ void serialize_impl(std::ostream& out) const;
59
+ void deserialize_impl(std::istream& in);
60
+
61
+ protected:
62
+ /* Initializes the implementation*/
63
+ virtual void create_impl();
64
+ };
65
+
66
+ } // namespace faiss