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
@@ -14,6 +14,7 @@
14
14
  #include <cstdio>
15
15
 
16
16
  #include <algorithm>
17
+ #include <limits>
17
18
  #include <memory>
18
19
 
19
20
  #include <faiss/IndexFlat.h>
@@ -24,22 +25,33 @@
24
25
  #include <faiss/utils/sorting.h>
25
26
  #include <faiss/utils/utils.h>
26
27
 
28
+ #include <faiss/impl/simd_dispatch.h>
29
+
30
+ // Scalar (NONE) fallback for dynamic dispatch
31
+ #define THE_SIMD_LEVEL SIMDLevel::NONE
32
+ // NOLINTNEXTLINE(facebook-hte-InlineHeader)
33
+ // NOLINTNEXTLINE(facebook-hte-InlineHeader)
34
+ #include <faiss/impl/binary_hamming/IndexBinaryIVF_impl.h>
35
+ #include <faiss/utils/hamming_distance/hamming_computer-generic.h>
36
+ #undef THE_SIMD_LEVEL
37
+
27
38
  namespace faiss {
28
39
 
29
40
  IndexBinaryIVF::IndexBinaryIVF(
30
- IndexBinary* quantizer,
31
- size_t d,
32
- size_t nlist,
33
- bool own_invlists)
34
- : IndexBinary(d),
41
+ IndexBinary* quantizer_,
42
+ size_t d_,
43
+ size_t nlist_,
44
+ bool own_invlists_)
45
+ : IndexBinary(d_),
35
46
  invlists(
36
- own_invlists ? new ArrayInvertedLists(nlist, code_size)
37
- : nullptr),
38
- own_invlists(own_invlists),
39
- quantizer(quantizer),
40
- nlist(nlist) {
41
- FAISS_THROW_IF_NOT(d == quantizer->d);
42
- is_trained = quantizer->is_trained && (quantizer->ntotal == nlist);
47
+ own_invlists_ ? new ArrayInvertedLists(nlist_, code_size)
48
+ : nullptr),
49
+ own_invlists(own_invlists_),
50
+ quantizer(quantizer_),
51
+ nlist(nlist_) {
52
+ FAISS_THROW_IF_NOT(d_ == static_cast<size_t>(quantizer_->d));
53
+ is_trained = quantizer_->is_trained &&
54
+ (static_cast<size_t>(quantizer_->ntotal) == nlist_);
43
55
  cp.niter = 10;
44
56
  }
45
57
 
@@ -62,7 +74,7 @@ void IndexBinaryIVF::add_core(
62
74
  const idx_t* xids,
63
75
  const idx_t* precomputed_idx) {
64
76
  FAISS_THROW_IF_NOT(is_trained);
65
- assert(invlists);
77
+ FAISS_THROW_IF_NOT_MSG(invlists, "invlists not initialized");
66
78
  direct_map.check_can_add(xids);
67
79
 
68
80
  const idx_t* idx;
@@ -78,7 +90,7 @@ void IndexBinaryIVF::add_core(
78
90
  }
79
91
 
80
92
  idx_t n_add = 0;
81
- for (size_t i = 0; i < n; i++) {
93
+ for (idx_t i = 0; i < n; i++) {
82
94
  idx_t id = xids ? xids[i] : ntotal + i;
83
95
  idx_t list_no = idx[i];
84
96
 
@@ -120,25 +132,47 @@ void IndexBinaryIVF::search(
120
132
  idx_t k,
121
133
  int32_t* distances,
122
134
  idx_t* labels,
123
- const SearchParameters* params) const {
124
- FAISS_THROW_IF_NOT_MSG(
125
- !params, "search params not supported for this index");
135
+ const SearchParameters* params_in) const {
126
136
  FAISS_THROW_IF_NOT(k > 0);
127
- FAISS_THROW_IF_NOT(nprobe > 0);
137
+ FAISS_THROW_IF_NOT_MSG(invlists, "IVF index has no inverted lists");
138
+ const IVFSearchParameters* params = nullptr;
139
+ if (params_in) {
140
+ params = dynamic_cast<const IVFSearchParameters*>(params_in);
141
+ FAISS_THROW_IF_NOT_MSG(
142
+ params, "IndexBinaryIVF params have incorrect type");
143
+ FAISS_THROW_IF_MSG(
144
+ params->sel, "IDSelector is not supported for IndexBinaryIVF");
145
+ }
146
+ const size_t nprobe_ =
147
+ std::min(nlist, params ? params->nprobe : this->nprobe);
148
+ FAISS_THROW_IF_NOT(nprobe_ > 0);
128
149
 
129
- const size_t nprobe_2 = std::min(nlist, this->nprobe);
130
- std::unique_ptr<idx_t[]> idx(new idx_t[n * nprobe_2]);
131
- std::unique_ptr<int32_t[]> coarse_dis(new int32_t[n * nprobe_2]);
150
+ std::unique_ptr<idx_t[]> idx(new idx_t[n * nprobe_]);
151
+ std::unique_ptr<int32_t[]> coarse_dis(new int32_t[n * nprobe_]);
132
152
 
133
153
  double t0 = getmillisecs();
134
- quantizer->search(n, x, nprobe_2, coarse_dis.get(), idx.get());
154
+ quantizer->search(
155
+ n,
156
+ x,
157
+ nprobe_,
158
+ coarse_dis.get(),
159
+ idx.get(),
160
+ params ? params->quantizer_params : nullptr);
135
161
  indexIVF_stats.quantization_time += getmillisecs() - t0;
136
162
 
137
163
  t0 = getmillisecs();
138
- invlists->prefetch_lists(idx.get(), n * nprobe_2);
164
+ invlists->prefetch_lists(idx.get(), static_cast<int>(n * nprobe_));
139
165
 
140
166
  search_preassigned(
141
- n, x, k, idx.get(), coarse_dis.get(), distances, labels, false);
167
+ n,
168
+ x,
169
+ k,
170
+ idx.get(),
171
+ coarse_dis.get(),
172
+ distances,
173
+ labels,
174
+ false,
175
+ params);
142
176
  indexIVF_stats.search_time += getmillisecs() - t0;
143
177
  }
144
178
 
@@ -150,11 +184,11 @@ void IndexBinaryIVF::reconstruct(idx_t key, uint8_t* recons) const {
150
184
  void IndexBinaryIVF::reconstruct_n(idx_t i0, idx_t ni, uint8_t* recons) const {
151
185
  FAISS_THROW_IF_NOT(ni == 0 || (i0 >= 0 && i0 + ni <= ntotal));
152
186
 
153
- for (idx_t list_no = 0; list_no < nlist; list_no++) {
187
+ for (size_t list_no = 0; list_no < nlist; list_no++) {
154
188
  size_t list_size = invlists->list_size(list_no);
155
189
  const idx_t* idlist = invlists->get_ids(list_no);
156
190
 
157
- for (idx_t offset = 0; offset < list_size; offset++) {
191
+ for (size_t offset = 0; offset < list_size; offset++) {
158
192
  idx_t id = idlist[offset];
159
193
  if (!(id >= i0 && id < i0 + ni)) {
160
194
  continue;
@@ -185,7 +219,7 @@ void IndexBinaryIVF::search_and_reconstruct(
185
219
 
186
220
  quantizer->search(n, x, nprobe_2, coarse_dis.get(), idx.get());
187
221
 
188
- invlists->prefetch_lists(idx.get(), n * nprobe_2);
222
+ invlists->prefetch_lists(idx.get(), static_cast<int>(n * nprobe_2));
189
223
 
190
224
  // search_preassigned() with `store_pairs` enabled to obtain the list_no
191
225
  // and offset into `codes` for reconstruction
@@ -243,7 +277,8 @@ void IndexBinaryIVF::train(idx_t n, const uint8_t* x) {
243
277
  printf("Training quantizer\n");
244
278
  }
245
279
 
246
- if (quantizer->is_trained && (quantizer->ntotal == nlist)) {
280
+ if (quantizer->is_trained &&
281
+ (static_cast<size_t>(quantizer->ntotal) == nlist)) {
247
282
  if (verbose) {
248
283
  printf("IVF quantizer does not need training.\n");
249
284
  }
@@ -252,7 +287,7 @@ void IndexBinaryIVF::train(idx_t n, const uint8_t* x) {
252
287
  printf("Training quantizer on %" PRId64 " vectors in %dD\n", n, d);
253
288
  }
254
289
 
255
- Clustering clus(d, nlist, cp);
290
+ Clustering clus(d, static_cast<int>(nlist), cp);
256
291
  quantizer->reset();
257
292
 
258
293
  IndexFlatL2 index_tmp(d);
@@ -304,7 +339,9 @@ void IndexBinaryIVF::merge_from(IndexBinary& otherIndex, idx_t add_id) {
304
339
  }
305
340
 
306
341
  void IndexBinaryIVF::replace_invlists(InvertedLists* il, bool own) {
307
- FAISS_THROW_IF_NOT(il->nlist == nlist && il->code_size == code_size);
342
+ FAISS_THROW_IF_NOT(
343
+ il->nlist == nlist &&
344
+ il->code_size == static_cast<size_t>(code_size));
308
345
  if (own_invlists) {
309
346
  delete invlists;
310
347
  }
@@ -312,68 +349,11 @@ void IndexBinaryIVF::replace_invlists(InvertedLists* il, bool own) {
312
349
  own_invlists = own;
313
350
  }
314
351
 
315
- namespace {
316
-
317
- template <class HammingComputer>
318
- struct IVFBinaryScannerL2 : BinaryInvertedListScanner {
319
- HammingComputer hc;
320
- size_t code_size;
321
- bool store_pairs;
322
-
323
- IVFBinaryScannerL2(size_t code_size, bool store_pairs)
324
- : code_size(code_size), store_pairs(store_pairs) {}
325
-
326
- void set_query(const uint8_t* query_vector) override {
327
- hc.set(query_vector, code_size);
328
- }
329
-
330
- idx_t list_no;
331
- void set_list(idx_t list_no_2, uint8_t /* coarse_dis */) override {
332
- this->list_no = list_no_2;
333
- }
334
-
335
- uint32_t distance_to_code(const uint8_t* code) const override {
336
- return hc.hamming(code);
337
- }
352
+ // IVFBinaryScannerL2, search_knn_hamming_count, BlockSearch,
353
+ // BlockSearchVariableK, search_knn_hamming_per_invlist are now in
354
+ // impl/binary_hamming/IndexBinaryIVF_impl.h (compiled per-ISA)
338
355
 
339
- size_t scan_codes(
340
- size_t n,
341
- const uint8_t* __restrict codes,
342
- const idx_t* __restrict ids,
343
- int32_t* __restrict simi,
344
- idx_t* __restrict idxi,
345
- size_t k) const override {
346
- using C = CMax<int32_t, idx_t>;
347
-
348
- size_t nup = 0;
349
- for (size_t j = 0; j < n; j++) {
350
- uint32_t dis = hc.hamming(codes);
351
- if (dis < simi[0]) {
352
- idx_t id = store_pairs ? lo_build(list_no, j) : ids[j];
353
- heap_replace_top<C>(k, simi, idxi, dis, id);
354
- nup++;
355
- }
356
- codes += code_size;
357
- }
358
- return nup;
359
- }
360
-
361
- void scan_codes_range(
362
- size_t n,
363
- const uint8_t* __restrict codes,
364
- const idx_t* __restrict ids,
365
- int radius,
366
- RangeQueryResult& result) const override {
367
- for (size_t j = 0; j < n; j++) {
368
- uint32_t dis = hc.hamming(codes);
369
- if (dis < radius) {
370
- int64_t id = store_pairs ? lo_build(list_no, j) : ids[j];
371
- result.add(dis, id);
372
- }
373
- codes += code_size;
374
- }
375
- }
376
- };
356
+ namespace {
377
357
 
378
358
  void search_knn_hamming_heap(
379
359
  const IndexBinaryIVF* ivf,
@@ -389,6 +369,10 @@ void search_knn_hamming_heap(
389
369
  idx_t nprobe = params ? params->nprobe : ivf->nprobe;
390
370
  nprobe = std::min((idx_t)ivf->nlist, nprobe);
391
371
  idx_t max_codes = params ? params->max_codes : ivf->max_codes;
372
+ const idx_t unlimited_list_size = std::numeric_limits<idx_t>::max();
373
+ if (max_codes == 0) {
374
+ max_codes = unlimited_list_size;
375
+ }
392
376
  MetricType metric_type = ivf->metric_type;
393
377
 
394
378
  // almost verbatim copy from IndexIVF::search_preassigned
@@ -403,7 +387,7 @@ void search_knn_hamming_heap(
403
387
  ivf->get_InvertedListScanner(store_pairs));
404
388
 
405
389
  #pragma omp for
406
- for (idx_t i = 0; i < n; i++) {
390
+ for (idx_t i = 0; i < static_cast<idx_t>(n); i++) {
407
391
  const uint8_t* xi = x + i * ivf->code_size;
408
392
  scanner->set_query(xi);
409
393
 
@@ -419,7 +403,7 @@ void search_knn_hamming_heap(
419
403
 
420
404
  size_t nscan = 0;
421
405
 
422
- for (size_t ik = 0; ik < nprobe; ik++) {
406
+ for (idx_t ik = 0; ik < nprobe; ik++) {
423
407
  idx_t key = keysi[ik]; /* select the list */
424
408
  if (key < 0) {
425
409
  // not enough centroids for multiprobe
@@ -429,7 +413,7 @@ void search_knn_hamming_heap(
429
413
  key < (idx_t)ivf->nlist,
430
414
  "Invalid key=%" PRId64 " at ik=%zd nlist=%zd\n",
431
415
  key,
432
- ik,
416
+ static_cast<size_t>(ik),
433
417
  ivf->nlist);
434
418
 
435
419
  scanner->set_list(key, coarse_dis[i * nprobe + ik]);
@@ -437,6 +421,10 @@ void search_knn_hamming_heap(
437
421
  nlistv++;
438
422
 
439
423
  size_t list_size = ivf->invlists->list_size(key);
424
+ size_t list_size_max = static_cast<size_t>(max_codes) - nscan;
425
+ if (list_size > list_size_max) {
426
+ list_size = list_size_max;
427
+ }
440
428
  InvertedLists::ScopedCodes scodes(ivf->invlists, key);
441
429
  std::unique_ptr<InvertedLists::ScopedIds> sids;
442
430
  const idx_t* ids = nullptr;
@@ -451,7 +439,7 @@ void search_knn_hamming_heap(
451
439
  list_size, scodes.get(), ids, simi, idxi, k);
452
440
 
453
441
  nscan += list_size;
454
- if (max_codes && nscan >= max_codes) {
442
+ if (nscan >= static_cast<size_t>(max_codes)) {
455
443
  break;
456
444
  }
457
445
  }
@@ -472,313 +460,17 @@ void search_knn_hamming_heap(
472
460
  indexIVF_stats.nheap_updates += nheap;
473
461
  }
474
462
 
475
- template <class HammingComputer, bool store_pairs>
476
- void search_knn_hamming_count(
477
- const IndexBinaryIVF* ivf,
478
- size_t nx,
479
- const uint8_t* __restrict x,
480
- const idx_t* __restrict keys,
481
- int k,
482
- int32_t* __restrict distances,
483
- idx_t* __restrict labels,
484
- const IVFSearchParameters* params) {
485
- const int nBuckets = ivf->d + 1;
486
- std::vector<int> all_counters(nx * nBuckets, 0);
487
- std::unique_ptr<idx_t[]> all_ids_per_dis(new idx_t[nx * nBuckets * k]);
488
-
489
- idx_t nprobe = params ? params->nprobe : ivf->nprobe;
490
- nprobe = std::min((idx_t)ivf->nlist, nprobe);
491
- idx_t max_codes = params ? params->max_codes : ivf->max_codes;
492
-
493
- std::vector<HCounterState<HammingComputer>> cs;
494
- for (size_t i = 0; i < nx; ++i) {
495
- cs.push_back(
496
- HCounterState<HammingComputer>(
497
- all_counters.data() + i * nBuckets,
498
- all_ids_per_dis.get() + i * nBuckets * k,
499
- x + i * ivf->code_size,
500
- ivf->d,
501
- k));
502
- }
503
-
504
- size_t nlistv = 0, ndis = 0;
505
-
506
- #pragma omp parallel for reduction(+ : nlistv, ndis)
507
- for (int64_t i = 0; i < nx; i++) {
508
- const idx_t* keysi = keys + i * nprobe;
509
- HCounterState<HammingComputer>& csi = cs[i];
510
-
511
- size_t nscan = 0;
512
-
513
- for (size_t ik = 0; ik < nprobe; ik++) {
514
- idx_t key = keysi[ik]; /* select the list */
515
- if (key < 0) {
516
- // not enough centroids for multiprobe
517
- continue;
518
- }
519
- FAISS_THROW_IF_NOT_FMT(
520
- key < (idx_t)ivf->nlist,
521
- "Invalid key=%" PRId64 " at ik=%zd nlist=%zd\n",
522
- key,
523
- ik,
524
- ivf->nlist);
525
-
526
- nlistv++;
527
- size_t list_size = ivf->invlists->list_size(key);
528
- InvertedLists::ScopedCodes scodes(ivf->invlists, key);
529
- const uint8_t* list_vecs = scodes.get();
530
- const idx_t* ids =
531
- store_pairs ? nullptr : ivf->invlists->get_ids(key);
532
-
533
- for (size_t j = 0; j < list_size; j++) {
534
- const uint8_t* yj = list_vecs + ivf->code_size * j;
535
-
536
- idx_t id = store_pairs ? (key << 32 | j) : ids[j];
537
- csi.update_counter(yj, id);
538
- }
539
- if (ids) {
540
- ivf->invlists->release_ids(key, ids);
541
- }
542
-
543
- nscan += list_size;
544
- if (max_codes && nscan >= max_codes) {
545
- break;
546
- }
547
- }
548
- ndis += nscan;
549
-
550
- int nres = 0;
551
- for (int b = 0; b < nBuckets && nres < k; b++) {
552
- for (int l = 0; l < csi.counters[b] && nres < k; l++) {
553
- labels[i * k + nres] = csi.ids_per_dis[b * k + l];
554
- distances[i * k + nres] = b;
555
- nres++;
556
- }
557
- }
558
- while (nres < k) {
559
- labels[i * k + nres] = -1;
560
- distances[i * k + nres] = std::numeric_limits<int32_t>::max();
561
- ++nres;
562
- }
563
- }
564
-
565
- indexIVF_stats.nq += nx;
566
- indexIVF_stats.nlist += nlistv;
567
- indexIVF_stats.ndis += ndis;
568
- }
569
-
570
- /* Manages NQ queries at a time, stores results */
571
- template <class HammingComputer, int NQ, int K>
572
- struct BlockSearch {
573
- HammingComputer hcs[NQ];
574
- // heaps to update for each query
575
- int32_t* distances[NQ];
576
- idx_t* labels[NQ];
577
- // curent top of heap
578
- int32_t heap_tops[NQ];
579
-
580
- BlockSearch(
581
- size_t code_size,
582
- const uint8_t* __restrict x,
583
- const int32_t* __restrict keys,
584
- int32_t* __restrict all_distances,
585
- idx_t* __restrict all_labels) {
586
- for (idx_t q = 0; q < NQ; q++) {
587
- idx_t qno = keys[q];
588
- hcs[q] = HammingComputer(x + qno * code_size, code_size);
589
- distances[q] = all_distances + qno * K;
590
- labels[q] = all_labels + qno * K;
591
- heap_tops[q] = distances[q][0];
592
- }
593
- }
594
-
595
- void add_bcode(const uint8_t* bcode, idx_t id) {
596
- using C = CMax<int32_t, idx_t>;
597
- for (int q = 0; q < NQ; q++) {
598
- int dis = hcs[q].hamming(bcode);
599
- if (dis < heap_tops[q]) {
600
- heap_replace_top<C>(K, distances[q], labels[q], dis, id);
601
- heap_tops[q] = distances[q][0];
602
- }
603
- }
604
- }
605
- };
606
-
607
- template <class HammingComputer, int NQ>
608
- struct BlockSearchVariableK {
609
- int k;
610
- HammingComputer hcs[NQ];
611
- // heaps to update for each query
612
- int32_t* distances[NQ];
613
- idx_t* labels[NQ];
614
- // curent top of heap
615
- int32_t heap_tops[NQ];
616
-
617
- BlockSearchVariableK(
618
- size_t code_size,
619
- int k,
620
- const uint8_t* __restrict x,
621
- const int32_t* __restrict keys,
622
- int32_t* __restrict all_distances,
623
- idx_t* __restrict all_labels)
624
- : k(k) {
625
- for (idx_t q = 0; q < NQ; q++) {
626
- idx_t qno = keys[q];
627
- hcs[q] = HammingComputer(x + qno * code_size, code_size);
628
- distances[q] = all_distances + qno * k;
629
- labels[q] = all_labels + qno * k;
630
- heap_tops[q] = distances[q][0];
631
- }
632
- }
633
-
634
- void add_bcode(const uint8_t* bcode, idx_t id) {
635
- using C = CMax<int32_t, idx_t>;
636
- for (int q = 0; q < NQ; q++) {
637
- int dis = hcs[q].hamming(bcode);
638
- if (dis < heap_tops[q]) {
639
- heap_replace_top<C>(k, distances[q], labels[q], dis, id);
640
- heap_tops[q] = distances[q][0];
641
- }
642
- }
643
- }
644
- };
645
-
646
- template <class HammingComputer>
647
- void search_knn_hamming_per_invlist(
648
- const IndexBinaryIVF* ivf,
649
- size_t n,
650
- const uint8_t* __restrict x,
651
- idx_t k,
652
- const idx_t* __restrict keys_in,
653
- const int32_t* __restrict coarse_dis,
654
- int32_t* __restrict distances,
655
- idx_t* __restrict labels,
656
- bool store_pairs,
657
- const IVFSearchParameters* params) {
658
- idx_t nprobe = params ? params->nprobe : ivf->nprobe;
659
- nprobe = std::min((idx_t)ivf->nlist, nprobe);
660
- idx_t max_codes = params ? params->max_codes : ivf->max_codes;
661
- FAISS_THROW_IF_NOT(max_codes == 0);
662
- FAISS_THROW_IF_NOT(!store_pairs);
663
-
664
- // reorder buckets
665
- std::vector<int64_t> lims(n + 1);
666
- int32_t* keys = new int32_t[n * nprobe];
667
- std::unique_ptr<int32_t[]> delete_keys(keys);
668
- for (idx_t i = 0; i < n * nprobe; i++) {
669
- keys[i] = keys_in[i];
670
- }
671
- matrix_bucket_sort_inplace(n, nprobe, keys, ivf->nlist, lims.data(), 0);
672
-
673
- using C = CMax<int32_t, idx_t>;
674
- heap_heapify<C>(n * k, distances, labels);
675
- const size_t code_size = ivf->code_size;
676
-
677
- for (idx_t l = 0; l < ivf->nlist; l++) {
678
- idx_t l0 = lims[l], nq = lims[l + 1] - l0;
679
-
680
- InvertedLists::ScopedCodes scodes(ivf->invlists, l);
681
- InvertedLists::ScopedIds sidx(ivf->invlists, l);
682
- idx_t nb = ivf->invlists->list_size(l);
683
- const uint8_t* bcodes = scodes.get();
684
- const idx_t* ids = sidx.get();
685
-
686
- idx_t i = 0;
687
-
688
- // process as much as possible by blocks
689
- constexpr int BS = 4;
690
-
691
- if (k == 1) {
692
- for (; i + BS <= nq; i += BS) {
693
- BlockSearch<HammingComputer, BS, 1> bc(
694
- code_size, x, keys + l0 + i, distances, labels);
695
- for (idx_t j = 0; j < nb; j++) {
696
- bc.add_bcode(bcodes + j * code_size, ids[j]);
697
- }
698
- }
699
- } else if (k == 2) {
700
- for (; i + BS <= nq; i += BS) {
701
- BlockSearch<HammingComputer, BS, 2> bc(
702
- code_size, x, keys + l0 + i, distances, labels);
703
- for (idx_t j = 0; j < nb; j++) {
704
- bc.add_bcode(bcodes + j * code_size, ids[j]);
705
- }
706
- }
707
- } else if (k == 4) {
708
- for (; i + BS <= nq; i += BS) {
709
- BlockSearch<HammingComputer, BS, 4> bc(
710
- code_size, x, keys + l0 + i, distances, labels);
711
- for (idx_t j = 0; j < nb; j++) {
712
- bc.add_bcode(bcodes + j * code_size, ids[j]);
713
- }
714
- }
715
- } else {
716
- for (; i + BS <= nq; i += BS) {
717
- BlockSearchVariableK<HammingComputer, BS> bc(
718
- code_size, k, x, keys + l0 + i, distances, labels);
719
- for (idx_t j = 0; j < nb; j++) {
720
- bc.add_bcode(bcodes + j * code_size, ids[j]);
721
- }
722
- }
723
- }
724
-
725
- // leftovers
726
- for (; i < nq; i++) {
727
- idx_t qno = keys[l0 + i];
728
- HammingComputer hc(x + qno * code_size, code_size);
729
- idx_t* __restrict idxi = labels + qno * k;
730
- int32_t* __restrict simi = distances + qno * k;
731
- int32_t simi0 = simi[0];
732
- for (idx_t j = 0; j < nb; j++) {
733
- int dis = hc.hamming(bcodes + j * code_size);
734
-
735
- if (dis < simi0) {
736
- idx_t id = store_pairs ? lo_build(l, j) : ids[j];
737
- heap_replace_top<C>(k, simi, idxi, dis, id);
738
- simi0 = simi[0];
739
- }
740
- }
741
- }
742
- }
743
- for (idx_t i = 0; i < n; i++) {
744
- heap_reorder<C>(k, distances + i * k, labels + i * k);
745
- }
746
- }
747
-
748
- struct Run_search_knn_hamming_per_invlist {
749
- using T = void;
750
-
751
- template <class HammingComputer, class... Types>
752
- void f(Types... args) {
753
- search_knn_hamming_per_invlist<HammingComputer>(args...);
754
- }
755
- };
756
-
757
- template <bool store_pairs>
758
- struct Run_search_knn_hamming_count {
759
- using T = void;
760
-
761
- template <class HammingComputer, class... Types>
762
- void f(Types... args) {
763
- search_knn_hamming_count<HammingComputer, store_pairs>(args...);
764
- }
765
- };
766
-
767
- struct BuildScanner {
768
- using T = BinaryInvertedListScanner*;
769
-
770
- template <class HammingComputer>
771
- T f(size_t code_size, bool store_pairs) {
772
- return new IVFBinaryScannerL2<HammingComputer>(code_size, store_pairs);
773
- }
774
- };
775
-
776
463
  } // anonymous namespace
777
464
 
465
+ // The remaining template code (search_knn_hamming_count,
466
+ // search_knn_hamming_per_invlist, etc.) has been moved to
467
+ // impl/binary_hamming/IndexBinaryIVF_impl.h
468
+
778
469
  BinaryInvertedListScanner* IndexBinaryIVF::get_InvertedListScanner(
779
470
  bool store_pairs) const {
780
- BuildScanner bs;
781
- return dispatch_HammingComputer(code_size, bs, code_size, store_pairs);
471
+ return with_simd_level([&]<SIMDLevel SL>() {
472
+ return make_binary_ivf_scanner_fixSL<SL>(code_size, store_pairs);
473
+ });
782
474
  }
783
475
 
784
476
  void IndexBinaryIVF::search_preassigned(
@@ -792,23 +484,37 @@ void IndexBinaryIVF::search_preassigned(
792
484
  bool store_pairs,
793
485
  const IVFSearchParameters* params) const {
794
486
  if (per_invlist_search) {
795
- Run_search_knn_hamming_per_invlist r;
796
- // clang-format off
797
- dispatch_HammingComputer(
798
- code_size, r, this, n, x, k,
799
- cidx, cdis, dis, idx, store_pairs, params);
800
- // clang-format on
487
+ with_simd_level([&]<SIMDLevel SL>() {
488
+ search_knn_hamming_per_invlist_fixSL<SL>(
489
+ code_size,
490
+ this,
491
+ n,
492
+ x,
493
+ k,
494
+ cidx,
495
+ cdis,
496
+ dis,
497
+ idx,
498
+ store_pairs,
499
+ params);
500
+ });
801
501
  } else if (use_heap) {
802
502
  search_knn_hamming_heap(
803
503
  this, n, x, k, cidx, cdis, dis, idx, store_pairs, params);
804
- } else if (store_pairs) { // !use_heap && store_pairs
805
- Run_search_knn_hamming_count<true> r;
806
- dispatch_HammingComputer(
807
- code_size, r, this, n, x, cidx, k, dis, idx, params);
808
- } else { // !use_heap && !store_pairs
809
- Run_search_knn_hamming_count<false> r;
810
- dispatch_HammingComputer(
811
- code_size, r, this, n, x, cidx, k, dis, idx, params);
504
+ } else {
505
+ with_simd_level([&]<SIMDLevel SL>() {
506
+ search_knn_hamming_count_fixSL<SL>(
507
+ code_size,
508
+ store_pairs,
509
+ this,
510
+ n,
511
+ x,
512
+ cidx,
513
+ k,
514
+ dis,
515
+ idx,
516
+ params);
517
+ });
812
518
  }
813
519
  }
814
520
 
@@ -829,7 +535,7 @@ void IndexBinaryIVF::range_search(
829
535
  indexIVF_stats.quantization_time += getmillisecs() - t0;
830
536
 
831
537
  t0 = getmillisecs();
832
- invlists->prefetch_lists(idx.get(), n * nprobe_2);
538
+ invlists->prefetch_lists(idx.get(), static_cast<int>(n * nprobe_2));
833
539
 
834
540
  range_search_preassigned(n, x, radius, idx.get(), coarse_dis.get(), res);
835
541
 
@@ -841,7 +547,7 @@ void IndexBinaryIVF::range_search_preassigned(
841
547
  const uint8_t* __restrict x,
842
548
  int radius,
843
549
  const idx_t* __restrict assign,
844
- const int32_t* __restrict centroid_dis,
550
+ const int32_t* __restrict /* centroid_dis */,
845
551
  RangeSearchResult* __restrict res) const {
846
552
  const size_t nprobe_2 = std::min(nlist, this->nprobe);
847
553
  bool store_pairs = false;