faiss 0.6.2 → 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 (144) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -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 +4 -5
  12. data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
  13. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +2 -4
  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 +10 -11
  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 +17 -6
  22. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +1 -1
  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 +3 -4
  28. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +1 -1
  29. data/vendor/faiss/faiss/IndexIVFPQ.cpp +40 -22
  30. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +0 -1
  31. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +19 -49
  32. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +180 -76
  33. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -4
  34. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +8 -6
  35. data/vendor/faiss/faiss/IndexLSH.cpp +2 -3
  36. data/vendor/faiss/faiss/IndexLattice.cpp +5 -0
  37. data/vendor/faiss/faiss/IndexNNDescent.cpp +9 -2
  38. data/vendor/faiss/faiss/IndexNSG.cpp +7 -2
  39. data/vendor/faiss/faiss/IndexPQ.cpp +6 -8
  40. data/vendor/faiss/faiss/IndexPreTransform.cpp +15 -0
  41. data/vendor/faiss/faiss/IndexRaBitQ.cpp +2 -2
  42. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +1 -2
  43. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +5 -1
  44. data/vendor/faiss/faiss/IndexRefine.cpp +30 -1
  45. data/vendor/faiss/faiss/IndexReplicas.cpp +1 -2
  46. data/vendor/faiss/faiss/IndexShards.cpp +2 -2
  47. data/vendor/faiss/faiss/IndexShardsIVF.cpp +2 -2
  48. data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
  49. data/vendor/faiss/faiss/SuperKMeans.cpp +256 -240
  50. data/vendor/faiss/faiss/SuperKMeans.h +30 -0
  51. data/vendor/faiss/faiss/VectorTransform.cpp +33 -2
  52. data/vendor/faiss/faiss/clone_index.cpp +5 -0
  53. data/vendor/faiss/faiss/factory_tools.cpp +47 -4
  54. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
  55. data/vendor/faiss/faiss/gpu/GpuIndex.h +34 -11
  56. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +47 -0
  57. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +17 -0
  58. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +16 -0
  59. data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +1 -1
  60. data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +2 -2
  61. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +180 -0
  62. data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +1 -5
  63. data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +88 -0
  64. data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFPQ.h +134 -0
  65. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +2 -2
  66. data/vendor/faiss/faiss/impl/DistanceComputer.h +34 -0
  67. data/vendor/faiss/faiss/impl/EDENQuantizer.h +119 -0
  68. data/vendor/faiss/faiss/impl/HNSW.cpp +109 -152
  69. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
  70. data/vendor/faiss/faiss/impl/NSG.cpp +3 -1
  71. data/vendor/faiss/faiss/impl/Panorama.h +9 -7
  72. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
  73. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +34 -22
  74. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +44 -36
  75. data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
  76. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +168 -67
  77. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +19 -0
  78. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +2 -11
  79. data/vendor/faiss/faiss/impl/ResultHandler.h +25 -31
  80. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +258 -57
  81. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +20 -0
  82. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
  83. data/vendor/faiss/faiss/impl/VisitedTable.cpp +22 -2
  84. data/vendor/faiss/faiss/impl/VisitedTable.h +20 -0
  85. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +1 -1
  86. data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
  87. data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +35 -2
  88. data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +1 -1
  89. data/vendor/faiss/faiss/impl/index_read.cpp +376 -36
  90. data/vendor/faiss/faiss/impl/index_write.cpp +55 -4
  91. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +8 -9
  92. data/vendor/faiss/faiss/impl/platform_macros.h +3 -1
  93. data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +284 -0
  94. data/vendor/faiss/faiss/impl/polysemous_training/dispatch.h +115 -0
  95. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +0 -1
  96. data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +26 -15
  97. data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +4 -4
  98. data/vendor/faiss/faiss/impl/result_handler/ResultHandler.cpp +195 -0
  99. data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +133 -0
  100. data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +281 -0
  101. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +72 -0
  102. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +228 -0
  103. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp +882 -0
  104. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +9 -8
  105. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +85 -23
  106. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +30 -30
  107. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +4 -5
  108. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +101 -34
  109. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +136 -0
  110. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +16 -16
  111. data/vendor/faiss/faiss/impl/simd_dispatch.h +30 -9
  112. data/vendor/faiss/faiss/index_factory.cpp +32 -6
  113. data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
  114. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +2 -2
  115. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +19 -4
  116. data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -1
  117. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +60 -0
  118. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +26 -1
  119. data/vendor/faiss/faiss/svs/IndexSVSFlat.h +13 -0
  120. data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +1 -1
  121. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +1 -1
  122. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +31 -1
  123. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +15 -2
  124. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +1 -2
  125. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
  126. data/vendor/faiss/faiss/utils/distances.cpp +14 -2
  127. data/vendor/faiss/faiss/utils/distances_simd.cpp +4 -3
  128. data/vendor/faiss/faiss/utils/extra_distances.cpp +4 -14
  129. data/vendor/faiss/faiss/utils/extra_distances.h +1 -2
  130. data/vendor/faiss/faiss/utils/hamming.cpp +1 -1
  131. data/vendor/faiss/faiss/utils/quantize_lut.cpp +29 -8
  132. data/vendor/faiss/faiss/utils/rabitq_simd.h +202 -0
  133. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +0 -1
  134. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +263 -15
  135. data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +160 -18
  136. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
  137. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +273 -0
  138. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_spr.cpp +92 -0
  139. data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +11 -0
  140. data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +143 -6
  141. data/vendor/faiss/faiss/utils/simd_levels.cpp +44 -0
  142. data/vendor/faiss/faiss/utils/simd_levels.h +14 -0
  143. data/vendor/faiss/faiss/utils/utils.cpp +9 -27
  144. metadata +16 -1
@@ -206,6 +206,206 @@ const float kLloydMaxBoundaries8[] = {
206
206
  2.8413202220f, 2.9594262622f, 3.0937618168f, 3.2505157199f,
207
207
  3.4405881450f, 3.6864032383f, 4.0502898282f
208
208
  };
209
+ const float kLloydMaxCentroids5[] = {
210
+ -3.260726295605043f, -2.691115579554310f, -2.317736402126149f,
211
+ -2.028725991363304f, -1.787231211885846f, -1.576226389073775f,
212
+ -1.386338935362625f, -1.211803212032400f, -1.048782381365585f,
213
+ -0.894564395854440f, -0.747135131789057f, -0.604933168939543f,
214
+ -0.466699175119721f, -0.331378051429876f, -0.198051689203879f,
215
+ -0.065889622349093f, 0.065889622349093f, 0.198051689203879f,
216
+ 0.331378051429876f, 0.466699175119721f, 0.604933168939543f,
217
+ 0.747135131789057f, 0.894564395854440f, 1.048782381365585f,
218
+ 1.211803212032400f, 1.386338935362625f, 1.576226389073775f,
219
+ 1.787231211885846f, 2.028725991363304f, 2.317736402126149f,
220
+ 2.691115579554310f, 3.260726295605043f
221
+ };
222
+ const float kLloydMaxBoundaries5[] = {
223
+ -2.975920937579676f, -2.504425990840229f,
224
+ -2.173231196744727f, -1.907978601624575f,
225
+ -1.681728800479811f, -1.481282662218200f,
226
+ -1.299071073697513f, -1.130292796698992f,
227
+ -0.971673388610013f, -0.820849763821748f,
228
+ -0.676034150364300f, -0.535816172029632f,
229
+ -0.399038613274799f, -0.264714870316877f,
230
+ -0.131970655776486f, 0.000000000000000f,
231
+ 0.131970655776486f, 0.264714870316877f,
232
+ 0.399038613274799f, 0.535816172029632f,
233
+ 0.676034150364300f, 0.820849763821748f,
234
+ 0.971673388610013f, 1.130292796698992f,
235
+ 1.299071073697513f, 1.481282662218200f,
236
+ 1.681728800479811f, 1.907978601624575f,
237
+ 2.173231196744727f, 2.504425990840229f,
238
+ 2.975920937579676f
239
+ };
240
+ const float kLloydMaxCentroids6[] = {
241
+ -3.744069023696475f, -3.240416640324168f, -2.917391465309850f,
242
+ -2.672261701410258f, -2.471294740528467f, -2.298972741297400f,
243
+ -2.146803022259123f, -2.009604894545278f, -1.883971899229356f,
244
+ -1.767537148129260f, -1.658584711429843f, -1.555827465952835f,
245
+ -1.458272959944728f, -1.365137897182360f, -1.275791622351997f,
246
+ -1.189717571132746f, -1.106485959691858f, -1.025734313393752f,
247
+ -0.947153093015629f, -0.870474868055092f, -0.795466052902551f,
248
+ -0.721920472069418f, -0.649654245231535f, -0.578501846064579f,
249
+ -0.508312758753803f, -0.438948800917774f, -0.370281933281155f,
250
+ -0.302192289440361f, -0.234566569768735f, -0.167296609901720f,
251
+ -0.100278121713920f, -0.033409455880258f, 0.033409455880258f,
252
+ 0.100278121713920f, 0.167296609901720f, 0.234566569768735f,
253
+ 0.302192289440361f, 0.370281933281155f, 0.438948800917774f,
254
+ 0.508312758753803f, 0.578501846064579f, 0.649654245231535f,
255
+ 0.721920472069418f, 0.795466052902551f, 0.870474868055092f,
256
+ 0.947153093015629f, 1.025734313393752f, 1.106485959691858f,
257
+ 1.189717571132746f, 1.275791622351997f, 1.365137897182360f,
258
+ 1.458272959944728f, 1.555827465952835f, 1.658584711429843f,
259
+ 1.767537148129260f, 1.883971899229356f, 2.009604894545278f,
260
+ 2.146803022259123f, 2.298972741297400f, 2.471294740528467f,
261
+ 2.672261701410258f, 2.917391465309850f, 3.240416640324168f,
262
+ 3.744069023696475f
263
+ };
264
+ const float kLloydMaxBoundaries6[] = {
265
+ -3.492242832010322f, -3.078904052817009f,
266
+ -2.794826583360054f, -2.571778220969362f,
267
+ -2.385133740912933f, -2.222887881778261f,
268
+ -2.078203958402201f, -1.946788396887317f,
269
+ -1.825754523679308f, -1.713060929779552f,
270
+ -1.607206088691339f, -1.507050212948781f,
271
+ -1.411705428563544f, -1.320464759767178f,
272
+ -1.232754596742371f, -1.148101765412302f,
273
+ -1.066110136542805f, -0.986443703204690f,
274
+ -0.908813980535361f, -0.832970460478822f,
275
+ -0.758693262485985f, -0.685787358650477f,
276
+ -0.614078045648057f, -0.543407302409191f,
277
+ -0.473630779835788f, -0.404615367099464f,
278
+ -0.336237111360758f, -0.268379429604548f,
279
+ -0.200931589835227f, -0.133787365807820f,
280
+ -0.066843788797089f, 0.000000000000000f,
281
+ 0.066843788797089f, 0.133787365807820f,
282
+ 0.200931589835227f, 0.268379429604548f,
283
+ 0.336237111360758f, 0.404615367099464f,
284
+ 0.473630779835788f, 0.543407302409191f,
285
+ 0.614078045648057f, 0.685787358650477f,
286
+ 0.758693262485985f, 0.832970460478822f,
287
+ 0.908813980535361f, 0.986443703204690f,
288
+ 1.066110136542805f, 1.148101765412302f,
289
+ 1.232754596742371f, 1.320464759767178f,
290
+ 1.411705428563544f, 1.507050212948781f,
291
+ 1.607206088691339f, 1.713060929779552f,
292
+ 1.825754523679308f, 1.946788396887317f,
293
+ 2.078203958402201f, 2.222887881778261f,
294
+ 2.385133740912933f, 2.571778220969362f,
295
+ 2.794826583360054f, 3.078904052817009f,
296
+ 3.492242832010322f
297
+ };
298
+ const float kLloydMaxCentroids7[] = {
299
+ -4.189521933023523f, -3.734857105369156f, -3.447381010593710f,
300
+ -3.231896182843021f, -3.057216102842374f, -2.909021527386642f,
301
+ -2.779491911054078f, -2.663867022558051f, -2.559023499137449f,
302
+ -2.462795908452321f, -2.373620316421171f, -2.290326870492530f,
303
+ -2.212016460501213f, -2.137983242734970f, -2.067662153838450f,
304
+ -2.000593243383757f, -1.936396720412283f, -1.874755326807296f,
305
+ -1.815400993379865f, -1.758105160675647f, -1.702671162415673f,
306
+ -1.648928306223807f, -1.596727786313424f, -1.545938700893484f,
307
+ -1.496445137501057f, -1.448144252238147f, -1.400944106526214f,
308
+ -1.354762105115604f, -1.309523700469555f, -1.265161378699170f,
309
+ -1.221613876387012f, -1.178825265520504f, -1.136744262343403f,
310
+ -1.095323771921318f, -1.054520418037026f, -1.014294067830043f,
311
+ -0.974607484216044f, -0.935426075762634f, -0.896717615963322f,
312
+ -0.858451939611374f, -0.820600783245502f, -0.783137537563140f,
313
+ -0.746037126679468f, -0.709275946093977f, -0.672831567493634f,
314
+ -0.636682661398141f, -0.600808970989236f, -0.565191195643323f,
315
+ -0.529810843625619f, -0.494650181610316f, -0.459692230045422f,
316
+ -0.424920552397901f, -0.390319263305967f, -0.355873075050329f,
317
+ -0.321567103923158f, -0.287386806226095f, -0.253318071908346f,
318
+ -0.219347083403316f, -0.185460257086808f, -0.151644263013162f,
319
+ -0.117885968250325f, -0.084172419896719f, -0.050490753968962f,
320
+ -0.016828143177728f, 0.016828143177728f, 0.050490753968962f,
321
+ 0.084172419896719f, 0.117885968250325f, 0.151644263013162f,
322
+ 0.185460257086808f, 0.219347083403316f, 0.253318071908346f,
323
+ 0.287386806226095f, 0.321567103923158f, 0.355873075050329f,
324
+ 0.390319263305967f, 0.424920552397901f, 0.459692230045422f,
325
+ 0.494650181610316f, 0.529810843625619f, 0.565191195643323f,
326
+ 0.600808970989236f, 0.636682661398141f, 0.672831567493634f,
327
+ 0.709275946093977f, 0.746037126679468f, 0.783137537563140f,
328
+ 0.820600783245502f, 0.858451939611374f, 0.896717615963322f,
329
+ 0.935426075762634f, 0.974607484216044f, 1.014294067830043f,
330
+ 1.054520418037026f, 1.095323771921318f, 1.136744262343403f,
331
+ 1.178825265520504f, 1.221613876387012f, 1.265161378699170f,
332
+ 1.309523700469555f, 1.354762105115604f, 1.400944106526214f,
333
+ 1.448144252238147f, 1.496445137501057f, 1.545938700893484f,
334
+ 1.596727786313424f, 1.648928306223807f, 1.702671162415673f,
335
+ 1.758105160675647f, 1.815400993379865f, 1.874755326807296f,
336
+ 1.936396720412283f, 2.000593243383757f, 2.067662153838450f,
337
+ 2.137983242734970f, 2.212016460501213f, 2.290326870492530f,
338
+ 2.373620316421171f, 2.462795908452321f, 2.559023499137449f,
339
+ 2.663867022558051f, 2.779491911054078f, 2.909021527386642f,
340
+ 3.057216102842374f, 3.231896182843021f, 3.447381010593710f,
341
+ 3.734857105369156f, 4.189521933023523f
342
+ };
343
+ const float kLloydMaxBoundaries7[] = {
344
+ -3.962189519196340f, -3.591119057981433f,
345
+ -3.339638596718365f, -3.144556142842697f,
346
+ -2.983118815114508f, -2.844256719220360f,
347
+ -2.721679466806065f, -2.611445260847750f,
348
+ -2.510909703794885f, -2.418208112436746f,
349
+ -2.331973593456850f, -2.251171665496871f,
350
+ -2.174999851618091f, -2.102822698286710f,
351
+ -2.034127698611103f, -1.968494981898020f,
352
+ -1.905576023609790f, -1.845078160093581f,
353
+ -1.786753077027756f, -1.730388161545660f,
354
+ -1.675799734319740f, -1.622828046268615f,
355
+ -1.571333243603454f, -1.521191919197270f,
356
+ -1.472294694869602f, -1.424544179382180f,
357
+ -1.377853105820909f, -1.332142902792580f,
358
+ -1.287342539584363f, -1.243387627543091f,
359
+ -1.200219570953758f, -1.157784763931954f,
360
+ -1.116034017132360f, -1.074922094979172f,
361
+ -1.034407242933534f, -0.994450776023043f,
362
+ -0.955016779989339f, -0.916071845862978f,
363
+ -0.877584777787348f, -0.839526361428438f,
364
+ -0.801869160404321f, -0.764587332121304f,
365
+ -0.727656536386722f, -0.691053756793806f,
366
+ -0.654757114445887f, -0.618745816193689f,
367
+ -0.583000083316280f, -0.547501019634471f,
368
+ -0.512230512617967f, -0.477171205827869f,
369
+ -0.442306391221661f, -0.407619907851934f,
370
+ -0.373096169178148f, -0.338720089486743f,
371
+ -0.304476955074627f, -0.270352439067221f,
372
+ -0.236332577655831f, -0.202403670245062f,
373
+ -0.168552260049985f, -0.134765115631744f,
374
+ -0.101029194073522f, -0.067331586932840f,
375
+ -0.033659448573345f, 0.000000000000000f,
376
+ 0.033659448573345f, 0.067331586932840f,
377
+ 0.101029194073522f, 0.134765115631744f,
378
+ 0.168552260049985f, 0.202403670245062f,
379
+ 0.236332577655831f, 0.270352439067221f,
380
+ 0.304476955074627f, 0.338720089486743f,
381
+ 0.373096169178148f, 0.407619907851934f,
382
+ 0.442306391221661f, 0.477171205827869f,
383
+ 0.512230512617967f, 0.547501019634471f,
384
+ 0.583000083316280f, 0.618745816193689f,
385
+ 0.654757114445887f, 0.691053756793806f,
386
+ 0.727656536386722f, 0.764587332121304f,
387
+ 0.801869160404321f, 0.839526361428438f,
388
+ 0.877584777787348f, 0.916071845862978f,
389
+ 0.955016779989339f, 0.994450776023043f,
390
+ 1.034407242933534f, 1.074922094979172f,
391
+ 1.116034017132360f, 1.157784763931954f,
392
+ 1.200219570953758f, 1.243387627543091f,
393
+ 1.287342539584363f, 1.332142902792580f,
394
+ 1.377853105820909f, 1.424544179382180f,
395
+ 1.472294694869602f, 1.521191919197270f,
396
+ 1.571333243603454f, 1.622828046268615f,
397
+ 1.675799734319740f, 1.730388161545660f,
398
+ 1.786753077027756f, 1.845078160093581f,
399
+ 1.905576023609790f, 1.968494981898020f,
400
+ 2.034127698611103f, 2.102822698286710f,
401
+ 2.174999851618091f, 2.251171665496871f,
402
+ 2.331973593456850f, 2.418208112436746f,
403
+ 2.510909703794885f, 2.611445260847750f,
404
+ 2.721679466806065f, 2.844256719220360f,
405
+ 2.983118815114508f, 3.144556142842697f,
406
+ 3.339638596718365f, 3.591119057981433f,
407
+ 3.962189519196340f
408
+ };
209
409
  // clang-format on
210
410
 
211
411
  struct LloydMaxTable {
@@ -219,15 +419,15 @@ const LloydMaxTable kLloydMaxTables[] = {
219
419
  {kLloydMaxCentroids2, kLloydMaxBoundaries2}, // 2
220
420
  {kLloydMaxCentroids3, kLloydMaxBoundaries3}, // 3
221
421
  {kLloydMaxCentroids4, kLloydMaxBoundaries4}, // 4
222
- {nullptr, nullptr}, // 5 (unused)
223
- {nullptr, nullptr}, // 6 (unused)
224
- {nullptr, nullptr}, // 7 (unused)
422
+ {kLloydMaxCentroids5, kLloydMaxBoundaries5}, // 5
423
+ {kLloydMaxCentroids6, kLloydMaxBoundaries6}, // 6
424
+ {kLloydMaxCentroids7, kLloydMaxBoundaries7}, // 7
225
425
  {kLloydMaxCentroids8, kLloydMaxBoundaries8}, // 8
226
426
  };
227
427
 
228
428
  void populate_lloyd_max_trained(size_t mse_bits, std::vector<float>& trained) {
229
429
  FAISS_THROW_IF_NOT(mse_bits >= 1 && mse_bits <= 8);
230
- FAISS_THROW_IF_NOT(kLloydMaxTables[mse_bits].centroids != nullptr);
430
+ FAISS_THROW_IF_NOT(kLloydMaxTables[mse_bits].centroids);
231
431
  size_t k = size_t(1) << mse_bits;
232
432
  const auto& t = kLloydMaxTables[mse_bits];
233
433
  trained.resize(k + (k - 1));
@@ -251,14 +451,17 @@ ScalarQuantizer::ScalarQuantizer() {}
251
451
  void ScalarQuantizer::set_derived_sizes() {
252
452
  switch (qtype) {
253
453
  case QT_1bit_tqmse:
454
+ case QT_1bit_eden:
254
455
  code_size = (d + 7) / 8;
255
456
  bits = 1;
256
457
  break;
257
458
  case QT_2bit_tqmse:
459
+ case QT_2bit_eden:
258
460
  code_size = (d * 2 + 7) / 8;
259
461
  bits = 2;
260
462
  break;
261
463
  case QT_3bit_tqmse:
464
+ case QT_3bit_eden:
262
465
  code_size = (d * 3 + 7) / 8;
263
466
  bits = 3;
264
467
  break;
@@ -267,19 +470,30 @@ void ScalarQuantizer::set_derived_sizes() {
267
470
  case QT_8bit_direct:
268
471
  case QT_8bit_direct_signed:
269
472
  case QT_8bit_tqmse:
473
+ case QT_8bit_eden:
270
474
  code_size = d;
271
475
  bits = 8;
272
476
  break;
273
477
  case QT_4bit:
274
478
  case QT_4bit_uniform:
275
479
  case QT_4bit_tqmse:
480
+ case QT_4bit_eden:
276
481
  code_size = (d + 1) / 2;
277
482
  bits = 4;
278
483
  break;
484
+ case QT_5bit_eden:
485
+ code_size = (d * 5 + 7) / 8;
486
+ bits = 5;
487
+ break;
279
488
  case QT_6bit:
489
+ case QT_6bit_eden:
280
490
  code_size = (d * 6 + 7) / 8;
281
491
  bits = 6;
282
492
  break;
493
+ case QT_7bit_eden:
494
+ code_size = (d * 7 + 7) / 8;
495
+ bits = 7;
496
+ break;
283
497
  case QT_fp16:
284
498
  code_size = d * 2;
285
499
  bits = 16;
@@ -334,7 +548,7 @@ void ScalarQuantizer::train(size_t n, const float* x) {
334
548
  case QT_4bit_uniform:
335
549
  case QT_8bit_uniform:
336
550
  FAISS_THROW_IF_NOT(n > 0);
337
- FAISS_THROW_IF_NOT(x != nullptr);
551
+ FAISS_THROW_IF_NOT(x);
338
552
  train_Uniform(
339
553
  rangestat,
340
554
  rangestat_arg,
@@ -347,7 +561,7 @@ void ScalarQuantizer::train(size_t n, const float* x) {
347
561
  case QT_8bit:
348
562
  case QT_6bit:
349
563
  FAISS_THROW_IF_NOT(n > 0);
350
- FAISS_THROW_IF_NOT(x != nullptr);
564
+ FAISS_THROW_IF_NOT(x);
351
565
  train_NonUniform(
352
566
  rangestat,
353
567
  rangestat_arg,
@@ -363,6 +577,16 @@ void ScalarQuantizer::train(size_t n, const float* x) {
363
577
  case QT_8bit_direct_signed:
364
578
  // no training necessary
365
579
  break;
580
+ case QT_1bit_eden:
581
+ case QT_2bit_eden:
582
+ case QT_3bit_eden:
583
+ case QT_4bit_eden:
584
+ case QT_5bit_eden:
585
+ case QT_6bit_eden:
586
+ case QT_7bit_eden:
587
+ case QT_8bit_eden:
588
+ populate_lloyd_max_trained(bits, trained);
589
+ break;
366
590
  case QT_1bit_tqmse:
367
591
  populate_lloyd_max_trained(1, trained);
368
592
  break;
@@ -417,17 +641,14 @@ void ScalarQuantizer::TurboQuantRefine::init_projection(size_t d) {
417
641
  }
418
642
 
419
643
  ScalarQuantizer::SQuantizer* ScalarQuantizer::select_quantizer() const {
420
- return with_simd_level_spr([&]<SIMDLevel SL>() -> SQuantizer* {
421
- if constexpr (SL != SIMDLevel::NONE) {
422
- auto* q = scalar_quantizer::sq_select_quantizer<SL>(
423
- qtype, d, trained);
424
- if (q) {
425
- return q;
426
- }
427
- }
428
- return scalar_quantizer::sq_select_quantizer<SIMDLevel::NONE>(
429
- qtype, d, trained);
430
- });
644
+ // A SIMD level's factory returns nullptr when the dimension is
645
+ // incompatible (e.g. AVX-512 needs d % 16 == 0); the dispatcher then falls
646
+ // back to the next-lower level (AVX-512 -> AVX2 -> scalar).
647
+ return with_simd_level_fallback<AVAILABLE_SIMD_LEVELS_A0_SPR>(
648
+ [&]<SIMDLevel SL>() -> SQuantizer* {
649
+ return scalar_quantizer::sq_select_quantizer<SL>(
650
+ qtype, d, trained);
651
+ });
431
652
  }
432
653
 
433
654
  void ScalarQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
@@ -438,7 +659,7 @@ void ScalarQuantizer::compute_codes(const float* x, uint8_t* codes, size_t n)
438
659
  std::unique_ptr<SQuantizer> squant(select_quantizer());
439
660
 
440
661
  memset(codes, 0, code_size * n);
441
- #pragma omp parallel for
662
+ #pragma omp parallel for if (n > 100)
442
663
  for (int64_t i = 0; i < static_cast<int64_t>(n); i++) {
443
664
  squant->encode_vector(x + i * d, codes + i * code_size);
444
665
  }
@@ -451,7 +672,7 @@ void ScalarQuantizer::decode(const uint8_t* codes, float* x, size_t n) const {
451
672
  }
452
673
  std::unique_ptr<SQuantizer> squant(select_quantizer());
453
674
 
454
- #pragma omp parallel for
675
+ #pragma omp parallel for if (n > 100)
455
676
  for (int64_t i = 0; i < static_cast<int64_t>(n); i++) {
456
677
  squant->decode_vector(codes + i * code_size, x + i * d);
457
678
  }
@@ -460,17 +681,11 @@ void ScalarQuantizer::decode(const uint8_t* codes, float* x, size_t n) const {
460
681
  ScalarQuantizer::SQDistanceComputer* ScalarQuantizer::get_distance_computer(
461
682
  MetricType metric) const {
462
683
  FAISS_THROW_IF_NOT(metric == METRIC_L2 || metric == METRIC_INNER_PRODUCT);
463
- return with_simd_level_spr([&]<SIMDLevel SL>() -> SQDistanceComputer* {
464
- if constexpr (SL != SIMDLevel::NONE) {
465
- auto* dc = scalar_quantizer::sq_select_distance_computer<SL>(
466
- metric, qtype, d, trained);
467
- if (dc) {
468
- return dc;
469
- }
470
- }
471
- return scalar_quantizer::sq_select_distance_computer<SIMDLevel::NONE>(
472
- metric, qtype, d, trained);
473
- });
684
+ return with_simd_level_fallback<AVAILABLE_SIMD_LEVELS_A0_SPR>(
685
+ [&]<SIMDLevel SL>() -> SQDistanceComputer* {
686
+ return scalar_quantizer::sq_select_distance_computer<SL>(
687
+ metric, qtype, d, trained);
688
+ });
474
689
  }
475
690
 
476
691
  InvertedListScanner* ScalarQuantizer::select_InvertedListScanner(
@@ -479,33 +694,19 @@ InvertedListScanner* ScalarQuantizer::select_InvertedListScanner(
479
694
  bool store_pairs,
480
695
  const IDSelector* sel,
481
696
  bool by_residual) const {
482
- return with_simd_level_spr([&]<SIMDLevel SL>() -> InvertedListScanner* {
483
- if constexpr (SL != SIMDLevel::NONE) {
484
- auto* s = scalar_quantizer::sq_select_InvertedListScanner<SL>(
485
- qtype,
486
- mt,
487
- d,
488
- code_size,
489
- trained,
490
- quantizer,
491
- store_pairs,
492
- sel,
493
- by_residual);
494
- if (s) {
495
- return s;
496
- }
497
- }
498
- return scalar_quantizer::sq_select_InvertedListScanner<SIMDLevel::NONE>(
499
- qtype,
500
- mt,
501
- d,
502
- code_size,
503
- trained,
504
- quantizer,
505
- store_pairs,
506
- sel,
507
- by_residual);
508
- });
697
+ return with_simd_level_fallback<AVAILABLE_SIMD_LEVELS_A0_SPR>(
698
+ [&]<SIMDLevel SL>() -> InvertedListScanner* {
699
+ return scalar_quantizer::sq_select_InvertedListScanner<SL>(
700
+ qtype,
701
+ mt,
702
+ d,
703
+ code_size,
704
+ trained,
705
+ quantizer,
706
+ store_pairs,
707
+ sel,
708
+ by_residual);
709
+ });
509
710
  }
510
711
 
511
712
  } // namespace faiss
@@ -45,6 +45,14 @@ struct ScalarQuantizer : Quantizer {
45
45
  QT_3bit_tq, ///< Full TurboQuant (2-bit MSE + 1-bit QJL + factors)
46
46
  QT_4bit_tq, ///< Full TurboQuant (3-bit MSE + 1-bit QJL + factors)
47
47
  QT_5bit_tq, ///< Full TurboQuant (4-bit MSE + 1-bit QJL + factors)
48
+ QT_1bit_eden, ///< EDEN Lloyd-Max scalar code, 1 bit per component
49
+ QT_2bit_eden, ///< EDEN Lloyd-Max scalar code, 2 bits per component
50
+ QT_3bit_eden, ///< EDEN Lloyd-Max scalar code, 3 bits per component
51
+ QT_4bit_eden, ///< EDEN Lloyd-Max scalar code, 4 bits per component
52
+ QT_5bit_eden, ///< EDEN Lloyd-Max scalar code, 5 bits per component
53
+ QT_6bit_eden, ///< EDEN Lloyd-Max scalar code, 6 bits per component
54
+ QT_7bit_eden, ///< EDEN Lloyd-Max scalar code, 7 bits per component
55
+ QT_8bit_eden, ///< EDEN Lloyd-Max scalar code, 8 bits per component
48
56
  QT_count
49
57
  };
50
58
 
@@ -135,6 +143,18 @@ struct ScalarQuantizer : Quantizer {
135
143
  float distance_to_code(const uint8_t* code) final {
136
144
  return query_to_code(code);
137
145
  }
146
+
147
+ void distance_to_code_batch_4(
148
+ const uint8_t* c1,
149
+ const uint8_t* c2,
150
+ const uint8_t* c3,
151
+ const uint8_t* c4,
152
+ float& d1,
153
+ float& d2,
154
+ float& d3,
155
+ float& d4) override {
156
+ query_to_codes_batch_4(c1, c2, c3, c4, d1, d2, d3, d4);
157
+ }
138
158
  };
139
159
 
140
160
  /// TurboQuant full (QT_*_tq) refinement state, isolated from the
@@ -70,8 +70,8 @@ void ThreadedIndex<IndexT>::addIndex(IndexT* index) {
70
70
 
71
71
  // Make sure this index is not duplicated
72
72
  for (auto& p : indices_) {
73
- FAISS_THROW_IF_NOT_MSG(
74
- p.first != index,
73
+ FAISS_THROW_IF_MSG(
74
+ p.first == index,
75
75
  "addIndex: attempting to add index "
76
76
  "that is already in the collection");
77
77
  }
@@ -15,8 +15,12 @@ namespace faiss {
15
15
  // advance() is O(1) except every 250 calls, which are O(size).
16
16
  // The hash set strategy is a constant factor slower for get()/set(),
17
17
  // but O(1) to construct and O(visits) to advance.
18
- // A size of ~1M seems to be the threshold where the hash set wins.
19
- size_t visited_table_hashset_threshold = 500000;
18
+ // 10M is only a current estimated threshold, not a proven crossover: we are not
19
+ // sure the array still wins at 10M. The point where the array stops paying off
20
+ // varies by dataset (it shifts with dimension, working-set / cache pressure,
21
+ // etc.), so this is a coarse default that should eventually be replaced by
22
+ // smarter per-index tuning.
23
+ size_t visited_table_hashset_threshold = 10000000;
20
24
 
21
25
  std::unique_ptr<VisitedTable> VisitedTable::create(
22
26
  size_t size,
@@ -29,6 +33,22 @@ std::unique_ptr<VisitedTable> VisitedTable::create(
29
33
  return std::make_unique<VisitedTableVector>(size);
30
34
  }
31
35
 
36
+ VisitedTable& VisitedTable::get_reusable(
37
+ size_t size,
38
+ std::optional<bool> use_hashset) {
39
+ bool use_set =
40
+ use_hashset.value_or(size >= visited_table_hashset_threshold);
41
+ if (use_set) {
42
+ thread_local VisitedTableSet tls_set;
43
+ tls_set.advance();
44
+ return tls_set;
45
+ }
46
+ thread_local VisitedTableVector tls_vec(0);
47
+ tls_vec.ensure_size(size);
48
+ tls_vec.advance();
49
+ return tls_vec;
50
+ }
51
+
32
52
  void VisitedTableVector::advance() {
33
53
  if (visno < 254) {
34
54
  // 254 rather than 255 because sometimes we use visno and visno+1
@@ -48,6 +48,18 @@ struct VisitedTable {
48
48
  static std::unique_ptr<VisitedTable> create(
49
49
  size_t size,
50
50
  std::optional<bool> use_hashset = std::nullopt);
51
+
52
+ /// Returns a thread-local, reusable table sized for at least `size` and
53
+ /// reset to a clean state. Unlike create(), it does not allocate on each
54
+ /// call: the O(size) versioned array is allocated once per thread and
55
+ /// reused across searches, avoiding a per-search alloc+zero of the whole
56
+ /// array when a static index is searched repeatedly.
57
+ ///
58
+ /// The returned reference is owned by thread-local storage: do not delete
59
+ /// it and do not use it beyond the current search on the calling thread.
60
+ static VisitedTable& get_reusable(
61
+ size_t size,
62
+ std::optional<bool> use_hashset = std::nullopt);
51
63
  };
52
64
 
53
65
  /// Set-based implementation using unordered_set.
@@ -87,6 +99,14 @@ struct VisitedTableVector FAISS_FINAL : VisitedTable {
87
99
 
88
100
  explicit VisitedTableVector(size_t size) : visited(size, 0) {}
89
101
 
102
+ /// Grow so indices in [0, size) are valid; new slots read as unvisited.
103
+ /// Never shrinks, so capacity is retained when the table is reused.
104
+ void ensure_size(size_t size) {
105
+ if (visited.size() < size) {
106
+ visited.resize(size, 0);
107
+ }
108
+ }
109
+
90
110
  bool set(size_t no) final {
91
111
  if (visited[no] == visno) {
92
112
  return false;
@@ -292,7 +292,7 @@ void search_knn_hamming_per_invlist(
292
292
  nprobe = std::min((idx_t)ivf->nlist, nprobe);
293
293
  idx_t max_codes = params ? params->max_codes : ivf->max_codes;
294
294
  FAISS_THROW_IF_NOT(max_codes == 0);
295
- FAISS_THROW_IF_NOT(!store_pairs);
295
+ FAISS_THROW_IF_MSG(store_pairs, "store_pairs is not supported here");
296
296
 
297
297
  // reorder buckets
298
298
  std::vector<int64_t> lims(n + 1);
@@ -9,17 +9,17 @@
9
9
 
10
10
  #define THE_SIMD_LEVEL SIMDLevel::AVX2
11
11
 
12
- // NOLINTNEXTLINE(facebook-hte-InlineHeader)
12
+ // NOLINTNEXTLINE(facebook-hte-InlineHeader,facebook-unused-include-check)
13
13
  #include <faiss/utils/hamming_distance/hamming_computer-avx2.h>
14
14
 
15
15
  // NOLINTNEXTLINE(facebook-hte-InlineHeader)
16
- #include <faiss/impl/binary_hamming/IndexBinaryHNSW_impl.h>
16
+ #include <faiss/impl/binary_hamming/IndexBinaryHNSW_impl.h> // IWYU pragma: keep
17
17
  // NOLINTNEXTLINE(facebook-hte-InlineHeader)
18
- #include <faiss/impl/binary_hamming/IndexBinaryHash_impl.h>
18
+ #include <faiss/impl/binary_hamming/IndexBinaryHash_impl.h> // IWYU pragma: keep
19
19
  // NOLINTNEXTLINE(facebook-hte-InlineHeader)
20
20
  #include <faiss/impl/binary_hamming/IndexBinaryIVF_impl.h>
21
21
  // NOLINTNEXTLINE(facebook-hte-InlineHeader)
22
- #include <faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h>
22
+ #include <faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h> // IWYU pragma: keep
23
23
  // NOLINTNEXTLINE(facebook-hte-InlineHeader)
24
24
  #include <faiss/impl/binary_hamming/IndexPQ_impl.h>
25
25
 
@@ -33,6 +33,7 @@
33
33
 
34
34
  #include <faiss/impl/fast_scan/accumulate_loops.h>
35
35
  #include <faiss/impl/fast_scan/fast_scan.h>
36
+ #include <faiss/utils/simd_levels.h>
36
37
 
37
38
  #if defined(COMPILE_SIMD_AVX512) && defined(__AVX512F__)
38
39
  #include <faiss/impl/fast_scan/accumulate_loops_512.h>
@@ -114,8 +115,40 @@ struct ScannerMixIn : FastScanCodeScanner {
114
115
  constexpr bool use_avx512_qbs = false;
115
116
  #endif
116
117
  if constexpr (use_avx512_qbs) {
117
- // Use 512-bit QBS kernels with properly-leveled scalers.
118
- if (pq2x4_scale) {
118
+ // AMD Zen 4 / Zen 4c ("Bergamo", family 0x19) split 512-bit
119
+ // ops over a 256-bit datapath, so the 512-bit QBS kernel yields no
120
+ // throughput gain but pays extra per-block LUT-assembly and
121
+ // cross-lane reduction overhead (measured ~14% search regression
122
+ // for PQ8x4fs / PQ16x4fs). Route those CPUs to the 256-bit (AVX2)
123
+ // QBS kernel instead -- same output, no downside on Zen 4. This is
124
+ // a process-constant runtime branch, hoisted out of the inner
125
+ // accumulate loop. Intel AVX-512 keeps the 512-bit kernel.
126
+ if (SIMDConfig::avx512_split) {
127
+ if (pq2x4_scale) {
128
+ NormTableScaler<SIMDLevel::AVX2> scaler(pq2x4_scale);
129
+ pq4_accumulate_loop_qbs_fixed_scaler_256<SIMDLevel::AVX2>(
130
+ qbs,
131
+ nb,
132
+ nsq,
133
+ codes,
134
+ LUT,
135
+ handler_,
136
+ scaler,
137
+ block_stride);
138
+ } else {
139
+ DummyScaler<SIMDLevel::AVX2> dummy;
140
+ pq4_accumulate_loop_qbs_fixed_scaler_256<SIMDLevel::AVX2>(
141
+ qbs,
142
+ nb,
143
+ nsq,
144
+ codes,
145
+ LUT,
146
+ handler_,
147
+ dummy,
148
+ block_stride);
149
+ }
150
+ } else if (pq2x4_scale) {
151
+ // Use 512-bit QBS kernels with properly-leveled scalers.
119
152
  NormTableScaler<THE_LEVEL_TO_DISPATCH> scaler(pq2x4_scale);
120
153
  pq4_accumulate_loop_qbs_fixed_scaler_512(
121
154
  qbs,
@@ -30,7 +30,7 @@ void LockVector::prepare(size_t new_size) {
30
30
  // Just destroy old and init fresh; omp_lock_t is not copyable.
31
31
  clear();
32
32
  data_ = static_cast<omp_lock_t*>(malloc(new_cap * sizeof(omp_lock_t)));
33
- FAISS_THROW_IF_NOT(data_ != nullptr);
33
+ FAISS_THROW_IF_NOT(data_);
34
34
  capacity_ = new_cap;
35
35
  }
36
36
  for (size_t i = size_; i < new_size; i++) {