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