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
@@ -0,0 +1,460 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ /*
9
+ * Per-ISA implementation of Hamming distance computation for
10
+ * IndexBinaryIVF. Included once per SIMD TU with THE_SIMD_LEVEL
11
+ * set to the desired SIMDLevel.
12
+ *
13
+ * Contains: IVFBinaryScannerL2, search_knn_hamming_count,
14
+ * BlockSearch, BlockSearchVariableK, search_knn_hamming_per_invlist.
15
+ */
16
+
17
+ #pragma once
18
+
19
+ #ifndef THE_SIMD_LEVEL
20
+ #error "THE_SIMD_LEVEL must be defined before including this file"
21
+ #endif
22
+
23
+ #include <faiss/utils/hamming_distance/hamming_computer.h>
24
+
25
+ #include <algorithm>
26
+ #include <cinttypes>
27
+ #include <limits>
28
+ #include <memory>
29
+
30
+ #include <faiss/IndexBinaryIVF.h>
31
+ #include <faiss/impl/AuxIndexStructures.h>
32
+ #include <faiss/impl/FaissAssert.h>
33
+ #include <faiss/impl/binary_hamming/dispatch.h>
34
+ #include <faiss/utils/Heap.h>
35
+ #include <faiss/utils/hamming.h>
36
+ #include <faiss/utils/sorting.h>
37
+
38
+ namespace faiss {
39
+
40
+ namespace {
41
+
42
+ template <class HammingComputer>
43
+ struct IVFBinaryScannerL2 : BinaryInvertedListScanner {
44
+ HammingComputer hc;
45
+ size_t code_size;
46
+ bool store_pairs;
47
+
48
+ IVFBinaryScannerL2(size_t code_size_, bool store_pairs_)
49
+ : code_size(code_size_), store_pairs(store_pairs_) {}
50
+
51
+ void set_query(const uint8_t* query_vector) override {
52
+ hc.set(query_vector, code_size);
53
+ }
54
+
55
+ idx_t list_no = 0;
56
+ void set_list(idx_t list_no_2, uint8_t /* coarse_dis */) override {
57
+ this->list_no = list_no_2;
58
+ }
59
+
60
+ uint32_t distance_to_code(const uint8_t* code) const override {
61
+ return hc.hamming(code);
62
+ }
63
+
64
+ size_t scan_codes(
65
+ size_t n,
66
+ const uint8_t* __restrict codes,
67
+ const idx_t* __restrict ids,
68
+ int32_t* __restrict simi,
69
+ idx_t* __restrict idxi,
70
+ size_t k) const override {
71
+ using C = CMax<int32_t, idx_t>;
72
+
73
+ size_t nup = 0;
74
+ for (size_t j = 0; j < n; j++) {
75
+ uint32_t dis = hc.hamming(codes);
76
+ if (dis < static_cast<uint32_t>(simi[0])) {
77
+ idx_t id = store_pairs ? lo_build(list_no, j) : ids[j];
78
+ heap_replace_top<C>(k, simi, idxi, dis, id);
79
+ nup++;
80
+ }
81
+ codes += code_size;
82
+ }
83
+ return nup;
84
+ }
85
+
86
+ void scan_codes_range(
87
+ size_t n,
88
+ const uint8_t* __restrict codes,
89
+ const idx_t* __restrict ids,
90
+ int radius,
91
+ RangeQueryResult& result) const override {
92
+ for (size_t j = 0; j < n; j++) {
93
+ uint32_t dis = hc.hamming(codes);
94
+ if (dis < static_cast<uint32_t>(radius)) {
95
+ int64_t id = store_pairs ? lo_build(list_no, j) : ids[j];
96
+ result.add(dis, id);
97
+ }
98
+ codes += code_size;
99
+ }
100
+ }
101
+ };
102
+
103
+ template <class HammingComputer, bool store_pairs>
104
+ void search_knn_hamming_count(
105
+ const IndexBinaryIVF* ivf,
106
+ size_t nx,
107
+ const uint8_t* __restrict x,
108
+ const idx_t* __restrict keys,
109
+ int k,
110
+ int32_t* __restrict distances,
111
+ idx_t* __restrict labels,
112
+ const IVFSearchParameters* params) {
113
+ const int nBuckets = ivf->d + 1;
114
+ std::vector<int> all_counters(nx * nBuckets, 0);
115
+ std::unique_ptr<idx_t[]> all_ids_per_dis(new idx_t[nx * nBuckets * k]);
116
+
117
+ idx_t nprobe = params ? params->nprobe : ivf->nprobe;
118
+ nprobe = std::min((idx_t)ivf->nlist, nprobe);
119
+ idx_t max_codes = params ? params->max_codes : ivf->max_codes;
120
+
121
+ std::vector<HCounterState<HammingComputer>> cs;
122
+ cs.reserve(nx);
123
+ for (size_t i = 0; i < nx; ++i) {
124
+ cs.push_back(
125
+ HCounterState<HammingComputer>(
126
+ all_counters.data() + i * nBuckets,
127
+ all_ids_per_dis.get() + i * nBuckets * k,
128
+ x + i * ivf->code_size,
129
+ ivf->d,
130
+ k));
131
+ }
132
+
133
+ size_t nlistv = 0, ndis = 0;
134
+
135
+ #pragma omp parallel for reduction(+ : nlistv, ndis)
136
+ for (int64_t i = 0; i < static_cast<int64_t>(nx); i++) {
137
+ const idx_t* keysi = keys + i * nprobe;
138
+ HCounterState<HammingComputer>& csi = cs[i];
139
+
140
+ size_t nscan = 0;
141
+
142
+ for (idx_t ik = 0; ik < nprobe; ik++) {
143
+ idx_t key = keysi[ik]; /* select the list */
144
+ if (key < 0) {
145
+ // not enough centroids for multiprobe
146
+ continue;
147
+ }
148
+ FAISS_THROW_IF_NOT_FMT(
149
+ key < (idx_t)ivf->nlist,
150
+ "Invalid key=%" PRId64 " at ik=%zd nlist=%zd\n",
151
+ key,
152
+ static_cast<size_t>(ik),
153
+ ivf->nlist);
154
+
155
+ nlistv++;
156
+ size_t list_size = ivf->invlists->list_size(key);
157
+ size_t list_size_max = static_cast<size_t>(max_codes) - nscan;
158
+ if (list_size > list_size_max) {
159
+ list_size = list_size_max;
160
+ }
161
+ InvertedLists::ScopedCodes scodes(ivf->invlists, key);
162
+ const uint8_t* list_vecs = scodes.get();
163
+ const idx_t* ids =
164
+ store_pairs ? nullptr : ivf->invlists->get_ids(key);
165
+
166
+ for (size_t j = 0; j < list_size; j++) {
167
+ const uint8_t* yj = list_vecs + ivf->code_size * j;
168
+
169
+ idx_t id = store_pairs ? (key << 32 | j) : ids[j];
170
+ csi.update_counter(yj, id);
171
+ }
172
+ if (ids) {
173
+ ivf->invlists->release_ids(key, ids);
174
+ }
175
+
176
+ nscan += list_size;
177
+ if (nscan >= static_cast<size_t>(max_codes)) {
178
+ break;
179
+ }
180
+ }
181
+ ndis += nscan;
182
+
183
+ int nres = 0;
184
+ for (int b = 0; b < nBuckets && nres < k; b++) {
185
+ for (int l = 0; l < csi.counters[b] && nres < k; l++) {
186
+ labels[i * k + nres] = csi.ids_per_dis[b * k + l];
187
+ distances[i * k + nres] = b;
188
+ nres++;
189
+ }
190
+ }
191
+ while (nres < k) {
192
+ labels[i * k + nres] = -1;
193
+ distances[i * k + nres] = std::numeric_limits<int32_t>::max();
194
+ ++nres;
195
+ }
196
+ }
197
+
198
+ indexIVF_stats.nq += nx;
199
+ indexIVF_stats.nlist += nlistv;
200
+ indexIVF_stats.ndis += ndis;
201
+ }
202
+
203
+ /* Manages NQ queries at a time, stores results */
204
+ template <class HammingComputer, int NQ, int K>
205
+ struct BlockSearch {
206
+ HammingComputer hcs[NQ];
207
+ // heaps to update for each query
208
+ int32_t* distances[NQ] = {};
209
+ idx_t* labels[NQ] = {};
210
+ // curent top of heap
211
+ int32_t heap_tops[NQ] = {};
212
+
213
+ BlockSearch(
214
+ size_t code_size,
215
+ const uint8_t* __restrict x,
216
+ const int32_t* __restrict keys,
217
+ int32_t* __restrict all_distances,
218
+ idx_t* __restrict all_labels) {
219
+ for (idx_t q = 0; q < NQ; q++) {
220
+ idx_t qno = keys[q];
221
+ hcs[q] = HammingComputer(x + qno * code_size, code_size);
222
+ distances[q] = all_distances + qno * K;
223
+ labels[q] = all_labels + qno * K;
224
+ heap_tops[q] = distances[q][0];
225
+ }
226
+ }
227
+
228
+ void add_bcode(const uint8_t* bcode, idx_t id) {
229
+ using C = CMax<int32_t, idx_t>;
230
+ for (int q = 0; q < NQ; q++) {
231
+ int dis = hcs[q].hamming(bcode);
232
+ if (dis < heap_tops[q]) {
233
+ heap_replace_top<C>(K, distances[q], labels[q], dis, id);
234
+ heap_tops[q] = distances[q][0];
235
+ }
236
+ }
237
+ }
238
+ };
239
+
240
+ template <class HammingComputer, int NQ>
241
+ struct BlockSearchVariableK {
242
+ int k;
243
+ HammingComputer hcs[NQ];
244
+ // heaps to update for each query
245
+ int32_t* distances[NQ] = {};
246
+ idx_t* labels[NQ] = {};
247
+ // curent top of heap
248
+ int32_t heap_tops[NQ] = {};
249
+
250
+ BlockSearchVariableK(
251
+ size_t code_size,
252
+ int k_,
253
+ const uint8_t* __restrict x,
254
+ const int32_t* __restrict keys,
255
+ int32_t* __restrict all_distances,
256
+ idx_t* __restrict all_labels)
257
+ : k(k_) {
258
+ for (idx_t q = 0; q < NQ; q++) {
259
+ idx_t qno = keys[q];
260
+ hcs[q] = HammingComputer(x + qno * code_size, code_size);
261
+ distances[q] = all_distances + qno * k;
262
+ labels[q] = all_labels + qno * k;
263
+ heap_tops[q] = distances[q][0];
264
+ }
265
+ }
266
+
267
+ void add_bcode(const uint8_t* bcode, idx_t id) {
268
+ using C = CMax<int32_t, idx_t>;
269
+ for (int q = 0; q < NQ; q++) {
270
+ int dis = hcs[q].hamming(bcode);
271
+ if (dis < heap_tops[q]) {
272
+ heap_replace_top<C>(k, distances[q], labels[q], dis, id);
273
+ heap_tops[q] = distances[q][0];
274
+ }
275
+ }
276
+ }
277
+ };
278
+
279
+ template <class HammingComputer>
280
+ void search_knn_hamming_per_invlist(
281
+ const IndexBinaryIVF* ivf,
282
+ size_t n,
283
+ const uint8_t* __restrict x,
284
+ idx_t k,
285
+ const idx_t* __restrict keys_in,
286
+ const int32_t* __restrict /* coarse_dis */,
287
+ int32_t* __restrict distances,
288
+ idx_t* __restrict labels,
289
+ bool store_pairs,
290
+ const IVFSearchParameters* params) {
291
+ idx_t nprobe = params ? params->nprobe : ivf->nprobe;
292
+ nprobe = std::min((idx_t)ivf->nlist, nprobe);
293
+ idx_t max_codes = params ? params->max_codes : ivf->max_codes;
294
+ FAISS_THROW_IF_NOT(max_codes == 0);
295
+ FAISS_THROW_IF_NOT(!store_pairs);
296
+
297
+ // reorder buckets
298
+ std::vector<int64_t> lims(n + 1);
299
+ int32_t* keys = new int32_t[n * nprobe];
300
+ std::unique_ptr<int32_t[]> delete_keys(keys);
301
+ for (size_t i = 0; i < n * static_cast<size_t>(nprobe); i++) {
302
+ keys[i] = static_cast<int32_t>(keys_in[i]);
303
+ }
304
+ matrix_bucket_sort_inplace(
305
+ n, nprobe, keys, static_cast<int32_t>(ivf->nlist), lims.data(), 0);
306
+
307
+ using C = CMax<int32_t, idx_t>;
308
+ heap_heapify<C>(n * k, distances, labels);
309
+ const size_t code_size = ivf->code_size;
310
+
311
+ for (size_t l = 0; l < ivf->nlist; l++) {
312
+ idx_t l0 = lims[l], nq = lims[l + 1] - l0;
313
+
314
+ InvertedLists::ScopedCodes scodes(ivf->invlists, l);
315
+ InvertedLists::ScopedIds sidx(ivf->invlists, l);
316
+ idx_t nb = ivf->invlists->list_size(l);
317
+ const uint8_t* bcodes = scodes.get();
318
+ const idx_t* ids = sidx.get();
319
+
320
+ idx_t i = 0;
321
+
322
+ // process as much as possible by blocks
323
+ constexpr int BS = 4;
324
+
325
+ if (k == 1) {
326
+ for (; i + BS <= nq; i += BS) {
327
+ BlockSearch<HammingComputer, BS, 1> bc(
328
+ code_size, x, keys + l0 + i, distances, labels);
329
+ for (idx_t j = 0; j < nb; j++) {
330
+ bc.add_bcode(bcodes + j * code_size, ids[j]);
331
+ }
332
+ }
333
+ } else if (k == 2) {
334
+ for (; i + BS <= nq; i += BS) {
335
+ BlockSearch<HammingComputer, BS, 2> bc(
336
+ code_size, x, keys + l0 + i, distances, labels);
337
+ for (idx_t j = 0; j < nb; j++) {
338
+ bc.add_bcode(bcodes + j * code_size, ids[j]);
339
+ }
340
+ }
341
+ } else if (k == 4) {
342
+ for (; i + BS <= nq; i += BS) {
343
+ BlockSearch<HammingComputer, BS, 4> bc(
344
+ code_size, x, keys + l0 + i, distances, labels);
345
+ for (idx_t j = 0; j < nb; j++) {
346
+ bc.add_bcode(bcodes + j * code_size, ids[j]);
347
+ }
348
+ }
349
+ } else {
350
+ for (; i + BS <= nq; i += BS) {
351
+ BlockSearchVariableK<HammingComputer, BS> bc(
352
+ code_size,
353
+ static_cast<int>(k),
354
+ x,
355
+ keys + l0 + i,
356
+ distances,
357
+ labels);
358
+ for (idx_t j = 0; j < nb; j++) {
359
+ bc.add_bcode(bcodes + j * code_size, ids[j]);
360
+ }
361
+ }
362
+ }
363
+
364
+ // leftovers
365
+ for (; i < nq; i++) {
366
+ idx_t qno = keys[l0 + i];
367
+ HammingComputer hc(
368
+ x + qno * code_size, static_cast<int>(code_size));
369
+ idx_t* __restrict idxi = labels + qno * k;
370
+ int32_t* __restrict simi = distances + qno * k;
371
+ int32_t simi0 = simi[0];
372
+ for (idx_t j = 0; j < nb; j++) {
373
+ int dis = hc.hamming(bcodes + j * code_size);
374
+
375
+ if (dis < simi0) {
376
+ idx_t id = store_pairs ? lo_build(l, j) : ids[j];
377
+ heap_replace_top<C>(k, simi, idxi, dis, id);
378
+ simi0 = simi[0];
379
+ }
380
+ }
381
+ }
382
+ }
383
+ for (size_t i = 0; i < n; i++) {
384
+ heap_reorder<C>(k, distances + i * k, labels + i * k);
385
+ }
386
+ }
387
+
388
+ } // anonymous namespace
389
+
390
+ // --- Entry points ---
391
+
392
+ template <>
393
+ BinaryInvertedListScanner* make_binary_ivf_scanner_fixSL<THE_SIMD_LEVEL>(
394
+ size_t code_size,
395
+ bool store_pairs) {
396
+ return with_HammingComputer<THE_SIMD_LEVEL>(
397
+ code_size,
398
+ [&]<class HammingComputer>() -> BinaryInvertedListScanner* {
399
+ return new IVFBinaryScannerL2<HammingComputer>(
400
+ code_size, store_pairs);
401
+ });
402
+ }
403
+
404
+ template <>
405
+ void search_knn_hamming_per_invlist_fixSL<THE_SIMD_LEVEL>(
406
+ int code_size,
407
+ const IndexBinaryIVF* ivf,
408
+ size_t n,
409
+ const uint8_t* x,
410
+ idx_t k,
411
+ const idx_t* keys_in,
412
+ const int32_t* coarse_dis,
413
+ int32_t* distances,
414
+ idx_t* labels,
415
+ bool store_pairs,
416
+ const IVFSearchParameters* params) {
417
+ with_HammingComputer<THE_SIMD_LEVEL>(
418
+ code_size, [&]<class HammingComputer>() {
419
+ search_knn_hamming_per_invlist<HammingComputer>(
420
+ ivf,
421
+ n,
422
+ x,
423
+ k,
424
+ keys_in,
425
+ coarse_dis,
426
+ distances,
427
+ labels,
428
+ store_pairs,
429
+ params);
430
+ });
431
+ }
432
+
433
+ template <>
434
+ void search_knn_hamming_count_fixSL<THE_SIMD_LEVEL>(
435
+ int code_size,
436
+ bool store_pairs,
437
+ const IndexBinaryIVF* ivf,
438
+ size_t nx,
439
+ const uint8_t* x,
440
+ const idx_t* keys,
441
+ int k,
442
+ int32_t* distances,
443
+ idx_t* labels,
444
+ const IVFSearchParameters* params) {
445
+ if (store_pairs) {
446
+ with_HammingComputer<THE_SIMD_LEVEL>(
447
+ code_size, [&]<class HammingComputer>() {
448
+ search_knn_hamming_count<HammingComputer, true>(
449
+ ivf, nx, x, keys, k, distances, labels, params);
450
+ });
451
+ } else {
452
+ with_HammingComputer<THE_SIMD_LEVEL>(
453
+ code_size, [&]<class HammingComputer>() {
454
+ search_knn_hamming_count<HammingComputer, false>(
455
+ ivf, nx, x, keys, k, distances, labels, params);
456
+ });
457
+ }
458
+ }
459
+
460
+ } // namespace faiss
@@ -0,0 +1,159 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ /*
9
+ * Per-ISA implementation of Hamming distance computation for
10
+ * IndexIVFSpectralHash. Included once per SIMD TU with THE_SIMD_LEVEL
11
+ * set to the desired SIMDLevel.
12
+ */
13
+
14
+ #pragma once
15
+
16
+ #ifndef THE_SIMD_LEVEL
17
+ #error "THE_SIMD_LEVEL must be defined before including this file"
18
+ #endif
19
+
20
+ #include <faiss/utils/hamming_distance/hamming_computer.h>
21
+
22
+ #include <cmath>
23
+ #include <cstring>
24
+
25
+ #include <faiss/IndexIVFSpectralHash.h>
26
+ #include <faiss/VectorTransform.h>
27
+ #include <faiss/impl/AuxIndexStructures.h>
28
+ #include <faiss/impl/FaissAssert.h>
29
+ #include <faiss/impl/ResultHandler.h>
30
+ #include <faiss/impl/binary_hamming/dispatch.h>
31
+ #include <faiss/utils/hamming.h>
32
+
33
+ namespace faiss {
34
+
35
+ namespace {
36
+
37
+ void binarize_with_freq_impl(
38
+ size_t nbit,
39
+ float freq,
40
+ const float* x,
41
+ const float* c,
42
+ uint8_t* codes) {
43
+ memset(codes, 0, (nbit + 7) / 8);
44
+ for (size_t i = 0; i < nbit; i++) {
45
+ float xf = (x[i] - c[i]);
46
+ int64_t xi = int64_t(std::floor(xf * freq));
47
+ int64_t bit = xi & 1;
48
+ codes[i >> 3] |= bit << (i & 7);
49
+ }
50
+ }
51
+
52
+ template <class HammingComputer>
53
+ struct IVFScanner : InvertedListScanner {
54
+ using InvertedListScanner::scan_codes;
55
+ const IndexIVFSpectralHash* index;
56
+ size_t nbit;
57
+
58
+ float period, freq;
59
+ std::vector<float> q;
60
+ std::vector<float> zero;
61
+ std::vector<uint8_t> qcode;
62
+ HammingComputer hc;
63
+
64
+ IVFScanner(const IndexIVFSpectralHash* index_in, bool store_pairs_in)
65
+ : index(index_in),
66
+ nbit(index_in->nbit),
67
+ period(index_in->period),
68
+ freq(2.0 / index_in->period),
69
+ q(nbit),
70
+ zero(nbit),
71
+ qcode(index_in->code_size),
72
+ hc(qcode.data(), static_cast<int>(index_in->code_size)) {
73
+ this->store_pairs = store_pairs_in;
74
+ this->code_size = index->code_size;
75
+ this->keep_max = is_similarity_metric(index->metric_type);
76
+ }
77
+
78
+ void set_query(const float* query) override {
79
+ FAISS_THROW_IF_NOT(query);
80
+ FAISS_THROW_IF_NOT(q.size() == static_cast<size_t>(nbit));
81
+ index->vt->apply_noalloc(1, query, q.data());
82
+
83
+ if (index->threshold_type == IndexIVFSpectralHash::Thresh_global) {
84
+ binarize_with_freq_impl(
85
+ nbit, freq, q.data(), zero.data(), qcode.data());
86
+ hc.set(qcode.data(), code_size);
87
+ }
88
+ }
89
+
90
+ void set_list(idx_t list_no_in, float /*coarse_dis*/) override {
91
+ this->list_no = list_no_in;
92
+ if (index->threshold_type != IndexIVFSpectralHash::Thresh_global) {
93
+ const float* c = index->trained.data() + list_no_in * nbit;
94
+ binarize_with_freq_impl(nbit, freq, q.data(), c, qcode.data());
95
+ hc.set(qcode.data(), code_size);
96
+ }
97
+ }
98
+
99
+ float distance_to_code(const uint8_t* code) const final {
100
+ return hc.hamming(code);
101
+ }
102
+
103
+ size_t scan_codes(
104
+ size_t list_size,
105
+ const uint8_t* codes,
106
+ const idx_t* ids,
107
+ ResultHandler& handler) const override {
108
+ size_t nup = 0;
109
+ // get_InvertedListScanner asserts no IDSelector, so every code
110
+ // in the list has its distance computed.
111
+ for (size_t j = 0; j < list_size; j++) {
112
+ float dis = hc.hamming(codes);
113
+ handler.stats.scan_cnt++;
114
+
115
+ if (dis < handler.threshold) {
116
+ int64_t id = store_pairs ? lo_build(list_no, j) : ids[j];
117
+ if (handler.add_result(dis, id)) {
118
+ handler.stats.nheap_updates++;
119
+ nup++;
120
+ }
121
+ }
122
+ codes += code_size;
123
+ }
124
+ return nup;
125
+ }
126
+
127
+ void scan_codes_range(
128
+ size_t list_size,
129
+ const uint8_t* codes,
130
+ const idx_t* ids,
131
+ float radius,
132
+ RangeQueryResult& result) const override {
133
+ for (size_t j = 0; j < list_size; j++) {
134
+ float dis = hc.hamming(codes);
135
+ result.stats.scan_cnt++;
136
+ if (dis < radius) {
137
+ int64_t id = store_pairs ? lo_build(list_no, j) : ids[j];
138
+ result.add(dis, id);
139
+ result.stats.nheap_updates++;
140
+ }
141
+ codes += code_size;
142
+ }
143
+ }
144
+ };
145
+
146
+ } // anonymous namespace
147
+
148
+ template <>
149
+ InvertedListScanner* make_spectral_hash_scanner_fixSL<THE_SIMD_LEVEL>(
150
+ int code_size,
151
+ const IndexIVFSpectralHash* index,
152
+ bool store_pairs) {
153
+ return with_HammingComputer<THE_SIMD_LEVEL>(
154
+ code_size, [&]<class HammingComputer>() -> InvertedListScanner* {
155
+ return new IVFScanner<HammingComputer>(index, store_pairs);
156
+ });
157
+ }
158
+
159
+ } // namespace faiss
@@ -0,0 +1,92 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ /*
9
+ * Per-ISA implementation of polysemous Hamming inner loop for IndexPQ.
10
+ * Included once per SIMD TU with THE_SIMD_LEVEL set to the desired
11
+ * SIMDLevel.
12
+ */
13
+
14
+ #pragma once
15
+
16
+ #ifndef THE_SIMD_LEVEL
17
+ #error "THE_SIMD_LEVEL must be defined before including this file"
18
+ #endif
19
+
20
+ #include <faiss/utils/hamming_distance/hamming_computer.h>
21
+
22
+ #include <faiss/IndexPQ.h>
23
+ #include <faiss/impl/binary_hamming/dispatch.h>
24
+ #include <faiss/utils/Heap.h>
25
+ #include <faiss/utils/hamming.h>
26
+
27
+ namespace faiss {
28
+
29
+ namespace {
30
+
31
+ template <class HammingComputer>
32
+ size_t polysemous_inner_loop(
33
+ const IndexPQ* index,
34
+ const float* dis_table_qi,
35
+ const uint8_t* q_code,
36
+ size_t k,
37
+ float* heap_dis,
38
+ int64_t* heap_ids,
39
+ int ht) {
40
+ size_t M = index->pq.M;
41
+ size_t code_size = index->pq.code_size;
42
+ size_t ksub = index->pq.ksub;
43
+ size_t ntotal = index->ntotal;
44
+
45
+ const uint8_t* b_code = index->codes.data();
46
+
47
+ size_t n_pass_i = 0;
48
+
49
+ HammingComputer hc(q_code, static_cast<int>(code_size));
50
+
51
+ for (int64_t bi = 0; bi < static_cast<int64_t>(ntotal); bi++) {
52
+ int hd = hc.hamming(b_code);
53
+
54
+ if (hd < ht) {
55
+ n_pass_i++;
56
+
57
+ float dis = 0;
58
+ const float* dis_table = dis_table_qi;
59
+ for (size_t m = 0; m < M; m++) {
60
+ dis += dis_table[b_code[m]];
61
+ dis_table += ksub;
62
+ }
63
+
64
+ if (dis < heap_dis[0]) {
65
+ maxheap_replace_top(k, heap_dis, heap_ids, dis, bi);
66
+ }
67
+ }
68
+ b_code += code_size;
69
+ }
70
+ return n_pass_i;
71
+ }
72
+
73
+ } // anonymous namespace
74
+
75
+ template <>
76
+ size_t polysemous_inner_loop_fixSL<THE_SIMD_LEVEL>(
77
+ int code_size,
78
+ const IndexPQ* index,
79
+ const float* dis_table_qi,
80
+ const uint8_t* q_code,
81
+ size_t k,
82
+ float* heap_dis,
83
+ int64_t* heap_ids,
84
+ int ht) {
85
+ return with_HammingComputer<THE_SIMD_LEVEL>(
86
+ code_size, [&]<class HammingComputer>() -> size_t {
87
+ return polysemous_inner_loop<HammingComputer>(
88
+ index, dis_table_qi, q_code, k, heap_dis, heap_ids, ht);
89
+ });
90
+ }
91
+
92
+ } // namespace faiss