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
@@ -29,7 +29,7 @@ struct ZnSphereSearch {
29
29
  /// size dim * natom
30
30
  std::vector<float> voc;
31
31
 
32
- ZnSphereSearch(int dim, int r2);
32
+ ZnSphereSearch(int dim, int r2_in);
33
33
 
34
34
  /// find nearest centroid. x does not need to be normalized
35
35
  float search(const float* x, float* c) const;
@@ -57,7 +57,7 @@ struct EnumeratedVectors {
57
57
  uint64_t nv;
58
58
  int dim;
59
59
 
60
- explicit EnumeratedVectors(int dim) : nv(0), dim(dim) {}
60
+ explicit EnumeratedVectors(int dim_in) : nv(0), dim(dim_in) {}
61
61
 
62
62
  /// encode a vector from a collection
63
63
  virtual uint64_t encode(const float* x) const = 0;
@@ -98,7 +98,7 @@ struct Repeats {
98
98
  std::vector<Repeat> repeats;
99
99
 
100
100
  // initialize from a template of the atom.
101
- Repeats(int dim = 0, const float* c = nullptr);
101
+ Repeats(int dim_in = 0, const float* c = nullptr);
102
102
 
103
103
  // count number of possible codes for this atom
104
104
  uint64_t count() const;
@@ -124,7 +124,7 @@ struct ZnSphereCodec : ZnSphereSearch, EnumeratedVectors {
124
124
  uint64_t nv;
125
125
  size_t code_size;
126
126
 
127
- ZnSphereCodec(int dim, int r2);
127
+ ZnSphereCodec(int dim_in, int r2_in);
128
128
 
129
129
  uint64_t search_and_encode(const float* x) const;
130
130
 
@@ -146,7 +146,7 @@ struct ZnSphereCodecRec : EnumeratedVectors {
146
146
  int log2_dim;
147
147
  int code_size;
148
148
 
149
- ZnSphereCodecRec(int dim, int r2);
149
+ ZnSphereCodecRec(int dim_in, int r2_in);
150
150
 
151
151
  uint64_t encode_centroid(const float* c) const;
152
152
 
@@ -176,7 +176,7 @@ struct ZnSphereCodecAlt : ZnSphereCodec {
176
176
  bool use_rec;
177
177
  ZnSphereCodecRec znc_rec;
178
178
 
179
- ZnSphereCodecAlt(int dim, int r2);
179
+ ZnSphereCodecAlt(int dim_in, int r2_in);
180
180
 
181
181
  uint64_t encode(const float* x) const override;
182
182
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  #include <stdio.h>
9
9
 
10
- #if defined(__linux__) || defined(__FreeBSD__)
10
+ #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
11
11
 
12
12
  #include <fcntl.h>
13
13
  #include <sys/mman.h>
@@ -27,15 +27,22 @@
27
27
 
28
28
  namespace faiss {
29
29
 
30
- #if defined(__linux__) || defined(__FreeBSD__)
30
+ #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
31
31
 
32
32
  struct MmappedFileMappingOwner::PImpl {
33
33
  void* ptr = nullptr;
34
34
  size_t ptr_size = 0;
35
35
 
36
36
  explicit PImpl(const std::string& filename) {
37
- auto f = std::unique_ptr<FILE, decltype(&fclose)>(
38
- fopen(filename.c_str(), "r"), &fclose);
37
+ struct FileDeleter {
38
+ void operator()(FILE* f) const {
39
+ if (f)
40
+ fclose(f);
41
+ }
42
+ };
43
+
44
+ auto f = std::unique_ptr<FILE, FileDeleter>(
45
+ fopen(filename.c_str(), "r"), FileDeleter{});
39
46
  FAISS_THROW_IF_NOT_FMT(
40
47
  f.get(),
41
48
  "could not open %s for reading: %s",
@@ -53,11 +60,11 @@ struct MmappedFileMappingOwner::PImpl {
53
60
  void* address = mmap(
54
61
  nullptr, filesize, PROT_READ, MAP_SHARED, fileno(f.get()), 0);
55
62
  FAISS_THROW_IF_NOT_FMT(
56
- address != nullptr, "could not mmap(): %s", strerror(errno));
63
+ address != MAP_FAILED, "could not mmap(): %s", strerror(errno));
57
64
 
58
65
  // btw, fd can be closed here
59
66
 
60
- madvise(address, filesize, MADV_RANDOM);
67
+ (void)madvise(address, filesize, MADV_RANDOM);
61
68
 
62
69
  // save it
63
70
  ptr = address;
@@ -76,11 +83,11 @@ struct MmappedFileMappingOwner::PImpl {
76
83
  void* address =
77
84
  mmap(nullptr, filesize, PROT_READ, MAP_SHARED, fileno(f), 0);
78
85
  FAISS_THROW_IF_NOT_FMT(
79
- address != nullptr, "could not mmap(): %s", strerror(errno));
86
+ address != MAP_FAILED, "could not mmap(): %s", strerror(errno));
80
87
 
81
88
  // btw, fd can be closed here
82
89
 
83
- madvise(address, filesize, MADV_RANDOM);
90
+ (void)madvise(address, filesize, MADV_RANDOM);
84
91
 
85
92
  // save it
86
93
  ptr = address;
@@ -74,10 +74,6 @@ inline int __builtin_clzll(uint64_t x) {
74
74
  }
75
75
  #endif
76
76
 
77
- #define __builtin_popcount __popcnt
78
- #define __builtin_popcountl __popcnt64
79
- #define __builtin_popcountll __popcnt64
80
-
81
77
  #ifndef __clang__
82
78
  #define __m128i_u __m128i
83
79
  #define __m256i_u __m256i
@@ -110,9 +106,16 @@ inline int __builtin_clzll(uint64_t x) {
110
106
  // MSVC uses pragma pack instead of __attribute__((packed))
111
107
  // Use FAISS_PACK_STRUCTS_BEGIN/END to wrap packed structure definitions
112
108
  #define FAISS_PACKED
109
+ #define FAISS_RESTRICT __restrict
113
110
  #define FAISS_PACK_STRUCTS_BEGIN __pragma(pack(push, 1))
114
111
  #define FAISS_PACK_STRUCTS_END __pragma(pack(pop))
115
112
 
113
+ #ifdef SWIG
114
+ #define FAISS_MAYBE_UNUSED
115
+ #else
116
+ #define FAISS_MAYBE_UNUSED [[maybe_unused]]
117
+ #endif
118
+
116
119
  #else
117
120
  /*******************************************************
118
121
  * Linux and OSX
@@ -126,9 +129,13 @@ inline int __builtin_clzll(uint64_t x) {
126
129
  #ifdef SWIG
127
130
  #define ALIGNED(x)
128
131
  #define FAISS_PACKED
132
+ #define FAISS_RESTRICT
133
+ #define FAISS_MAYBE_UNUSED
129
134
  #else
130
135
  #define ALIGNED(x) __attribute__((aligned(x)))
131
136
  #define FAISS_PACKED __attribute__((packed))
137
+ #define FAISS_RESTRICT __restrict
138
+ #define FAISS_MAYBE_UNUSED [[maybe_unused]]
132
139
  #endif
133
140
 
134
141
  // On non-Windows, FAISS_PACKED handles packing, so these are no-ops
@@ -0,0 +1,549 @@
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
+ #pragma once
9
+
10
+ #ifndef THE_SIMD_LEVEL
11
+ #error "THE_SIMD_LEVEL must be defined before including IVFPQScanner_impl.h"
12
+ #endif
13
+
14
+ #include <faiss/IndexIVFPQ.h>
15
+ #include <faiss/impl/IDSelector.h>
16
+ #include <faiss/impl/ResultHandler.h>
17
+ #include <faiss/impl/pq_code_distance/IVFPQ_QueryTables.h>
18
+ #include <faiss/impl/pq_code_distance/pq_code_distance-inl.h>
19
+ #include <faiss/impl/simd_dispatch.h>
20
+ #include <faiss/invlists/DirectMap.h>
21
+ #include <faiss/utils/distances_dispatch.h>
22
+ #include <faiss/utils/hamming.h>
23
+
24
+ namespace faiss {
25
+ namespace pq_code_distance {
26
+
27
+ template <class C, bool use_sel>
28
+ struct WrappedSearchResult {
29
+ ResultHandler& res;
30
+ size_t nup = 0;
31
+ idx_t list_no;
32
+
33
+ const idx_t* ids;
34
+ const IDSelector* sel;
35
+
36
+ WrappedSearchResult(
37
+ idx_t list_no_in,
38
+ const idx_t* ids_in,
39
+ const IDSelector* sel_in,
40
+ ResultHandler& res_in)
41
+ : res(res_in), list_no(list_no_in), ids(ids_in), sel(sel_in) {}
42
+
43
+ inline bool skip_entry(idx_t j) {
44
+ return use_sel && !sel->is_member(ids[j]);
45
+ }
46
+
47
+ inline void add(idx_t j, float dis) {
48
+ // Reached only for codes that passed skip_entry — i.e. distance
49
+ // was actually computed for this code (post-filter).
50
+ res.stats.scan_cnt++;
51
+ if (C::cmp(res.threshold, dis)) {
52
+ idx_t id = ids ? ids[j] : lo_build(this->list_no, j);
53
+ if (res.add_result(dis, id)) {
54
+ res.stats.nheap_updates++;
55
+ nup++;
56
+ }
57
+ }
58
+ }
59
+ };
60
+
61
+ /*****************************************************
62
+ * Scaning the codes.
63
+ * The scanning functions call their favorite precompute_*
64
+ * function to precompute the tables they need.
65
+ *****************************************************/
66
+ template <typename IDType, MetricType METRIC_TYPE, class PQCodeDist>
67
+ struct IVFPQScannerT : QueryTables {
68
+ using PQDecoder = typename PQCodeDist::PQDecoder;
69
+ const uint8_t* list_codes = nullptr;
70
+ const IDType* list_ids;
71
+ size_t list_size = 0;
72
+
73
+ IVFPQScannerT(
74
+ const IndexIVFPQ& ivfpq_in,
75
+ const IVFSearchParameters* params_in)
76
+ : QueryTables(ivfpq_in, params_in) {
77
+ FAISS_THROW_IF_NOT(METRIC_TYPE == metric_type);
78
+ }
79
+
80
+ /*****************************************************
81
+ * Scaning the codes: simple PQ scan.
82
+ *****************************************************/
83
+
84
+ // This is the baseline version of scan_list_with_tables().
85
+ // It demonstrates what this function actually does.
86
+ //
87
+ // /// version of the scan where we use precomputed tables.
88
+ // template <class SearchResultType>
89
+ // void scan_list_with_table(
90
+ // size_t ncode,
91
+ // const uint8_t* codes,
92
+ // SearchResultType& res) const {
93
+ //
94
+ // for (size_t j = 0; j < ncode; j++, codes += pq.code_size) {
95
+ // if (res.skip_entry(j)) {
96
+ // continue;
97
+ // }
98
+ // float dis = dis0 + PQCodeDist::distance_single_code(
99
+ // pq, sim_table, codes);
100
+ // res.add(j, dis);
101
+ // }
102
+ // }
103
+
104
+ // This is the modified version of scan_list_with_tables().
105
+ // It was observed that doing manual unrolling of the loop that
106
+ // utilizes distance_single_code() speeds up the computations.
107
+
108
+ /// version of the scan where we use precomputed tables.
109
+ template <class SearchResultType>
110
+ void scan_list_with_table(
111
+ size_t ncode,
112
+ const uint8_t* codes,
113
+ SearchResultType& res) const {
114
+ int counter = 0;
115
+
116
+ size_t saved_j[4] = {0, 0, 0, 0};
117
+ for (size_t j = 0; j < ncode; j++) {
118
+ if (res.skip_entry(j)) {
119
+ continue;
120
+ }
121
+
122
+ saved_j[0] = (counter == 0) ? j : saved_j[0];
123
+ saved_j[1] = (counter == 1) ? j : saved_j[1];
124
+ saved_j[2] = (counter == 2) ? j : saved_j[2];
125
+ saved_j[3] = (counter == 3) ? j : saved_j[3];
126
+
127
+ counter += 1;
128
+ if (counter == 4) {
129
+ float distance_0 = 0;
130
+ float distance_1 = 0;
131
+ float distance_2 = 0;
132
+ float distance_3 = 0;
133
+ PQCodeDist::distance_four_codes(
134
+ pq.M,
135
+ pq.nbits,
136
+ sim_table,
137
+ codes + saved_j[0] * pq.code_size,
138
+ codes + saved_j[1] * pq.code_size,
139
+ codes + saved_j[2] * pq.code_size,
140
+ codes + saved_j[3] * pq.code_size,
141
+ distance_0,
142
+ distance_1,
143
+ distance_2,
144
+ distance_3);
145
+
146
+ res.add(saved_j[0], dis0 + distance_0);
147
+ res.add(saved_j[1], dis0 + distance_1);
148
+ res.add(saved_j[2], dis0 + distance_2);
149
+ res.add(saved_j[3], dis0 + distance_3);
150
+ counter = 0;
151
+ }
152
+ }
153
+
154
+ if (counter >= 1) {
155
+ float dis = dis0 +
156
+ PQCodeDist::distance_single_code(
157
+ pq.M,
158
+ pq.nbits,
159
+ sim_table,
160
+ codes + saved_j[0] * pq.code_size);
161
+ res.add(saved_j[0], dis);
162
+ }
163
+ if (counter >= 2) {
164
+ float dis = dis0 +
165
+ PQCodeDist::distance_single_code(
166
+ pq.M,
167
+ pq.nbits,
168
+ sim_table,
169
+ codes + saved_j[1] * pq.code_size);
170
+ res.add(saved_j[1], dis);
171
+ }
172
+ if (counter >= 3) {
173
+ float dis = dis0 +
174
+ PQCodeDist::distance_single_code(
175
+ pq.M,
176
+ pq.nbits,
177
+ sim_table,
178
+ codes + saved_j[2] * pq.code_size);
179
+ res.add(saved_j[2], dis);
180
+ }
181
+ }
182
+
183
+ /// tables are not precomputed, but pointers are provided to the
184
+ /// relevant X_c|x_r tables
185
+ template <class SearchResultType>
186
+ void scan_list_with_pointer(
187
+ size_t ncode,
188
+ const uint8_t* codes,
189
+ SearchResultType& res) const {
190
+ for (size_t j = 0; j < ncode; j++, codes += pq.code_size) {
191
+ if (res.skip_entry(j)) {
192
+ continue;
193
+ }
194
+ PQDecoder decoder(codes, pq.nbits);
195
+ float dis = dis0;
196
+ const float* tab = sim_table_2;
197
+
198
+ for (size_t m = 0; m < pq.M; m++) {
199
+ int ci = decoder.decode();
200
+ dis += sim_table_ptrs[m][ci] - 2 * tab[ci];
201
+ tab += pq.ksub;
202
+ }
203
+ res.add(j, dis);
204
+ }
205
+ }
206
+
207
+ /// nothing is precomputed: access residuals on-the-fly
208
+ template <class SearchResultType>
209
+ void scan_on_the_fly_dist(
210
+ size_t ncode,
211
+ const uint8_t* codes,
212
+ SearchResultType& res) const {
213
+ const float* dvec;
214
+ float local_dis0 = 0;
215
+ if (by_residual) {
216
+ if (METRIC_TYPE == METRIC_INNER_PRODUCT) {
217
+ ivfpq.quantizer->reconstruct(key, residual_vec);
218
+ local_dis0 = fvec_inner_product_dispatch(residual_vec, qi, d);
219
+ } else {
220
+ ivfpq.quantizer->compute_residual(qi, residual_vec, key);
221
+ }
222
+ dvec = residual_vec;
223
+ } else {
224
+ dvec = qi;
225
+ local_dis0 = 0;
226
+ }
227
+
228
+ for (size_t j = 0; j < ncode; j++, codes += pq.code_size) {
229
+ if (res.skip_entry(j)) {
230
+ continue;
231
+ }
232
+ pq.decode(codes, decoded_vec);
233
+
234
+ float dis;
235
+ if (METRIC_TYPE == METRIC_INNER_PRODUCT) {
236
+ dis = local_dis0 +
237
+ fvec_inner_product_dispatch(decoded_vec, qi, d);
238
+ } else {
239
+ dis = fvec_L2sqr_dispatch(decoded_vec, dvec, d);
240
+ }
241
+ res.add(j, dis);
242
+ }
243
+ }
244
+
245
+ /*****************************************************
246
+ * Scanning codes with polysemous filtering
247
+ *****************************************************/
248
+
249
+ // This is the baseline version of scan_list_polysemous_hc().
250
+ // It demonstrates what this function actually does.
251
+
252
+ // template <class HammingComputer, class SearchResultType>
253
+ // void scan_list_polysemous_hc(
254
+ // size_t ncode,
255
+ // const uint8_t* codes,
256
+ // SearchResultType& res) const {
257
+ // int ht = ivfpq.polysemous_ht;
258
+ // size_t n_hamming_pass = 0, nup = 0;
259
+ //
260
+ // int code_size = pq.code_size;
261
+ //
262
+ // HammingComputer hc(q_code.data(), code_size);
263
+ //
264
+ // for (size_t j = 0; j < ncode; j++, codes += code_size) {
265
+ // if (res.skip_entry(j)) {
266
+ // continue;
267
+ // }
268
+ // const uint8_t* b_code = codes;
269
+ // int hd = hc.hamming(b_code);
270
+ // if (hd < ht) {
271
+ // n_hamming_pass++;
272
+ //
273
+ // float dis =
274
+ // dis0 +
275
+ // PQCodeDist::distance_single_code(
276
+ // pq, sim_table, codes);
277
+ //
278
+ // res.add(j, dis);
279
+ // }
280
+ // }
281
+ // #pragma omp critical
282
+ // { indexIVFPQ_stats.n_hamming_pass += n_hamming_pass; }
283
+ // }
284
+
285
+ // This is the modified version of scan_list_with_tables().
286
+ // It was observed that doing manual unrolling of the loop that
287
+ // utilizes distance_single_code() speeds up the computations.
288
+
289
+ template <class HammingComputer, class SearchResultType>
290
+ void scan_list_polysemous_hc(
291
+ size_t ncode,
292
+ const uint8_t* codes,
293
+ SearchResultType& res) const {
294
+ int ht = ivfpq.polysemous_ht;
295
+ size_t n_hamming_pass = 0;
296
+
297
+ int code_size = static_cast<int>(pq.code_size);
298
+
299
+ size_t saved_j[8];
300
+ int counter = 0;
301
+
302
+ HammingComputer hc(q_code.data(), code_size);
303
+
304
+ for (size_t j = 0; j < (ncode / 4) * 4; j += 4) {
305
+ const uint8_t* b_code = codes + j * code_size;
306
+
307
+ // Unrolling is a key. Basically, doing multiple popcount
308
+ // operations one after another speeds things up.
309
+
310
+ // 9999999 is just an arbitrary large number
311
+ int hd0 = (res.skip_entry(j + 0))
312
+ ? 99999999
313
+ : hc.hamming(b_code + 0 * code_size);
314
+ int hd1 = (res.skip_entry(j + 1))
315
+ ? 99999999
316
+ : hc.hamming(b_code + 1 * code_size);
317
+ int hd2 = (res.skip_entry(j + 2))
318
+ ? 99999999
319
+ : hc.hamming(b_code + 2 * code_size);
320
+ int hd3 = (res.skip_entry(j + 3))
321
+ ? 99999999
322
+ : hc.hamming(b_code + 3 * code_size);
323
+
324
+ saved_j[counter] = j + 0;
325
+ counter = (hd0 < ht) ? (counter + 1) : counter;
326
+ saved_j[counter] = j + 1;
327
+ counter = (hd1 < ht) ? (counter + 1) : counter;
328
+ saved_j[counter] = j + 2;
329
+ counter = (hd2 < ht) ? (counter + 1) : counter;
330
+ saved_j[counter] = j + 3;
331
+ counter = (hd3 < ht) ? (counter + 1) : counter;
332
+
333
+ if (counter >= 4) {
334
+ // process four codes at the same time
335
+ n_hamming_pass += 4;
336
+
337
+ float distance_0 = dis0;
338
+ float distance_1 = dis0;
339
+ float distance_2 = dis0;
340
+ float distance_3 = dis0;
341
+ PQCodeDist::distance_four_codes(
342
+ pq.M,
343
+ pq.nbits,
344
+ sim_table,
345
+ codes + saved_j[0] * pq.code_size,
346
+ codes + saved_j[1] * pq.code_size,
347
+ codes + saved_j[2] * pq.code_size,
348
+ codes + saved_j[3] * pq.code_size,
349
+ distance_0,
350
+ distance_1,
351
+ distance_2,
352
+ distance_3);
353
+
354
+ res.add(saved_j[0], dis0 + distance_0);
355
+ res.add(saved_j[1], dis0 + distance_1);
356
+ res.add(saved_j[2], dis0 + distance_2);
357
+ res.add(saved_j[3], dis0 + distance_3);
358
+
359
+ //
360
+ counter -= 4;
361
+ saved_j[0] = saved_j[4];
362
+ saved_j[1] = saved_j[5];
363
+ saved_j[2] = saved_j[6];
364
+ saved_j[3] = saved_j[7];
365
+ }
366
+ }
367
+
368
+ for (int kk = 0; kk < counter; kk++) {
369
+ n_hamming_pass++;
370
+
371
+ float dis = dis0 +
372
+ PQCodeDist::distance_single_code(
373
+ pq.M,
374
+ pq.nbits,
375
+ sim_table,
376
+ codes + saved_j[kk] * pq.code_size);
377
+
378
+ res.add(saved_j[kk], dis);
379
+ }
380
+
381
+ // process leftovers
382
+ for (size_t j = (ncode / 4) * 4; j < ncode; j++) {
383
+ if (res.skip_entry(j)) {
384
+ continue;
385
+ }
386
+ const uint8_t* b_code = codes + j * code_size;
387
+ int hd = hc.hamming(b_code);
388
+ if (hd < ht) {
389
+ n_hamming_pass++;
390
+
391
+ float dis = dis0 +
392
+ PQCodeDist::distance_single_code(
393
+ pq.M,
394
+ pq.nbits,
395
+ sim_table,
396
+ codes + j * code_size);
397
+
398
+ res.add(j, dis);
399
+ }
400
+ }
401
+
402
+ #pragma omp critical
403
+ {
404
+ indexIVFPQ_stats.n_hamming_pass += n_hamming_pass;
405
+ }
406
+ }
407
+
408
+ template <class SearchResultType>
409
+ void scan_list_polysemous(
410
+ size_t ncode,
411
+ const uint8_t* codes,
412
+ SearchResultType& res) const {
413
+ with_HammingComputer<PQCodeDist::simd_level>(
414
+ pq.code_size, [&]<class HammingComputer>() {
415
+ this->scan_list_polysemous_hc<
416
+ HammingComputer,
417
+ SearchResultType>(ncode, codes, res);
418
+ });
419
+ }
420
+ };
421
+
422
+ /* We put as many parameters as possible in template. Hopefully the
423
+ * gain in runtime is worth the code bloat.
424
+ *
425
+ * C is the comparator < or >, it is directly related to METRIC_TYPE.
426
+ *
427
+ * precompute_mode is how much we precompute (2 = precompute distance tables,
428
+ * 1 = precompute pointers to distances, 0 = compute distances one by one).
429
+ * Currently only 2 is supported
430
+ *
431
+ * use_sel: store or ignore the IDSelector
432
+ */
433
+ template <MetricType METRIC_TYPE, class C, class PQCodeDist, bool use_sel>
434
+ struct IVFPQScanner : IVFPQScannerT<idx_t, METRIC_TYPE, PQCodeDist>,
435
+ InvertedListScanner {
436
+ using InvertedListScanner::scan_codes;
437
+ int precompute_mode;
438
+ const IDSelector* sel;
439
+
440
+ IVFPQScanner(
441
+ const IndexIVFPQ& ivfpq_in,
442
+ bool store_pairs_in,
443
+ int precompute_mode_in,
444
+ const IDSelector* sel_in)
445
+ : IVFPQScannerT<idx_t, METRIC_TYPE, PQCodeDist>(ivfpq_in, nullptr),
446
+ precompute_mode(precompute_mode_in),
447
+ sel(sel_in) {
448
+ this->store_pairs = store_pairs_in;
449
+ this->keep_max = is_similarity_metric(METRIC_TYPE);
450
+ this->code_size = this->pq.code_size;
451
+ }
452
+
453
+ void set_query(const float* query) override {
454
+ this->init_query(query);
455
+ }
456
+
457
+ void set_list(idx_t list_no_in, float coarse_dis_in) override {
458
+ this->list_no = list_no_in;
459
+ this->init_list(list_no_in, coarse_dis_in, precompute_mode);
460
+ }
461
+
462
+ float distance_to_code(const uint8_t* code) const override {
463
+ FAISS_THROW_IF_NOT(precompute_mode == 2);
464
+ float dis = this->dis0 +
465
+ PQCodeDist::distance_single_code(
466
+ this->pq.M, this->pq.nbits, this->sim_table, code);
467
+ return dis;
468
+ }
469
+
470
+ size_t scan_codes(
471
+ size_t ncode,
472
+ const uint8_t* codes,
473
+ const idx_t* ids,
474
+ ResultHandler& handler) const override {
475
+ WrappedSearchResult<C, use_sel> res(
476
+ this->key,
477
+ this->store_pairs ? nullptr : ids,
478
+ this->sel,
479
+ handler);
480
+
481
+ if (this->polysemous_ht > 0) {
482
+ FAISS_THROW_IF_NOT(precompute_mode == 2);
483
+ this->scan_list_polysemous(ncode, codes, res);
484
+ } else if (precompute_mode == 2) {
485
+ this->scan_list_with_table(ncode, codes, res);
486
+ } else if (precompute_mode == 1) {
487
+ this->scan_list_with_pointer(ncode, codes, res);
488
+ } else if (precompute_mode == 0) {
489
+ this->scan_on_the_fly_dist(ncode, codes, res);
490
+ } else {
491
+ FAISS_THROW_MSG("bad precomp mode");
492
+ }
493
+ return res.nup;
494
+ }
495
+ };
496
+
497
+ template <SIMDLevel SL>
498
+ InvertedListScanner* make_IVFPQInvertedListScanner(
499
+ const IndexIVFPQ& ivfpq,
500
+ bool store_pairs,
501
+ const IDSelector* sel);
502
+
503
+ // NOLINTNEXTLINE(facebook-hte-MisplacedTemplateSpecialization)
504
+ template <>
505
+ InvertedListScanner* make_IVFPQInvertedListScanner<THE_SIMD_LEVEL>(
506
+ const IndexIVFPQ& ivfpq,
507
+ bool store_pairs,
508
+ const IDSelector* sel) {
509
+ auto make = [&]<class PQCodeDist, bool use_sel>() -> InvertedListScanner* {
510
+ if (ivfpq.metric_type == METRIC_INNER_PRODUCT) {
511
+ return new IVFPQScanner<
512
+ METRIC_INNER_PRODUCT,
513
+ CMin<float, idx_t>,
514
+ PQCodeDist,
515
+ use_sel>(ivfpq, store_pairs, 2, sel);
516
+ } else if (ivfpq.metric_type == METRIC_L2) {
517
+ return new IVFPQScanner<
518
+ METRIC_L2,
519
+ CMax<float, idx_t>,
520
+ PQCodeDist,
521
+ use_sel>(ivfpq, store_pairs, 2, sel);
522
+ } else {
523
+ FAISS_THROW_MSG("unsupported metric type");
524
+ }
525
+ };
526
+
527
+ auto with_decoder = [&]<bool use_sel>() -> InvertedListScanner* {
528
+ if (ivfpq.pq.nbits == 8) {
529
+ return make.template
530
+ operator()<PQCodeDistance<PQDecoder8, THE_SIMD_LEVEL>, use_sel>();
531
+ } else if (ivfpq.pq.nbits == 16) {
532
+ return make.template
533
+ operator()<PQCodeDistance<PQDecoder16, THE_SIMD_LEVEL>, use_sel>();
534
+ } else {
535
+ return make.template operator()<
536
+ PQCodeDistance<PQDecoderGeneric, THE_SIMD_LEVEL>,
537
+ use_sel>();
538
+ }
539
+ };
540
+
541
+ if (sel) {
542
+ return with_decoder.template operator()<true>();
543
+ } else {
544
+ return with_decoder.template operator()<false>();
545
+ }
546
+ }
547
+
548
+ } // namespace pq_code_distance
549
+ } // namespace faiss