faiss 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/ext/faiss/extconf.rb +2 -1
  4. data/ext/faiss/{index_rb.cpp → index.cpp} +1 -1
  5. data/ext/faiss/index_binary.cpp +1 -1
  6. data/ext/faiss/kmeans.cpp +1 -1
  7. data/ext/faiss/pca_matrix.cpp +1 -1
  8. data/ext/faiss/product_quantizer.cpp +1 -1
  9. data/ext/faiss/{utils_rb.cpp → utils.cpp} +1 -1
  10. data/lib/faiss/version.rb +1 -1
  11. data/vendor/faiss/faiss/AutoTune.cpp +93 -80
  12. data/vendor/faiss/faiss/Clustering.cpp +39 -240
  13. data/vendor/faiss/faiss/Clustering.h +6 -0
  14. data/vendor/faiss/faiss/IVFlib.cpp +41 -21
  15. data/vendor/faiss/faiss/Index.cpp +6 -5
  16. data/vendor/faiss/faiss/Index.h +5 -5
  17. data/vendor/faiss/faiss/Index2Layer.cpp +37 -53
  18. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +49 -37
  19. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +36 -34
  20. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +4 -1
  21. data/vendor/faiss/faiss/IndexBinary.cpp +5 -3
  22. data/vendor/faiss/faiss/IndexBinary.h +4 -4
  23. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +1 -1
  24. data/vendor/faiss/faiss/IndexBinaryFlat.h +1 -1
  25. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +4 -4
  26. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +84 -92
  27. data/vendor/faiss/faiss/IndexBinaryHNSW.h +9 -3
  28. data/vendor/faiss/faiss/IndexBinaryHash.cpp +45 -236
  29. data/vendor/faiss/faiss/IndexBinaryHash.h +6 -6
  30. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +87 -415
  31. data/vendor/faiss/faiss/IndexFastScan.cpp +72 -109
  32. data/vendor/faiss/faiss/IndexFastScan.h +25 -23
  33. data/vendor/faiss/faiss/IndexFlat.cpp +27 -20
  34. data/vendor/faiss/faiss/IndexFlat.h +21 -18
  35. data/vendor/faiss/faiss/IndexFlatCodes.cpp +42 -19
  36. data/vendor/faiss/faiss/IndexHNSW.cpp +283 -145
  37. data/vendor/faiss/faiss/IndexHNSW.h +16 -2
  38. data/vendor/faiss/faiss/IndexIDMap.cpp +25 -21
  39. data/vendor/faiss/faiss/IndexIDMap.h +9 -7
  40. data/vendor/faiss/faiss/IndexIVF.cpp +465 -362
  41. data/vendor/faiss/faiss/IndexIVF.h +33 -12
  42. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +77 -74
  43. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +96 -93
  44. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +4 -1
  45. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +357 -238
  46. data/vendor/faiss/faiss/IndexIVFFastScan.h +42 -41
  47. data/vendor/faiss/faiss/IndexIVFFlat.cpp +36 -68
  48. data/vendor/faiss/faiss/IndexIVFFlat.h +32 -0
  49. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +53 -30
  50. data/vendor/faiss/faiss/IndexIVFFlatPanorama.h +3 -1
  51. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +18 -15
  52. data/vendor/faiss/faiss/IndexIVFPQ.cpp +71 -843
  53. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +151 -121
  54. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +3 -0
  55. data/vendor/faiss/faiss/IndexIVFPQR.cpp +21 -17
  56. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +26 -39
  57. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +2 -1
  58. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +475 -476
  59. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +248 -93
  60. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +41 -127
  61. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +1 -1
  62. data/vendor/faiss/faiss/IndexLSH.cpp +36 -19
  63. data/vendor/faiss/faiss/IndexLattice.cpp +13 -13
  64. data/vendor/faiss/faiss/IndexNNDescent.cpp +36 -21
  65. data/vendor/faiss/faiss/IndexNNDescent.h +2 -2
  66. data/vendor/faiss/faiss/IndexNSG.cpp +39 -23
  67. data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +31 -11
  68. data/vendor/faiss/faiss/IndexPQ.cpp +128 -221
  69. data/vendor/faiss/faiss/IndexPQ.h +3 -2
  70. data/vendor/faiss/faiss/IndexPQFastScan.cpp +20 -14
  71. data/vendor/faiss/faiss/IndexPQFastScan.h +3 -0
  72. data/vendor/faiss/faiss/IndexPreTransform.cpp +25 -18
  73. data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
  74. data/vendor/faiss/faiss/IndexRaBitQ.cpp +11 -36
  75. data/vendor/faiss/faiss/IndexRaBitQ.h +2 -1
  76. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +41 -277
  77. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +183 -27
  78. data/vendor/faiss/faiss/IndexRefine.cpp +30 -25
  79. data/vendor/faiss/faiss/IndexRefine.h +4 -4
  80. data/vendor/faiss/faiss/IndexReplicas.cpp +6 -6
  81. data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +15 -14
  82. data/vendor/faiss/faiss/IndexRowwiseMinMax.h +1 -1
  83. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +82 -14
  84. data/vendor/faiss/faiss/IndexShards.cpp +10 -9
  85. data/vendor/faiss/faiss/IndexShardsIVF.cpp +21 -15
  86. data/vendor/faiss/faiss/MatrixStats.cpp +5 -4
  87. data/vendor/faiss/faiss/MetaIndexes.cpp +19 -17
  88. data/vendor/faiss/faiss/MetaIndexes.h +1 -1
  89. data/vendor/faiss/faiss/MetricType.h +14 -7
  90. data/vendor/faiss/faiss/SuperKMeans.cpp +656 -0
  91. data/vendor/faiss/faiss/SuperKMeans.h +97 -0
  92. data/vendor/faiss/faiss/VectorTransform.cpp +237 -149
  93. data/vendor/faiss/faiss/VectorTransform.h +16 -16
  94. data/vendor/faiss/faiss/build.cpp +23 -0
  95. data/vendor/faiss/faiss/build.h +15 -0
  96. data/vendor/faiss/faiss/clone_index.cpp +48 -47
  97. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +47 -47
  98. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +11 -0
  99. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +38 -38
  100. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +11 -0
  101. data/vendor/faiss/faiss/factory_tools.cpp +5 -0
  102. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +6 -5
  103. data/vendor/faiss/faiss/gpu/GpuResources.h +1 -1
  104. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +9 -9
  105. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +4 -3
  106. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +46 -0
  107. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +56 -0
  108. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +78 -1
  109. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +72 -0
  110. data/vendor/faiss/faiss/gpu/test/TestUtils.h +23 -0
  111. data/vendor/faiss/faiss/gpu/utils/CuvsFilterConvert.h +1 -1
  112. data/vendor/faiss/faiss/gpu/utils/CuvsUtils.h +21 -10
  113. data/vendor/faiss/faiss/gpu_metal/GpuIndexFlat.h +22 -0
  114. data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +35 -0
  115. data/vendor/faiss/faiss/gpu_metal/MetalFlatKernels.h +40 -0
  116. data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +51 -0
  117. data/vendor/faiss/faiss/gpu_metal/MetalIndexFlat.h +65 -0
  118. data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +66 -0
  119. data/vendor/faiss/faiss/gpu_metal/MetalResources.h +79 -0
  120. data/vendor/faiss/faiss/gpu_metal/StandardMetalResources.h +35 -0
  121. data/vendor/faiss/faiss/impl/AdSampling.cpp +103 -0
  122. data/vendor/faiss/faiss/impl/AdSampling.h +35 -0
  123. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +29 -25
  124. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +1 -0
  125. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +10 -9
  126. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +3 -0
  127. data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +244 -0
  128. data/vendor/faiss/faiss/impl/ClusteringHelpers.h +94 -0
  129. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +16 -16
  130. data/vendor/faiss/faiss/impl/CodePacker.cpp +3 -3
  131. data/vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp +1 -1
  132. data/vendor/faiss/faiss/impl/DistanceComputer.h +8 -8
  133. data/vendor/faiss/faiss/impl/FaissAssert.h +6 -3
  134. data/vendor/faiss/faiss/impl/FaissException.h +50 -3
  135. data/vendor/faiss/faiss/impl/HNSW.cpp +92 -317
  136. data/vendor/faiss/faiss/impl/HNSW.h +13 -34
  137. data/vendor/faiss/faiss/impl/IDSelector.cpp +15 -11
  138. data/vendor/faiss/faiss/impl/IDSelector.h +8 -8
  139. data/vendor/faiss/faiss/impl/InvertedListScannerStats.h +26 -0
  140. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +82 -77
  141. data/vendor/faiss/faiss/impl/NNDescent.cpp +62 -25
  142. data/vendor/faiss/faiss/impl/NNDescent.h +6 -2
  143. data/vendor/faiss/faiss/impl/NSG.cpp +38 -21
  144. data/vendor/faiss/faiss/impl/NSG.h +4 -4
  145. data/vendor/faiss/faiss/impl/Panorama.cpp +23 -6
  146. data/vendor/faiss/faiss/impl/Panorama.h +258 -87
  147. data/vendor/faiss/faiss/impl/PdxLayout.cpp +93 -0
  148. data/vendor/faiss/faiss/impl/PdxLayout.h +41 -0
  149. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +46 -32
  150. data/vendor/faiss/faiss/impl/PolysemousTraining.h +3 -3
  151. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +35 -35
  152. data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +21 -16
  153. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +30 -23
  154. data/vendor/faiss/faiss/impl/Quantizer.h +2 -2
  155. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +55 -49
  156. data/vendor/faiss/faiss/impl/RaBitQUtils.h +65 -0
  157. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +296 -283
  158. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +26 -23
  159. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +1 -1
  160. data/vendor/faiss/faiss/impl/ResultHandler.h +99 -75
  161. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +52 -4
  162. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +27 -1
  163. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +14 -11
  164. data/vendor/faiss/faiss/impl/VisitedTable.h +7 -0
  165. data/vendor/faiss/faiss/impl/approx_topk/approx_topk.h +276 -0
  166. data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +68 -0
  167. data/vendor/faiss/faiss/{utils → impl}/approx_topk/generic.h +15 -8
  168. data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +68 -0
  169. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab-inl.h +169 -0
  170. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab.h +117 -0
  171. data/vendor/faiss/faiss/impl/approx_topk/simdlib256-inl.h +146 -0
  172. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHNSW_impl.h +73 -0
  173. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +270 -0
  174. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +460 -0
  175. data/vendor/faiss/faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h +159 -0
  176. data/vendor/faiss/faiss/impl/binary_hamming/IndexPQ_impl.h +92 -0
  177. data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +26 -0
  178. data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +26 -0
  179. data/vendor/faiss/faiss/impl/binary_hamming/dispatch.h +143 -0
  180. data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +26 -0
  181. data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +26 -0
  182. data/vendor/faiss/faiss/impl/expanded_scanners.h +8 -3
  183. data/vendor/faiss/faiss/impl/{FastScanDistancePostProcessing.h → fast_scan/FastScanDistancePostProcessing.h} +13 -6
  184. data/vendor/faiss/faiss/impl/{LookupTableScaler.h → fast_scan/LookupTableScaler.h} +16 -5
  185. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +237 -0
  186. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +185 -0
  187. data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +229 -0
  188. data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +268 -0
  189. data/vendor/faiss/faiss/impl/{pq4_fast_scan.cpp → fast_scan/fast_scan.cpp} +169 -2
  190. data/vendor/faiss/faiss/impl/fast_scan/fast_scan.h +341 -0
  191. data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +36 -0
  192. data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +40 -0
  193. data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +120 -0
  194. data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +104 -0
  195. data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +213 -0
  196. data/vendor/faiss/faiss/impl/{pq4_fast_scan_search_qbs.cpp → fast_scan/kernels_simd512.h} +26 -356
  197. data/vendor/faiss/faiss/impl/fast_scan/rabitq_dispatching.h +90 -0
  198. data/vendor/faiss/faiss/impl/fast_scan/rabitq_result_handler.h +108 -0
  199. data/vendor/faiss/faiss/impl/{simd_result_handlers.h → fast_scan/simd_result_handlers.h} +282 -134
  200. data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +54 -0
  201. data/vendor/faiss/faiss/impl/hnsw/LockVector.h +64 -0
  202. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +91 -0
  203. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +64 -0
  204. data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +104 -0
  205. data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +111 -0
  206. data/vendor/faiss/faiss/impl/index_read.cpp +1132 -45
  207. data/vendor/faiss/faiss/impl/index_read_utils.h +1 -1
  208. data/vendor/faiss/faiss/impl/index_write.cpp +95 -13
  209. data/vendor/faiss/faiss/impl/io.cpp +6 -6
  210. data/vendor/faiss/faiss/impl/io_macros.h +33 -16
  211. data/vendor/faiss/faiss/impl/kmeans1d.cpp +10 -10
  212. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +37 -23
  213. data/vendor/faiss/faiss/impl/lattice_Zn.h +6 -6
  214. data/vendor/faiss/faiss/impl/mapped_io.cpp +6 -6
  215. data/vendor/faiss/faiss/impl/platform_macros.h +11 -4
  216. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +549 -0
  217. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +245 -0
  218. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.h +105 -0
  219. data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +106 -0
  220. data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +21 -0
  221. data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +21 -0
  222. data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +21 -0
  223. data/vendor/faiss/faiss/impl/pq_code_distance/{pq_code_distance-avx2.cpp → pq_code_distance-avx2.h} +9 -13
  224. data/vendor/faiss/faiss/impl/pq_code_distance/{pq_code_distance-avx512.cpp → pq_code_distance-avx512.h} +9 -57
  225. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +29 -111
  226. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +96 -0
  227. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +238 -5
  228. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +5 -7
  229. data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +68 -0
  230. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +311 -477
  231. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
  232. data/vendor/faiss/faiss/impl/scalar_quantizer/codecs.h +1 -1
  233. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +3 -2
  234. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +102 -11
  235. data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +27 -1
  236. data/vendor/faiss/faiss/impl/scalar_quantizer/similarities.h +3 -3
  237. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +148 -0
  238. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +167 -0
  239. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +59 -0
  240. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +163 -0
  241. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +311 -0
  242. data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +192 -8
  243. data/vendor/faiss/faiss/impl/scalar_quantizer/training.h +12 -0
  244. data/vendor/faiss/faiss/impl/simd_dispatch.h +100 -66
  245. data/vendor/faiss/faiss/impl/simdlib/simdlib.h +57 -0
  246. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_avx2.h +264 -172
  247. data/vendor/faiss/faiss/impl/simdlib/simdlib_avx512.h +414 -0
  248. data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +44 -0
  249. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_emulated.h +231 -166
  250. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_neon.h +270 -218
  251. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_ppc64.h +201 -160
  252. data/vendor/faiss/faiss/impl/svs_io.cpp +12 -3
  253. data/vendor/faiss/faiss/impl/svs_io.h +8 -2
  254. data/vendor/faiss/faiss/index_factory.cpp +86 -18
  255. data/vendor/faiss/faiss/index_io.h +24 -0
  256. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +66 -16
  257. data/vendor/faiss/faiss/invlists/DirectMap.cpp +24 -14
  258. data/vendor/faiss/faiss/invlists/DirectMap.h +4 -3
  259. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +157 -73
  260. data/vendor/faiss/faiss/invlists/InvertedLists.h +86 -23
  261. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +4 -4
  262. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +13 -13
  263. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
  264. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +1 -1
  265. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +2 -2
  266. data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +350 -0
  267. data/vendor/faiss/faiss/svs/IndexSVSIVF.h +128 -0
  268. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.cpp +40 -0
  269. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.h +43 -0
  270. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +225 -0
  271. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.h +71 -0
  272. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +25 -1
  273. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +18 -2
  274. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +1 -1
  275. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +12 -3
  276. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +7 -2
  277. data/vendor/faiss/faiss/utils/Heap.cpp +10 -10
  278. data/vendor/faiss/faiss/utils/NeuralNet.cpp +47 -36
  279. data/vendor/faiss/faiss/utils/NeuralNet.h +1 -1
  280. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +10 -4
  281. data/vendor/faiss/faiss/utils/distances.cpp +390 -560
  282. data/vendor/faiss/faiss/utils/distances.h +20 -1
  283. data/vendor/faiss/faiss/utils/distances_dispatch.h +117 -37
  284. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +8 -7
  285. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +33 -14
  286. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +12 -1
  287. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +16 -293
  288. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +57 -0
  289. data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +290 -0
  290. data/vendor/faiss/faiss/utils/distances_simd.cpp +5 -177
  291. data/vendor/faiss/faiss/utils/extra_distances.cpp +9 -8
  292. data/vendor/faiss/faiss/utils/extra_distances.h +32 -6
  293. data/vendor/faiss/faiss/utils/hamming-inl.h +13 -11
  294. data/vendor/faiss/faiss/utils/hamming.cpp +66 -517
  295. data/vendor/faiss/faiss/utils/hamming.h +92 -2
  296. data/vendor/faiss/faiss/utils/hamming_distance/common.h +287 -10
  297. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +15 -0
  298. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +15 -0
  299. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx2.h +142 -0
  300. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +234 -0
  301. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-generic.h +368 -0
  302. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-neon.h +322 -0
  303. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-rvv.h +39 -0
  304. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer.h +146 -0
  305. data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +481 -0
  306. data/vendor/faiss/faiss/utils/hamming_distance/hamming_neon.cpp +15 -0
  307. data/vendor/faiss/faiss/utils/hamming_distance/hamming_rvv.cpp +15 -0
  308. data/vendor/faiss/faiss/utils/partitioning.cpp +66 -987
  309. data/vendor/faiss/faiss/utils/partitioning.h +31 -0
  310. data/vendor/faiss/faiss/utils/popcount.h +29 -0
  311. data/vendor/faiss/faiss/utils/pq_code_distance.h +2 -2
  312. data/vendor/faiss/faiss/utils/prefetch.h +2 -2
  313. data/vendor/faiss/faiss/utils/quantize_lut.cpp +30 -30
  314. data/vendor/faiss/faiss/utils/quantize_lut.h +1 -1
  315. data/vendor/faiss/faiss/utils/rabitq_simd.h +57 -536
  316. data/vendor/faiss/faiss/utils/random.cpp +6 -6
  317. data/vendor/faiss/faiss/utils/simd_impl/IVFFlatScanner-inl.h +51 -0
  318. data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +5 -1
  319. data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +213 -4
  320. data/vendor/faiss/faiss/utils/simd_impl/distances_autovec-inl.h +163 -10
  321. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +250 -4
  322. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +7 -4
  323. data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +189 -0
  324. data/vendor/faiss/faiss/utils/simd_impl/distances_simdlib256.h +195 -0
  325. data/vendor/faiss/faiss/utils/simd_impl/distances_sse-inl.h +2 -1
  326. data/vendor/faiss/faiss/utils/{distances_fused/simdlib_based.h → simd_impl/exhaustive_L2sqr_blas_cmax.h} +5 -10
  327. data/vendor/faiss/faiss/utils/simd_impl/hamming_impl.h +481 -0
  328. data/vendor/faiss/faiss/utils/simd_impl/partitioning_avx2.cpp +14 -0
  329. data/vendor/faiss/faiss/utils/simd_impl/partitioning_neon.cpp +14 -0
  330. data/vendor/faiss/faiss/utils/simd_impl/partitioning_simdlib256.h +1085 -0
  331. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +355 -0
  332. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +477 -0
  333. data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +55 -0
  334. data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +55 -0
  335. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_dispatch.h +32 -0
  336. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +43 -0
  337. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +57 -0
  338. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +45 -0
  339. data/vendor/faiss/faiss/utils/simd_levels.cpp +17 -5
  340. data/vendor/faiss/faiss/utils/simd_levels.h +93 -1
  341. data/vendor/faiss/faiss/utils/sorting.cpp +48 -36
  342. data/vendor/faiss/faiss/utils/utils.cpp +5 -5
  343. data/vendor/faiss/faiss/utils/utils.h +3 -3
  344. metadata +119 -34
  345. data/vendor/faiss/faiss/impl/RaBitQStats.cpp +0 -29
  346. data/vendor/faiss/faiss/impl/RaBitQStats.h +0 -56
  347. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +0 -224
  348. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +0 -230
  349. data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +0 -84
  350. data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +0 -196
  351. data/vendor/faiss/faiss/utils/approx_topk/mode.h +0 -34
  352. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +0 -36
  353. data/vendor/faiss/faiss/utils/extra_distances-inl.h +0 -235
  354. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +0 -462
  355. data/vendor/faiss/faiss/utils/hamming_distance/avx512-inl.h +0 -490
  356. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +0 -449
  357. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +0 -87
  358. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +0 -524
  359. data/vendor/faiss/faiss/utils/simdlib.h +0 -42
  360. data/vendor/faiss/faiss/utils/simdlib_avx512.h +0 -365
  361. /data/ext/faiss/{utils_rb.h → utils.h} +0 -0
@@ -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