faiss 0.6.0 → 0.6.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 (361) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/ext/faiss/extconf.rb +2 -1
  4. data/ext/faiss/{index_rb.cpp → index.cpp} +1 -1
  5. data/ext/faiss/index_binary.cpp +1 -1
  6. data/ext/faiss/kmeans.cpp +1 -1
  7. data/ext/faiss/pca_matrix.cpp +1 -1
  8. data/ext/faiss/product_quantizer.cpp +1 -1
  9. data/ext/faiss/{utils_rb.cpp → utils.cpp} +1 -1
  10. data/lib/faiss/version.rb +1 -1
  11. data/vendor/faiss/faiss/AutoTune.cpp +93 -80
  12. data/vendor/faiss/faiss/Clustering.cpp +39 -240
  13. data/vendor/faiss/faiss/Clustering.h +6 -0
  14. data/vendor/faiss/faiss/IVFlib.cpp +41 -21
  15. data/vendor/faiss/faiss/Index.cpp +6 -5
  16. data/vendor/faiss/faiss/Index.h +5 -5
  17. data/vendor/faiss/faiss/Index2Layer.cpp +37 -53
  18. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +49 -37
  19. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +36 -34
  20. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +4 -1
  21. data/vendor/faiss/faiss/IndexBinary.cpp +5 -3
  22. data/vendor/faiss/faiss/IndexBinary.h +4 -4
  23. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +1 -1
  24. data/vendor/faiss/faiss/IndexBinaryFlat.h +1 -1
  25. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +4 -4
  26. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +84 -92
  27. data/vendor/faiss/faiss/IndexBinaryHNSW.h +9 -3
  28. data/vendor/faiss/faiss/IndexBinaryHash.cpp +45 -236
  29. data/vendor/faiss/faiss/IndexBinaryHash.h +6 -6
  30. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +87 -415
  31. data/vendor/faiss/faiss/IndexFastScan.cpp +72 -109
  32. data/vendor/faiss/faiss/IndexFastScan.h +25 -23
  33. data/vendor/faiss/faiss/IndexFlat.cpp +27 -20
  34. data/vendor/faiss/faiss/IndexFlat.h +21 -18
  35. data/vendor/faiss/faiss/IndexFlatCodes.cpp +42 -19
  36. data/vendor/faiss/faiss/IndexHNSW.cpp +283 -145
  37. data/vendor/faiss/faiss/IndexHNSW.h +16 -2
  38. data/vendor/faiss/faiss/IndexIDMap.cpp +25 -21
  39. data/vendor/faiss/faiss/IndexIDMap.h +9 -7
  40. data/vendor/faiss/faiss/IndexIVF.cpp +465 -362
  41. data/vendor/faiss/faiss/IndexIVF.h +33 -12
  42. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +77 -74
  43. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +96 -93
  44. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +4 -1
  45. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +357 -238
  46. data/vendor/faiss/faiss/IndexIVFFastScan.h +42 -41
  47. data/vendor/faiss/faiss/IndexIVFFlat.cpp +36 -68
  48. data/vendor/faiss/faiss/IndexIVFFlat.h +32 -0
  49. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +53 -30
  50. data/vendor/faiss/faiss/IndexIVFFlatPanorama.h +3 -1
  51. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +18 -15
  52. data/vendor/faiss/faiss/IndexIVFPQ.cpp +71 -843
  53. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +151 -121
  54. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +3 -0
  55. data/vendor/faiss/faiss/IndexIVFPQR.cpp +21 -17
  56. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +26 -39
  57. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +2 -1
  58. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +475 -476
  59. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +248 -93
  60. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +41 -127
  61. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +1 -1
  62. data/vendor/faiss/faiss/IndexLSH.cpp +36 -19
  63. data/vendor/faiss/faiss/IndexLattice.cpp +13 -13
  64. data/vendor/faiss/faiss/IndexNNDescent.cpp +36 -21
  65. data/vendor/faiss/faiss/IndexNNDescent.h +2 -2
  66. data/vendor/faiss/faiss/IndexNSG.cpp +39 -23
  67. data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +31 -11
  68. data/vendor/faiss/faiss/IndexPQ.cpp +128 -221
  69. data/vendor/faiss/faiss/IndexPQ.h +3 -2
  70. data/vendor/faiss/faiss/IndexPQFastScan.cpp +20 -14
  71. data/vendor/faiss/faiss/IndexPQFastScan.h +3 -0
  72. data/vendor/faiss/faiss/IndexPreTransform.cpp +25 -18
  73. data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
  74. data/vendor/faiss/faiss/IndexRaBitQ.cpp +11 -36
  75. data/vendor/faiss/faiss/IndexRaBitQ.h +2 -1
  76. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +41 -277
  77. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +183 -27
  78. data/vendor/faiss/faiss/IndexRefine.cpp +30 -25
  79. data/vendor/faiss/faiss/IndexRefine.h +4 -4
  80. data/vendor/faiss/faiss/IndexReplicas.cpp +6 -6
  81. data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +15 -14
  82. data/vendor/faiss/faiss/IndexRowwiseMinMax.h +1 -1
  83. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +82 -14
  84. data/vendor/faiss/faiss/IndexShards.cpp +10 -9
  85. data/vendor/faiss/faiss/IndexShardsIVF.cpp +21 -15
  86. data/vendor/faiss/faiss/MatrixStats.cpp +5 -4
  87. data/vendor/faiss/faiss/MetaIndexes.cpp +19 -17
  88. data/vendor/faiss/faiss/MetaIndexes.h +1 -1
  89. data/vendor/faiss/faiss/MetricType.h +14 -7
  90. data/vendor/faiss/faiss/SuperKMeans.cpp +656 -0
  91. data/vendor/faiss/faiss/SuperKMeans.h +97 -0
  92. data/vendor/faiss/faiss/VectorTransform.cpp +237 -149
  93. data/vendor/faiss/faiss/VectorTransform.h +16 -16
  94. data/vendor/faiss/faiss/build.cpp +23 -0
  95. data/vendor/faiss/faiss/build.h +15 -0
  96. data/vendor/faiss/faiss/clone_index.cpp +48 -47
  97. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +47 -47
  98. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +11 -0
  99. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +38 -38
  100. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +11 -0
  101. data/vendor/faiss/faiss/factory_tools.cpp +5 -0
  102. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +6 -5
  103. data/vendor/faiss/faiss/gpu/GpuResources.h +1 -1
  104. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +9 -9
  105. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +4 -3
  106. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +46 -0
  107. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +56 -0
  108. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +78 -1
  109. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +72 -0
  110. data/vendor/faiss/faiss/gpu/test/TestUtils.h +23 -0
  111. data/vendor/faiss/faiss/gpu/utils/CuvsFilterConvert.h +1 -1
  112. data/vendor/faiss/faiss/gpu/utils/CuvsUtils.h +21 -10
  113. data/vendor/faiss/faiss/gpu_metal/GpuIndexFlat.h +22 -0
  114. data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +35 -0
  115. data/vendor/faiss/faiss/gpu_metal/MetalFlatKernels.h +40 -0
  116. data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +51 -0
  117. data/vendor/faiss/faiss/gpu_metal/MetalIndexFlat.h +65 -0
  118. data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +66 -0
  119. data/vendor/faiss/faiss/gpu_metal/MetalResources.h +79 -0
  120. data/vendor/faiss/faiss/gpu_metal/StandardMetalResources.h +35 -0
  121. data/vendor/faiss/faiss/impl/AdSampling.cpp +103 -0
  122. data/vendor/faiss/faiss/impl/AdSampling.h +35 -0
  123. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +29 -25
  124. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +1 -0
  125. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +10 -9
  126. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +3 -0
  127. data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +244 -0
  128. data/vendor/faiss/faiss/impl/ClusteringHelpers.h +94 -0
  129. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +16 -16
  130. data/vendor/faiss/faiss/impl/CodePacker.cpp +3 -3
  131. data/vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp +1 -1
  132. data/vendor/faiss/faiss/impl/DistanceComputer.h +8 -8
  133. data/vendor/faiss/faiss/impl/FaissAssert.h +6 -3
  134. data/vendor/faiss/faiss/impl/FaissException.h +50 -3
  135. data/vendor/faiss/faiss/impl/HNSW.cpp +92 -317
  136. data/vendor/faiss/faiss/impl/HNSW.h +13 -34
  137. data/vendor/faiss/faiss/impl/IDSelector.cpp +15 -11
  138. data/vendor/faiss/faiss/impl/IDSelector.h +8 -8
  139. data/vendor/faiss/faiss/impl/InvertedListScannerStats.h +26 -0
  140. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +82 -77
  141. data/vendor/faiss/faiss/impl/NNDescent.cpp +62 -25
  142. data/vendor/faiss/faiss/impl/NNDescent.h +6 -2
  143. data/vendor/faiss/faiss/impl/NSG.cpp +38 -21
  144. data/vendor/faiss/faiss/impl/NSG.h +4 -4
  145. data/vendor/faiss/faiss/impl/Panorama.cpp +23 -6
  146. data/vendor/faiss/faiss/impl/Panorama.h +258 -87
  147. data/vendor/faiss/faiss/impl/PdxLayout.cpp +93 -0
  148. data/vendor/faiss/faiss/impl/PdxLayout.h +41 -0
  149. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +46 -32
  150. data/vendor/faiss/faiss/impl/PolysemousTraining.h +3 -3
  151. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +35 -35
  152. data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +21 -16
  153. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +30 -23
  154. data/vendor/faiss/faiss/impl/Quantizer.h +2 -2
  155. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +55 -49
  156. data/vendor/faiss/faiss/impl/RaBitQUtils.h +65 -0
  157. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +296 -283
  158. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +26 -23
  159. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +1 -1
  160. data/vendor/faiss/faiss/impl/ResultHandler.h +99 -75
  161. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +52 -4
  162. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +27 -1
  163. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +14 -11
  164. data/vendor/faiss/faiss/impl/VisitedTable.h +7 -0
  165. data/vendor/faiss/faiss/impl/approx_topk/approx_topk.h +276 -0
  166. data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +68 -0
  167. data/vendor/faiss/faiss/{utils → impl}/approx_topk/generic.h +15 -8
  168. data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +68 -0
  169. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab-inl.h +169 -0
  170. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab.h +117 -0
  171. data/vendor/faiss/faiss/impl/approx_topk/simdlib256-inl.h +146 -0
  172. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHNSW_impl.h +73 -0
  173. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +270 -0
  174. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +460 -0
  175. data/vendor/faiss/faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h +159 -0
  176. data/vendor/faiss/faiss/impl/binary_hamming/IndexPQ_impl.h +92 -0
  177. data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +26 -0
  178. data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +26 -0
  179. data/vendor/faiss/faiss/impl/binary_hamming/dispatch.h +143 -0
  180. data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +26 -0
  181. data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +26 -0
  182. data/vendor/faiss/faiss/impl/expanded_scanners.h +8 -3
  183. data/vendor/faiss/faiss/impl/{FastScanDistancePostProcessing.h → fast_scan/FastScanDistancePostProcessing.h} +13 -6
  184. data/vendor/faiss/faiss/impl/{LookupTableScaler.h → fast_scan/LookupTableScaler.h} +16 -5
  185. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +237 -0
  186. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +185 -0
  187. data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +229 -0
  188. data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +268 -0
  189. data/vendor/faiss/faiss/impl/{pq4_fast_scan.cpp → fast_scan/fast_scan.cpp} +169 -2
  190. data/vendor/faiss/faiss/impl/fast_scan/fast_scan.h +341 -0
  191. data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +36 -0
  192. data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +40 -0
  193. data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +120 -0
  194. data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +104 -0
  195. data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +213 -0
  196. data/vendor/faiss/faiss/impl/{pq4_fast_scan_search_qbs.cpp → fast_scan/kernels_simd512.h} +26 -356
  197. data/vendor/faiss/faiss/impl/fast_scan/rabitq_dispatching.h +90 -0
  198. data/vendor/faiss/faiss/impl/fast_scan/rabitq_result_handler.h +108 -0
  199. data/vendor/faiss/faiss/impl/{simd_result_handlers.h → fast_scan/simd_result_handlers.h} +282 -134
  200. data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +54 -0
  201. data/vendor/faiss/faiss/impl/hnsw/LockVector.h +64 -0
  202. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +91 -0
  203. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +64 -0
  204. data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +104 -0
  205. data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +111 -0
  206. data/vendor/faiss/faiss/impl/index_read.cpp +1132 -45
  207. data/vendor/faiss/faiss/impl/index_read_utils.h +1 -1
  208. data/vendor/faiss/faiss/impl/index_write.cpp +95 -13
  209. data/vendor/faiss/faiss/impl/io.cpp +6 -6
  210. data/vendor/faiss/faiss/impl/io_macros.h +33 -16
  211. data/vendor/faiss/faiss/impl/kmeans1d.cpp +10 -10
  212. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +37 -23
  213. data/vendor/faiss/faiss/impl/lattice_Zn.h +6 -6
  214. data/vendor/faiss/faiss/impl/mapped_io.cpp +6 -6
  215. data/vendor/faiss/faiss/impl/platform_macros.h +11 -4
  216. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +549 -0
  217. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +245 -0
  218. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.h +105 -0
  219. data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +106 -0
  220. data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +21 -0
  221. data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +21 -0
  222. data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +21 -0
  223. data/vendor/faiss/faiss/impl/pq_code_distance/{pq_code_distance-avx2.cpp → pq_code_distance-avx2.h} +9 -13
  224. data/vendor/faiss/faiss/impl/pq_code_distance/{pq_code_distance-avx512.cpp → pq_code_distance-avx512.h} +9 -57
  225. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +29 -111
  226. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +96 -0
  227. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +238 -5
  228. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +5 -7
  229. data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +68 -0
  230. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +311 -477
  231. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
  232. data/vendor/faiss/faiss/impl/scalar_quantizer/codecs.h +1 -1
  233. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +3 -2
  234. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +102 -11
  235. data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +27 -1
  236. data/vendor/faiss/faiss/impl/scalar_quantizer/similarities.h +3 -3
  237. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +148 -0
  238. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +167 -0
  239. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +59 -0
  240. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +163 -0
  241. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +311 -0
  242. data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +192 -8
  243. data/vendor/faiss/faiss/impl/scalar_quantizer/training.h +12 -0
  244. data/vendor/faiss/faiss/impl/simd_dispatch.h +100 -66
  245. data/vendor/faiss/faiss/impl/simdlib/simdlib.h +57 -0
  246. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_avx2.h +264 -172
  247. data/vendor/faiss/faiss/impl/simdlib/simdlib_avx512.h +414 -0
  248. data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +44 -0
  249. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_emulated.h +231 -166
  250. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_neon.h +270 -218
  251. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_ppc64.h +201 -160
  252. data/vendor/faiss/faiss/impl/svs_io.cpp +12 -3
  253. data/vendor/faiss/faiss/impl/svs_io.h +8 -2
  254. data/vendor/faiss/faiss/index_factory.cpp +86 -18
  255. data/vendor/faiss/faiss/index_io.h +24 -0
  256. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +66 -16
  257. data/vendor/faiss/faiss/invlists/DirectMap.cpp +24 -14
  258. data/vendor/faiss/faiss/invlists/DirectMap.h +4 -3
  259. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +157 -73
  260. data/vendor/faiss/faiss/invlists/InvertedLists.h +86 -23
  261. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +4 -4
  262. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +13 -13
  263. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
  264. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +1 -1
  265. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +2 -2
  266. data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +350 -0
  267. data/vendor/faiss/faiss/svs/IndexSVSIVF.h +128 -0
  268. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.cpp +40 -0
  269. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.h +43 -0
  270. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +225 -0
  271. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.h +71 -0
  272. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +25 -1
  273. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +18 -2
  274. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +1 -1
  275. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +12 -3
  276. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +7 -2
  277. data/vendor/faiss/faiss/utils/Heap.cpp +10 -10
  278. data/vendor/faiss/faiss/utils/NeuralNet.cpp +47 -36
  279. data/vendor/faiss/faiss/utils/NeuralNet.h +1 -1
  280. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +10 -4
  281. data/vendor/faiss/faiss/utils/distances.cpp +390 -560
  282. data/vendor/faiss/faiss/utils/distances.h +20 -1
  283. data/vendor/faiss/faiss/utils/distances_dispatch.h +117 -37
  284. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +8 -7
  285. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +33 -14
  286. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +12 -1
  287. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +16 -293
  288. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +57 -0
  289. data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +290 -0
  290. data/vendor/faiss/faiss/utils/distances_simd.cpp +5 -177
  291. data/vendor/faiss/faiss/utils/extra_distances.cpp +9 -8
  292. data/vendor/faiss/faiss/utils/extra_distances.h +32 -6
  293. data/vendor/faiss/faiss/utils/hamming-inl.h +13 -11
  294. data/vendor/faiss/faiss/utils/hamming.cpp +66 -517
  295. data/vendor/faiss/faiss/utils/hamming.h +92 -2
  296. data/vendor/faiss/faiss/utils/hamming_distance/common.h +287 -10
  297. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +15 -0
  298. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +15 -0
  299. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx2.h +142 -0
  300. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +234 -0
  301. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-generic.h +368 -0
  302. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-neon.h +322 -0
  303. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-rvv.h +39 -0
  304. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer.h +146 -0
  305. data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +481 -0
  306. data/vendor/faiss/faiss/utils/hamming_distance/hamming_neon.cpp +15 -0
  307. data/vendor/faiss/faiss/utils/hamming_distance/hamming_rvv.cpp +15 -0
  308. data/vendor/faiss/faiss/utils/partitioning.cpp +66 -987
  309. data/vendor/faiss/faiss/utils/partitioning.h +31 -0
  310. data/vendor/faiss/faiss/utils/popcount.h +29 -0
  311. data/vendor/faiss/faiss/utils/pq_code_distance.h +2 -2
  312. data/vendor/faiss/faiss/utils/prefetch.h +2 -2
  313. data/vendor/faiss/faiss/utils/quantize_lut.cpp +30 -30
  314. data/vendor/faiss/faiss/utils/quantize_lut.h +1 -1
  315. data/vendor/faiss/faiss/utils/rabitq_simd.h +57 -536
  316. data/vendor/faiss/faiss/utils/random.cpp +6 -6
  317. data/vendor/faiss/faiss/utils/simd_impl/IVFFlatScanner-inl.h +51 -0
  318. data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +5 -1
  319. data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +213 -4
  320. data/vendor/faiss/faiss/utils/simd_impl/distances_autovec-inl.h +163 -10
  321. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +250 -4
  322. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +7 -4
  323. data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +189 -0
  324. data/vendor/faiss/faiss/utils/simd_impl/distances_simdlib256.h +195 -0
  325. data/vendor/faiss/faiss/utils/simd_impl/distances_sse-inl.h +2 -1
  326. data/vendor/faiss/faiss/utils/{distances_fused/simdlib_based.h → simd_impl/exhaustive_L2sqr_blas_cmax.h} +5 -10
  327. data/vendor/faiss/faiss/utils/simd_impl/hamming_impl.h +481 -0
  328. data/vendor/faiss/faiss/utils/simd_impl/partitioning_avx2.cpp +14 -0
  329. data/vendor/faiss/faiss/utils/simd_impl/partitioning_neon.cpp +14 -0
  330. data/vendor/faiss/faiss/utils/simd_impl/partitioning_simdlib256.h +1085 -0
  331. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +355 -0
  332. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +477 -0
  333. data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +55 -0
  334. data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +55 -0
  335. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_dispatch.h +32 -0
  336. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +43 -0
  337. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +57 -0
  338. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +45 -0
  339. data/vendor/faiss/faiss/utils/simd_levels.cpp +17 -5
  340. data/vendor/faiss/faiss/utils/simd_levels.h +93 -1
  341. data/vendor/faiss/faiss/utils/sorting.cpp +48 -36
  342. data/vendor/faiss/faiss/utils/utils.cpp +5 -5
  343. data/vendor/faiss/faiss/utils/utils.h +3 -3
  344. metadata +119 -34
  345. data/vendor/faiss/faiss/impl/RaBitQStats.cpp +0 -29
  346. data/vendor/faiss/faiss/impl/RaBitQStats.h +0 -56
  347. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +0 -224
  348. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +0 -230
  349. data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +0 -84
  350. data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +0 -196
  351. data/vendor/faiss/faiss/utils/approx_topk/mode.h +0 -34
  352. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +0 -36
  353. data/vendor/faiss/faiss/utils/extra_distances-inl.h +0 -235
  354. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +0 -462
  355. data/vendor/faiss/faiss/utils/hamming_distance/avx512-inl.h +0 -490
  356. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +0 -449
  357. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +0 -87
  358. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +0 -524
  359. data/vendor/faiss/faiss/utils/simdlib.h +0 -42
  360. data/vendor/faiss/faiss/utils/simdlib_avx512.h +0 -365
  361. /data/ext/faiss/{utils_rb.h → utils.h} +0 -0
@@ -8,45 +8,51 @@
8
8
  #include <faiss/IndexIVFPQFastScan.h>
9
9
 
10
10
  #include <array>
11
- #include <cassert>
12
11
  #include <cstdio>
13
12
 
14
13
  #include <memory>
15
14
 
16
15
  #include <faiss/impl/AuxIndexStructures.h>
17
16
  #include <faiss/impl/FaissAssert.h>
18
- #include <faiss/utils/Heap.h>
17
+ #include <faiss/impl/ResultHandler.h>
18
+ #include <faiss/impl/simdlib/simdlib_dispatch.h>
19
19
  #include <faiss/utils/distances.h>
20
+ #include <faiss/utils/distances_dispatch.h>
20
21
  #include <faiss/utils/extra_distances.h>
21
- #include <faiss/utils/simdlib.h>
22
22
 
23
23
  #include <faiss/invlists/BlockInvertedLists.h>
24
24
 
25
- #include <faiss/impl/pq4_fast_scan.h>
26
- #include <faiss/impl/simd_result_handlers.h>
25
+ #include <faiss/impl/fast_scan/FastScanDistancePostProcessing.h>
26
+ #include <faiss/impl/fast_scan/fast_scan.h>
27
+ #include <faiss/impl/fast_scan/simd_result_handlers.h>
27
28
 
28
29
  namespace faiss {
29
30
 
30
- using namespace simd_result_handlers;
31
-
32
31
  inline size_t roundup(size_t a, size_t b) {
33
32
  return (a + b - 1) / b * b;
34
33
  }
35
34
 
36
35
  IndexIVFPQFastScan::IndexIVFPQFastScan(
37
- Index* quantizer,
38
- size_t d,
39
- size_t nlist,
40
- size_t M,
41
- size_t nbits,
36
+ Index* quantizer_in,
37
+ size_t d_in,
38
+ size_t nlist_in,
39
+ size_t M_in,
40
+ size_t nbits_in,
42
41
  MetricType metric,
43
- int bbs,
44
- bool own_invlists)
45
- : IndexIVFFastScan(quantizer, d, nlist, 0, metric, own_invlists),
46
- pq(d, M, nbits) {
42
+ int bbs_in,
43
+ bool own_invlists_in)
44
+ : IndexIVFFastScan(
45
+ quantizer_in,
46
+ d_in,
47
+ nlist_in,
48
+ 0,
49
+ metric,
50
+ own_invlists_in),
51
+ pq(d_in, M_in, nbits_in) {
47
52
  by_residual = false; // set to false by default because it's faster
48
53
 
49
- init_fastscan(&pq, M, nbits, nlist, metric, bbs, own_invlists);
54
+ init_fastscan(
55
+ &pq, M_in, nbits_in, nlist_in, metric, bbs_in, own_invlists_in);
50
56
  }
51
57
 
52
58
  IndexIVFPQFastScan::IndexIVFPQFastScan() {
@@ -55,7 +61,7 @@ IndexIVFPQFastScan::IndexIVFPQFastScan() {
55
61
  M2 = 0;
56
62
  }
57
63
 
58
- IndexIVFPQFastScan::IndexIVFPQFastScan(const IndexIVFPQ& orig, int bbs)
64
+ IndexIVFPQFastScan::IndexIVFPQFastScan(const IndexIVFPQ& orig, int bbs_in)
59
65
  : IndexIVFFastScan(
60
66
  orig.quantizer,
61
67
  orig.d,
@@ -72,7 +78,7 @@ IndexIVFPQFastScan::IndexIVFPQFastScan(const IndexIVFPQ& orig, int bbs)
72
78
  orig.pq.nbits,
73
79
  orig.nlist,
74
80
  orig.metric_type,
75
- bbs,
81
+ bbs_in,
76
82
  orig.own_invlists);
77
83
 
78
84
  by_residual = orig.by_residual;
@@ -89,7 +95,7 @@ IndexIVFPQFastScan::IndexIVFPQFastScan(const IndexIVFPQ& orig, int bbs)
89
95
  }
90
96
 
91
97
  #pragma omp parallel for if (nlist > 100)
92
- for (idx_t i = 0; i < nlist; i++) {
98
+ for (idx_t i = 0; i < static_cast<idx_t>(nlist); i++) {
93
99
  size_t nb = orig.invlists->list_size(i);
94
100
  size_t nb2 = roundup(nb, bbs);
95
101
  AlignedTable<uint8_t> tmp(nb2 * M2 / 2);
@@ -111,6 +117,10 @@ IndexIVFPQFastScan::IndexIVFPQFastScan(const IndexIVFPQ& orig, int bbs)
111
117
  orig_invlists = orig.invlists;
112
118
  }
113
119
 
120
+ size_t IndexIVFPQFastScan::fast_scan_code_size() const {
121
+ return M2 / 2;
122
+ }
123
+
114
124
  /*********************************************************
115
125
  * Training
116
126
  *********************************************************/
@@ -118,7 +128,7 @@ IndexIVFPQFastScan::IndexIVFPQFastScan(const IndexIVFPQ& orig, int bbs)
118
128
  void IndexIVFPQFastScan::train_encoder(
119
129
  idx_t n,
120
130
  const float* x,
121
- const idx_t* assign) {
131
+ const idx_t* /*assign*/) {
122
132
  pq.verbose = verbose;
123
133
  pq.train(n, x);
124
134
 
@@ -153,7 +163,7 @@ void IndexIVFPQFastScan::encode_vectors(
153
163
  bool include_listnos) const {
154
164
  if (by_residual) {
155
165
  AlignedTable<float> residuals(n * d);
156
- for (size_t i = 0; i < n; i++) {
166
+ for (idx_t i = 0; i < n; i++) {
157
167
  if (list_nos[i] < 0) {
158
168
  memset(residuals.data() + i * d, 0, sizeof(residuals[0]) * d);
159
169
  } else {
@@ -180,16 +190,19 @@ void IndexIVFPQFastScan::encode_vectors(
180
190
  * Look-Up Table functions
181
191
  *********************************************************/
182
192
 
193
+ // Explicit SIMD-level alias (no global bare aliases).
194
+ using simd8float32 = simd8float32_tpl<SINGLE_SIMD_LEVEL_256>;
195
+
183
196
  void fvec_madd_simd(
184
197
  size_t n,
185
198
  const float* a,
186
199
  float bf,
187
200
  const float* b,
188
201
  float* c) {
189
- assert(is_aligned_pointer(a));
190
- assert(is_aligned_pointer(b));
191
- assert(is_aligned_pointer(c));
192
- assert(n % 8 == 0);
202
+ FAISS_THROW_IF_NOT_MSG(is_aligned_pointer(a), "pointer a is not aligned");
203
+ FAISS_THROW_IF_NOT_MSG(is_aligned_pointer(b), "pointer b is not aligned");
204
+ FAISS_THROW_IF_NOT_MSG(is_aligned_pointer(c), "pointer c is not aligned");
205
+ FAISS_THROW_IF_NOT_MSG(n % 8 == 0, "n must be a multiple of 8");
193
206
  simd8float32 bf8(bf);
194
207
  n /= 8;
195
208
  for (size_t i = 0; i < n; i++) {
@@ -216,23 +229,24 @@ void IndexIVFPQFastScan::compute_LUT(
216
229
  AlignedTable<float>& biases,
217
230
  const FastScanDistancePostProcessing&) const {
218
231
  size_t dim12 = pq.ksub * pq.M;
219
- size_t d = pq.d;
220
- size_t nprobe = cq.nprobe;
232
+ size_t pq_d = pq.d;
233
+ size_t cq_nprobe = cq.nprobe;
221
234
 
222
235
  if (by_residual) {
223
236
  if (metric_type == METRIC_L2) {
224
- dis_tables.resize(n * nprobe * dim12);
237
+ dis_tables.resize(n * cq_nprobe * dim12);
225
238
 
226
239
  if (use_precomputed_table == 1) {
227
- biases.resize(n * nprobe);
228
- memcpy(biases.get(), cq.dis, sizeof(float) * n * nprobe);
240
+ biases.resize(n * cq_nprobe);
241
+ memcpy(biases.get(), cq.dis, sizeof(float) * n * cq_nprobe);
229
242
 
230
243
  AlignedTable<float> ip_table(n * dim12);
231
244
  pq.compute_inner_prod_tables(n, x, ip_table.get());
232
245
 
233
- #pragma omp parallel for if (n * nprobe > 8000)
234
- for (idx_t ij = 0; ij < n * nprobe; ij++) {
235
- idx_t i = ij / nprobe;
246
+ #pragma omp parallel for if (n * cq_nprobe > 8000)
247
+ for (idx_t ij = 0; ij < static_cast<idx_t>(n * cq_nprobe);
248
+ ij++) {
249
+ idx_t i = ij / cq_nprobe;
236
250
  float* tab = dis_tables.get() + ij * dim12;
237
251
  idx_t cij = cq.ids[ij];
238
252
 
@@ -251,26 +265,27 @@ void IndexIVFPQFastScan::compute_LUT(
251
265
  }
252
266
 
253
267
  } else {
254
- std::unique_ptr<float[]> xrel(new float[n * nprobe * d]);
255
- biases.resize(n * nprobe);
256
- memset(biases.get(), 0, sizeof(float) * n * nprobe);
257
-
258
- #pragma omp parallel for if (n * nprobe > 8000)
259
- for (idx_t ij = 0; ij < n * nprobe; ij++) {
260
- idx_t i = ij / nprobe;
261
- float* xij = &xrel[ij * d];
268
+ std::unique_ptr<float[]> xrel(new float[n * cq_nprobe * pq_d]);
269
+ biases.resize(n * cq_nprobe);
270
+ memset(biases.get(), 0, sizeof(float) * n * cq_nprobe);
271
+
272
+ #pragma omp parallel for if (n * cq_nprobe > 8000)
273
+ for (idx_t ij = 0; ij < static_cast<idx_t>(n * cq_nprobe);
274
+ ij++) {
275
+ idx_t i = ij / cq_nprobe;
276
+ float* xij = &xrel[ij * pq_d];
262
277
  idx_t cij = cq.ids[ij];
263
278
 
264
279
  if (cij >= 0) {
265
- quantizer->compute_residual(x + i * d, xij, cij);
280
+ quantizer->compute_residual(x + i * pq_d, xij, cij);
266
281
  } else {
267
282
  // will fill with NaNs
268
- memset(xij, -1, sizeof(float) * d);
283
+ memset(xij, -1, sizeof(float) * pq_d);
269
284
  }
270
285
  }
271
286
 
272
287
  pq.compute_distance_tables(
273
- n * nprobe, xrel.get(), dis_tables.get());
288
+ n * cq_nprobe, xrel.get(), dis_tables.get());
274
289
  }
275
290
 
276
291
  } else if (metric_type == METRIC_INNER_PRODUCT) {
@@ -278,8 +293,8 @@ void IndexIVFPQFastScan::compute_LUT(
278
293
  pq.compute_inner_prod_tables(n, x, dis_tables.get());
279
294
  // compute_inner_prod_tables(pq, n, x, dis_tables.get());
280
295
 
281
- biases.resize(n * nprobe);
282
- memcpy(biases.get(), cq.dis, sizeof(float) * n * nprobe);
296
+ biases.resize(n * cq_nprobe);
297
+ memcpy(biases.get(), cq.dis, sizeof(float) * n * cq_nprobe);
283
298
  } else {
284
299
  FAISS_THROW_FMT("metric %d not supported", metric_type);
285
300
  }
@@ -303,7 +318,9 @@ void IndexIVFPQFastScan::compute_LUT(
303
318
  namespace {
304
319
 
305
320
  struct IVFPQFastScanScanner : InvertedListScanner {
306
- static constexpr int impl = 10; // based on search_implem_10
321
+ using InvertedListScanner::scan_codes;
322
+ [[maybe_unused]] static constexpr int impl =
323
+ 10; // based on search_implem_10
307
324
  static constexpr size_t nq = 1; // 1 query at a time.
308
325
  const IndexIVFPQFastScan& index;
309
326
  AlignedTable<uint8_t> dis_tables;
@@ -313,24 +330,24 @@ struct IVFPQFastScanScanner : InvertedListScanner {
313
330
  const float* xi = nullptr;
314
331
 
315
332
  IVFPQFastScanScanner(
316
- const IndexIVFPQFastScan& index,
317
- bool store_pairs,
318
- const IDSelector* sel)
319
- : InvertedListScanner(store_pairs, sel), index(index) {
320
- this->keep_max = is_similarity_metric(index.metric_type);
321
- residual.resize(index.d);
333
+ const IndexIVFPQFastScan& index_in,
334
+ bool store_pairs_in,
335
+ const IDSelector* sel_in)
336
+ : InvertedListScanner(store_pairs_in, sel_in), index(index_in) {
337
+ this->keep_max = is_similarity_metric(index_in.metric_type);
338
+ residual.resize(index_in.d);
322
339
  }
323
340
 
324
341
  void set_query(const float* query) override {
325
342
  this->xi = query;
326
343
  }
327
344
 
328
- void set_list(idx_t list_no, float coarse_dis) override {
329
- this->list_no = list_no;
345
+ void set_list(idx_t list_no_in, float coarse_dis_in) override {
346
+ this->list_no = list_no_in;
330
347
  IndexIVFFastScan::CoarseQuantized cq{
331
- .nprobe = 1, // 1 due to explicitly passing in list_no
332
- .dis = &coarse_dis, // dis from query to list_no centroid.
333
- .ids = &list_no, // id of the current list we are scanning
348
+ .nprobe = 1, // 1 due to explicitly passing in list_no
349
+ .dis = &coarse_dis_in, // dis from query to list_no centroid.
350
+ .ids = &list_no_in, // id of the current list we are scanning
334
351
  };
335
352
  FastScanDistancePostProcessing empty_context{};
336
353
  index.compute_LUT_uint8(
@@ -349,7 +366,7 @@ struct IVFPQFastScanScanner : InvertedListScanner {
349
366
  const float* x = index.by_residual ? residual.data() : this->xi;
350
367
  float accu = 0;
351
368
  // implemented for all vector distances, although only L2 and IP are
352
- // suppored by FastScan
369
+ // supported by FastScan
353
370
  with_VectorDistance(pq.dsub, index.metric_type, 0.0, [&](auto vd) {
354
371
  int m;
355
372
  for (m = 0; m + 1 < pq.M; m += 2) {
@@ -377,73 +394,86 @@ struct IVFPQFastScanScanner : InvertedListScanner {
377
394
  size_t ntotal,
378
395
  const uint8_t* codes,
379
396
  const idx_t* ids,
380
- float* distances,
381
- idx_t* labels,
382
- size_t k) const override {
383
- // initialize the current iteration heap to the worst possible value of
384
- // the prior loop
385
- std::vector<float> curr_dists(k, distances[0]);
386
- std::vector<idx_t> curr_labels(k, labels[0]);
387
- FastScanDistancePostProcessing empty_context{};
388
- std::unique_ptr<SIMDResultHandlerToFloat> handler(
389
- index.make_knn_handler(
390
- !keep_max,
391
- impl,
392
- nq,
393
- k,
394
- curr_dists.data(),
395
- curr_labels.data(),
396
- sel,
397
- empty_context,
398
- &normalizers[0]));
399
-
400
- // This does not quite match search_implem_10, but it is fine because
401
- // the scanner operates on a single query at a time, and this value is
402
- // used as the query index. For a single query, the value is always 0.
403
- int qmap1[1] = {0};
404
-
405
- handler->q_map = qmap1;
406
- handler->begin(&normalizers[0]);
407
-
408
- const uint8_t* LUT = dis_tables.get();
409
- handler->dbias = biases.get();
410
-
411
- handler->ntotal = ntotal;
412
- handler->id_map = ids;
413
-
414
- pq4_accumulate_loop(
415
- 1,
416
- roundup(ntotal, index.bbs),
417
- index.bbs,
418
- static_cast<int>(index.M2),
419
- codes,
420
- LUT,
421
- *handler,
422
- nullptr,
423
- index.get_block_stride());
424
-
425
- // The handler is for the results of this iteration.
426
- // Then we need a second heap to combine across iterations.
427
- handler->end();
428
- if (keep_max) {
429
- minheap_addn(
397
+ ResultHandler& handler) const override {
398
+ auto scan_with_heap = [&](auto* heap_handler) -> size_t {
399
+ const size_t k = heap_handler->k;
400
+ if (k == 0) {
401
+ return 0;
402
+ }
403
+
404
+ // initialize the current iteration heap to the worst possible value
405
+ // of the caller-owned result handler.
406
+ std::vector<float> curr_dists(k, handler.threshold);
407
+ std::vector<idx_t> curr_labels(k, -1);
408
+
409
+ auto scanner = index.make_knn_scanner(
410
+ !keep_max,
411
+ nq,
430
412
  k,
431
- distances,
432
- labels,
433
413
  curr_dists.data(),
434
414
  curr_labels.data(),
435
- k);
415
+ sel);
416
+
417
+ SIMDResultHandlerToFloat* rh = scanner->handler();
418
+
419
+ // This does not quite match search_implem_10, but it is fine
420
+ // because the scanner operates on a single query at a time, and
421
+ // this value is used as the query index. For a single query, the
422
+ // value is always 0.
423
+ int qmap1[1] = {0};
424
+
425
+ rh->q_map = qmap1;
426
+ rh->begin(&normalizers[0]);
427
+
428
+ rh->dbias = biases.get();
429
+ rh->ntotal = ntotal;
430
+ rh->id_map = ids;
431
+
432
+ scanner->accumulate_loop(
433
+ 1,
434
+ roundup(ntotal, index.bbs),
435
+ index.bbs,
436
+ static_cast<int>(index.M2),
437
+ codes,
438
+ dis_tables.get(),
439
+ 0,
440
+ index.get_block_stride());
441
+
442
+ const size_t scan_cnt = rh->count_scanned_rows();
443
+ rh->end();
444
+
445
+ handler.stats.scan_cnt += scan_cnt;
446
+ size_t nup = 0;
447
+ for (size_t j = 0; j < k; j++) {
448
+ if (curr_labels[j] < 0) {
449
+ continue;
450
+ }
451
+ if (handler.add_result(curr_dists[j], curr_labels[j])) {
452
+ handler.stats.nheap_updates++;
453
+ nup++;
454
+ }
455
+ }
456
+ return nup;
457
+ };
458
+
459
+ if (!keep_max) {
460
+ using C = CMax<float, idx_t>;
461
+ if (auto* heap_handler =
462
+ dynamic_cast<HeapResultHandler<C, false>*>(&handler)) {
463
+ return scan_with_heap(heap_handler);
464
+ }
436
465
  } else {
437
- maxheap_addn(
438
- k,
439
- distances,
440
- labels,
441
- curr_dists.data(),
442
- curr_labels.data(),
443
- k);
466
+ using C = CMin<float, idx_t>;
467
+ if (auto* heap_handler =
468
+ dynamic_cast<HeapResultHandler<C, false>*>(&handler)) {
469
+ return scan_with_heap(heap_handler);
470
+ }
444
471
  }
445
472
 
446
- return handler->num_updates();
473
+ FAISS_THROW_MSG(
474
+ "IVFPQFastScanScanner::scan_codes requires HeapResultHandler; "
475
+ "custom ResultHandler scan is not supported by this optimized "
476
+ "scanner");
447
477
  }
448
478
  };
449
479
 
@@ -55,6 +55,9 @@ struct IndexIVFPQFastScan : IndexIVFFastScan {
55
55
  // built from an IndexIVFPQ
56
56
  explicit IndexIVFPQFastScan(const IndexIVFPQ& orig, int bbs = 32);
57
57
 
58
+ /// Packed code size: M2 / 2 bytes (4-bit PQ sub-quantizer nibbles)
59
+ size_t fast_scan_code_size() const override;
60
+
58
61
  void train_encoder(idx_t n, const float* x, const idx_t* assign) override;
59
62
 
60
63
  idx_t train_encoder_num_vectors() const override;
@@ -25,23 +25,23 @@ namespace faiss {
25
25
  ******************************************/
26
26
 
27
27
  IndexIVFPQR::IndexIVFPQR(
28
- Index* quantizer,
29
- size_t d,
30
- size_t nlist,
28
+ Index* quantizer_in,
29
+ size_t d_in,
30
+ size_t nlist_in,
31
31
  size_t M,
32
32
  size_t nbits_per_idx,
33
33
  size_t M_refine,
34
34
  size_t nbits_per_idx_refine,
35
- bool own_invlists)
35
+ bool own_invlists_in)
36
36
  : IndexIVFPQ(
37
- quantizer,
38
- d,
39
- nlist,
37
+ quantizer_in,
38
+ d_in,
39
+ nlist_in,
40
40
  M,
41
41
  nbits_per_idx,
42
42
  METRIC_L2,
43
- own_invlists),
44
- refine_pq(d, M_refine, nbits_per_idx_refine),
43
+ own_invlists_in),
44
+ refine_pq(d_in, M_refine, nbits_per_idx_refine),
45
45
  k_factor(4) {
46
46
  by_residual = true;
47
47
  refine_pq.cp.max_points_per_centroid = 1000;
@@ -126,7 +126,7 @@ void IndexIVFPQR::search_preassigned(
126
126
  idx_t* labels,
127
127
  bool store_pairs,
128
128
  const IVFSearchParameters* params,
129
- IndexIVFStats* stats) const {
129
+ IndexIVFStats* /*stats*/) const {
130
130
  uint64_t t0;
131
131
  TIC;
132
132
  size_t k_coarse = long((size_t)k * k_factor);
@@ -166,18 +166,22 @@ void IndexIVFPQR::search_preassigned(
166
166
  idx_t* heap_ids = labels + k * i;
167
167
  maxheap_heapify(k, heap_sim, heap_ids);
168
168
 
169
- for (int j = 0; j < k_coarse; j++) {
169
+ for (size_t j = 0; j < k_coarse; j++) {
170
170
  idx_t sl = shortlist[j];
171
171
 
172
172
  if (sl == -1) {
173
173
  continue;
174
174
  }
175
175
 
176
- int list_no = lo_listno(sl);
177
- int ofs = lo_offset(sl);
176
+ int list_no = static_cast<int>(lo_listno(sl));
177
+ int ofs = static_cast<int>(lo_offset(sl));
178
178
 
179
- assert(list_no >= 0 && list_no < nlist);
180
- assert(ofs >= 0 && ofs < invlists->list_size(list_no));
179
+ FAISS_THROW_IF_NOT(
180
+ list_no >= 0 && static_cast<size_t>(list_no) < nlist);
181
+ FAISS_THROW_IF_NOT(
182
+ ofs >= 0 &&
183
+ static_cast<size_t>(ofs) <
184
+ invlists->list_size(list_no));
181
185
 
182
186
  // 1st level residual
183
187
  quantizer->compute_residual(xq, residual_1.get(), list_no);
@@ -192,7 +196,7 @@ void IndexIVFPQR::search_preassigned(
192
196
 
193
197
  // 3rd level residual's approximation
194
198
  idx_t id = invlists->get_single_id(list_no, ofs);
195
- assert(0 <= id && id < ntotal);
199
+ FAISS_THROW_IF_NOT(0 <= id && id < ntotal);
196
200
  refine_pq.decode(
197
201
  &refine_codes[id * refine_pq.code_size],
198
202
  residual_1.get());
@@ -219,7 +223,7 @@ void IndexIVFPQR::reconstruct_from_offset(
219
223
  IndexIVFPQ::reconstruct_from_offset(list_no, offset, recons);
220
224
 
221
225
  idx_t id = invlists->get_single_id(list_no, offset);
222
- assert(0 <= id && id < ntotal);
226
+ FAISS_THROW_IF_NOT(0 <= id && id < ntotal);
223
227
 
224
228
  std::vector<float> r3(d);
225
229
  refine_pq.decode(&refine_codes[id * refine_pq.code_size], r3.data());