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
@@ -7,6 +7,7 @@
7
7
 
8
8
  #pragma once
9
9
 
10
+ #include <optional>
10
11
  #include <queue>
11
12
  #include <vector>
12
13
 
@@ -16,7 +17,6 @@
16
17
  #include <faiss/impl/DistanceComputer.h>
17
18
  #include <faiss/impl/FaissAssert.h>
18
19
  #include <faiss/impl/maybe_owned_vector.h>
19
- #include <faiss/impl/platform_macros.h>
20
20
  #include <faiss/utils/Heap.h>
21
21
  #include <faiss/utils/random.h>
22
22
 
@@ -25,6 +25,8 @@ namespace faiss {
25
25
  // Forward declarations to avoid circular dependency.
26
26
  struct IndexHNSW;
27
27
  struct IndexHNSWFlatPanorama;
28
+ struct MinimaxHeap;
29
+ class LockVector;
28
30
 
29
31
  /** Implementation of the Hierarchical Navigable Small World
30
32
  * datastructure.
@@ -45,8 +47,6 @@ struct IndexHNSWFlatPanorama;
45
47
  struct VisitedTable;
46
48
  struct DistanceComputer; // from AuxIndexStructures
47
49
  struct HNSWStats;
48
- template <class C>
49
- struct ResultHandler;
50
50
 
51
51
  struct SearchParametersHNSW : SearchParameters {
52
52
  int efSearch = 16;
@@ -65,37 +65,11 @@ struct HNSW {
65
65
 
66
66
  typedef std::pair<float, storage_idx_t> Node;
67
67
 
68
- /** Heap structure that allows fast access and updates.
69
- */
70
- struct MinimaxHeap {
71
- int n;
72
- int k;
73
- int nvalid;
74
-
75
- std::vector<storage_idx_t> ids;
76
- std::vector<float> dis;
77
- typedef faiss::CMax<float, storage_idx_t> HC;
78
-
79
- explicit MinimaxHeap(int n) : n(n), k(0), nvalid(0), ids(n), dis(n) {}
80
-
81
- void push(storage_idx_t i, float v);
82
-
83
- float max() const;
84
-
85
- int size() const;
86
-
87
- void clear();
88
-
89
- int pop_min(float* vmin_out = nullptr);
90
-
91
- int count_below(float thresh);
92
- };
93
-
94
68
  /// to sort pairs of (id, distance) from nearest to farthest or the reverse
95
69
  struct NodeDistCloser {
96
70
  float d;
97
71
  int id;
98
- NodeDistCloser(float d, int id) : d(d), id(id) {}
72
+ NodeDistCloser(float d_in, int id_in) : d(d_in), id(id_in) {}
99
73
  bool operator<(const NodeDistCloser& obj1) const {
100
74
  return d < obj1.d;
101
75
  }
@@ -104,7 +78,7 @@ struct HNSW {
104
78
  struct NodeDistFarther {
105
79
  float d;
106
80
  int id;
107
- NodeDistFarther(float d, int id) : d(d), id(id) {}
81
+ NodeDistFarther(float d_in, int id_in) : d(d_in), id(id_in) {}
108
82
  bool operator<(const NodeDistFarther& obj1) const {
109
83
  return d > obj1.d;
110
84
  }
@@ -143,6 +117,10 @@ struct HNSW {
143
117
  /// expansion factor at search time
144
118
  int efSearch = 16;
145
119
 
120
+ /// when pruning, leave room for more neighbors to avoid O(n^2)
121
+ /// costs and lock contention on frequently-pruned nodes.
122
+ float prune_headroom = 0.2f;
123
+
146
124
  /// during search: do we check whether the next best distance is good
147
125
  /// enough?
148
126
  bool check_relative_distance = true;
@@ -153,6 +131,9 @@ struct HNSW {
153
131
  /// use Panorama progressive pruning in search
154
132
  bool is_panorama = false;
155
133
 
134
+ // See impl/VisitedTable.h.
135
+ std::optional<bool> use_visited_hashset;
136
+
156
137
  // methods that initialize the tree sizes
157
138
 
158
139
  /// initialize the assign_probas and cum_nneighbor_per_level to
@@ -189,7 +170,7 @@ struct HNSW {
189
170
  storage_idx_t nearest,
190
171
  float d_nearest,
191
172
  int level,
192
- omp_lock_t* locks,
173
+ LockVector& locks,
193
174
  VisitedTable& vt,
194
175
  bool keep_max_size_level0 = false);
195
176
 
@@ -199,7 +180,7 @@ struct HNSW {
199
180
  DistanceComputer& ptdis,
200
181
  int pt_level,
201
182
  int pt_id,
202
- std::vector<omp_lock_t>& locks,
183
+ LockVector& locks,
203
184
  VisitedTable& vt,
204
185
  bool keep_max_size_level0 = false);
205
186
 
@@ -212,14 +193,14 @@ struct HNSW {
212
193
  HNSWStats search(
213
194
  DistanceComputer& qdis,
214
195
  const IndexHNSW* index,
215
- ResultHandler<C>& res,
196
+ ResultHandler& res,
216
197
  VisitedTable& vt,
217
198
  const SearchParameters* params = nullptr) const;
218
199
 
219
200
  /// search only in level 0 from a given vertex
220
201
  void search_level_0(
221
202
  DistanceComputer& qdis,
222
- ResultHandler<C>& res,
203
+ ResultHandler& res,
223
204
  idx_t nprobe,
224
205
  const storage_idx_t* nearest_i,
225
206
  const float* nearest_d,
@@ -239,7 +220,7 @@ struct HNSW {
239
220
  DistanceComputer& qdis,
240
221
  std::priority_queue<NodeDistFarther>& input,
241
222
  std::vector<NodeDistFarther>& output,
242
- int max_size,
223
+ size_t max_size,
243
224
  bool keep_max_size_level0 = false);
244
225
 
245
226
  void permute_entries(const idx_t* map);
@@ -272,8 +253,8 @@ FAISS_API extern HNSWStats hnsw_stats;
272
253
  int search_from_candidates(
273
254
  const HNSW& hnsw,
274
255
  DistanceComputer& qdis,
275
- ResultHandler<HNSW::C>& res,
276
- HNSW::MinimaxHeap& candidates,
256
+ ResultHandler& res,
257
+ MinimaxHeap& candidates,
277
258
  VisitedTable& vt,
278
259
  HNSWStats& stats,
279
260
  int level,
@@ -288,8 +269,8 @@ int search_from_candidates_panorama(
288
269
  const HNSW& hnsw,
289
270
  const IndexHNSW* index,
290
271
  DistanceComputer& qdis,
291
- ResultHandler<HNSW::C>& res,
292
- HNSW::MinimaxHeap& candidates,
272
+ ResultHandler& res,
273
+ MinimaxHeap& candidates,
293
274
  VisitedTable& vt,
294
275
  HNSWStats& stats,
295
276
  int level,
@@ -14,8 +14,11 @@ namespace faiss {
14
14
  * IDSelectorRange
15
15
  ***********************************************************************/
16
16
 
17
- IDSelectorRange::IDSelectorRange(idx_t imin, idx_t imax, bool assume_sorted)
18
- : imin(imin), imax(imax), assume_sorted(assume_sorted) {}
17
+ IDSelectorRange::IDSelectorRange(
18
+ idx_t imin_in,
19
+ idx_t imax_in,
20
+ bool assume_sorted_in)
21
+ : imin(imin_in), imax(imax_in), assume_sorted(assume_sorted_in) {}
19
22
 
20
23
  bool IDSelectorRange::is_member(idx_t id) const {
21
24
  return id >= imin && id < imax;
@@ -67,10 +70,11 @@ void IDSelectorRange::find_sorted_ids_bounds(
67
70
  * IDSelectorArray
68
71
  ***********************************************************************/
69
72
 
70
- IDSelectorArray::IDSelectorArray(size_t n, const idx_t* ids) : n(n), ids(ids) {}
73
+ IDSelectorArray::IDSelectorArray(size_t n_in, const idx_t* ids_in)
74
+ : n(n_in), ids(ids_in) {}
71
75
 
72
76
  bool IDSelectorArray::is_member(idx_t id) const {
73
- for (idx_t i = 0; i < n; i++) {
77
+ for (size_t i = 0; i < n; i++) {
74
78
  if (ids[i] == id) {
75
79
  return true;
76
80
  }
@@ -84,15 +88,15 @@ bool IDSelectorArray::is_member(idx_t id) const {
84
88
 
85
89
  IDSelectorBatch::IDSelectorBatch(size_t n, const idx_t* indices) {
86
90
  nbits = 0;
87
- while (n > ((idx_t)1 << nbits)) {
91
+ while (n > (size_t{1} << nbits)) {
88
92
  nbits++;
89
93
  }
90
94
  nbits += 5;
91
95
  // for n = 1M, nbits = 25 is optimal, see P56659518
92
96
 
93
97
  mask = ((idx_t)1 << nbits) - 1;
94
- bloom.resize((idx_t)1 << (nbits - 3), 0);
95
- for (idx_t i = 0; i < n; i++) {
98
+ bloom.resize(size_t{1} << (nbits - 3), 0);
99
+ for (size_t i = 0; i < n; i++) {
96
100
  idx_t id = indices[i];
97
101
  set.insert(id);
98
102
  id &= mask;
@@ -101,9 +105,9 @@ IDSelectorBatch::IDSelectorBatch(size_t n, const idx_t* indices) {
101
105
  }
102
106
 
103
107
  bool IDSelectorBatch::is_member(idx_t i) const {
104
- long im = i & mask;
108
+ idx_t im = i & mask;
105
109
  if (!(bloom[im >> 3] & (1 << (im & 7)))) {
106
- return 0;
110
+ return false;
107
111
  }
108
112
  return set.count(i);
109
113
  }
@@ -112,8 +116,8 @@ bool IDSelectorBatch::is_member(idx_t i) const {
112
116
  * IDSelectorBitmap
113
117
  ***********************************************************************/
114
118
 
115
- IDSelectorBitmap::IDSelectorBitmap(size_t n, const uint8_t* bitmap)
116
- : n(n), bitmap(bitmap) {}
119
+ IDSelectorBitmap::IDSelectorBitmap(size_t n_in, const uint8_t* bitmap_in)
120
+ : n(n_in), bitmap(bitmap_in) {}
117
121
 
118
122
  bool IDSelectorBitmap::is_member(idx_t ii) const {
119
123
  uint64_t i = ii;
@@ -116,7 +116,7 @@ struct IDSelectorBitmap : IDSelector {
116
116
  /** reverts the membership test of another selector */
117
117
  struct IDSelectorNot : IDSelector {
118
118
  const IDSelector* sel;
119
- explicit IDSelectorNot(const IDSelector* sel) : sel(sel) {}
119
+ explicit IDSelectorNot(const IDSelector* sel_) : sel(sel_) {}
120
120
  bool is_member(idx_t id) const final {
121
121
  return !sel->is_member(id);
122
122
  }
@@ -125,7 +125,7 @@ struct IDSelectorNot : IDSelector {
125
125
 
126
126
  /// selects all entries (useful for benchmarking)
127
127
  struct IDSelectorAll : IDSelector {
128
- bool is_member(idx_t id) const final {
128
+ bool is_member(idx_t /* id */) const final {
129
129
  return true;
130
130
  }
131
131
  virtual ~IDSelectorAll() {}
@@ -136,8 +136,8 @@ struct IDSelectorAll : IDSelector {
136
136
  struct IDSelectorAnd : IDSelector {
137
137
  const IDSelector* lhs;
138
138
  const IDSelector* rhs;
139
- IDSelectorAnd(const IDSelector* lhs, const IDSelector* rhs)
140
- : lhs(lhs), rhs(rhs) {}
139
+ IDSelectorAnd(const IDSelector* lhs_, const IDSelector* rhs_)
140
+ : lhs(lhs_), rhs(rhs_) {}
141
141
  bool is_member(idx_t id) const final {
142
142
  return lhs->is_member(id) && rhs->is_member(id);
143
143
  }
@@ -149,8 +149,8 @@ struct IDSelectorAnd : IDSelector {
149
149
  struct IDSelectorOr : IDSelector {
150
150
  const IDSelector* lhs;
151
151
  const IDSelector* rhs;
152
- IDSelectorOr(const IDSelector* lhs, const IDSelector* rhs)
153
- : lhs(lhs), rhs(rhs) {}
152
+ IDSelectorOr(const IDSelector* lhs_, const IDSelector* rhs_)
153
+ : lhs(lhs_), rhs(rhs_) {}
154
154
  bool is_member(idx_t id) const final {
155
155
  return lhs->is_member(id) || rhs->is_member(id);
156
156
  }
@@ -162,8 +162,8 @@ struct IDSelectorOr : IDSelector {
162
162
  struct IDSelectorXOr : IDSelector {
163
163
  const IDSelector* lhs;
164
164
  const IDSelector* rhs;
165
- IDSelectorXOr(const IDSelector* lhs, const IDSelector* rhs)
166
- : lhs(lhs), rhs(rhs) {}
165
+ IDSelectorXOr(const IDSelector* lhs_, const IDSelector* rhs_)
166
+ : lhs(lhs_), rhs(rhs_) {}
167
167
  bool is_member(idx_t id) const final {
168
168
  return lhs->is_member(id) ^ rhs->is_member(id);
169
169
  }
@@ -0,0 +1,26 @@
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
+ #ifndef FAISS_INVERTED_LIST_SCANNER_STATS_H
9
+ #define FAISS_INVERTED_LIST_SCANNER_STATS_H
10
+
11
+ #include <cstddef>
12
+
13
+ namespace faiss {
14
+
15
+ /** Per-list statistics returned by inverted-list scanners. */
16
+ struct InvertedListScannerStats {
17
+ /// Number of distances computed after IDSelector filtering.
18
+ size_t scan_cnt = 0;
19
+
20
+ /// Number of heap updates.
21
+ size_t nheap_updates = 0;
22
+ };
23
+
24
+ } // namespace faiss
25
+
26
+ #endif
@@ -18,14 +18,15 @@
18
18
 
19
19
  #include <faiss/impl/AuxIndexStructures.h>
20
20
  #include <faiss/impl/FaissAssert.h>
21
+ #include <faiss/impl/simd_dispatch.h>
21
22
  #include <faiss/utils/distances.h>
22
23
  #include <faiss/utils/utils.h>
23
24
 
24
- #include <faiss/utils/approx_topk/approx_topk.h>
25
+ #include <faiss/impl/approx_topk/approx_topk.h>
25
26
 
26
27
  // this is needed for prefetching
27
28
 
28
- #ifdef __AVX2__
29
+ #ifdef COMPILE_SIMD_AVX2
29
30
  #include <xmmintrin.h>
30
31
  #endif
31
32
 
@@ -153,12 +154,15 @@ lsq::LSQTimer lsq_timer;
153
154
  using lsq::LSQTimerScope;
154
155
 
155
156
  LocalSearchQuantizer::LocalSearchQuantizer(
156
- size_t d,
157
- size_t M,
158
- size_t nbits,
159
- Search_type_t search_type)
160
- : AdditiveQuantizer(d, std::vector<size_t>(M, nbits), search_type) {
161
- K = (1 << nbits);
157
+ size_t d_in,
158
+ size_t M_in,
159
+ size_t nbits_in,
160
+ Search_type_t search_type_in)
161
+ : AdditiveQuantizer(
162
+ d_in,
163
+ std::vector<size_t>(M_in, nbits_in),
164
+ search_type_in) {
165
+ K = (1 << nbits_in);
162
166
  std::srand(random_seed);
163
167
  }
164
168
 
@@ -169,7 +173,7 @@ LocalSearchQuantizer::~LocalSearchQuantizer() {
169
173
  LocalSearchQuantizer::LocalSearchQuantizer() : LocalSearchQuantizer(0, 0, 0) {}
170
174
 
171
175
  void LocalSearchQuantizer::train(size_t n, const float* x) {
172
- FAISS_THROW_IF_NOT(K == (1 << nbits[0]));
176
+ FAISS_THROW_IF_NOT(K == static_cast<size_t>(1 << nbits[0]));
173
177
  nperts = std::min(nperts, M);
174
178
 
175
179
  lsq_timer.reset();
@@ -193,7 +197,7 @@ void LocalSearchQuantizer::train(size_t n, const float* x) {
193
197
  std::vector<float> stddev(d, 0);
194
198
 
195
199
  #pragma omp parallel for
196
- for (int64_t i = 0; i < d; i++) {
200
+ for (int64_t i = 0; i < static_cast<int64_t>(d); i++) {
197
201
  float mean = 0;
198
202
  for (size_t j = 0; j < n; j++) {
199
203
  mean += x[j * d + i];
@@ -361,7 +365,7 @@ void LocalSearchQuantizer::update_codebooks(
361
365
  }
362
366
 
363
367
  // add a regularization term to B'B
364
- for (int64_t i = 0; i < M * K; i++) {
368
+ for (size_t i = 0; i < M * K; i++) {
365
369
  bb[i * (M * K) + i] += lambd;
366
370
  }
367
371
 
@@ -426,7 +430,7 @@ void LocalSearchQuantizer::update_codebooks(
426
430
  }
427
431
 
428
432
  // add a regularization term to B'B
429
- for (int64_t i = 0; i < M * K; i++) {
433
+ for (size_t i = 0; i < M * K; i++) {
430
434
  bb[i * (M * K) + i] += lambd;
431
435
  }
432
436
 
@@ -539,7 +543,7 @@ void LocalSearchQuantizer::icm_encode_impl(
539
543
  std::mt19937& gen,
540
544
  size_t n,
541
545
  size_t ils_iters,
542
- bool verbose) const {
546
+ bool verbose_in) const {
543
547
  std::vector<float> unaries(n * M * K); // [M, n, K]
544
548
  compute_unary_terms(x, unaries.data(), n);
545
549
 
@@ -563,7 +567,7 @@ void LocalSearchQuantizer::icm_encode_impl(
563
567
 
564
568
  // select the best code for every vector xi
565
569
  #pragma omp parallel for reduction(+ : n_betters, mean_obj)
566
- for (int64_t i = 0; i < n; i++) {
570
+ for (int64_t i = 0; i < static_cast<int64_t>(n); i++) {
567
571
  if (icm_objs[i] < best_objs[i]) {
568
572
  best_objs[i] = icm_objs[i];
569
573
  memcpy(best_codes.data() + i * M,
@@ -577,7 +581,7 @@ void LocalSearchQuantizer::icm_encode_impl(
577
581
 
578
582
  memcpy(codes, best_codes.data(), sizeof(int32_t) * n * M);
579
583
 
580
- if (verbose) {
584
+ if (verbose_in) {
581
585
  printf("\tils_iter %zd: obj = %lf, n_betters/n = %zd/%zd\n",
582
586
  iter1,
583
587
  mean_obj,
@@ -596,73 +600,75 @@ void LocalSearchQuantizer::icm_encode_step(
596
600
  FAISS_THROW_IF_NOT(M != 0 && K != 0);
597
601
  FAISS_THROW_IF_NOT(binaries != nullptr);
598
602
 
603
+ // Resolve SIMD level once, not per iteration of the n × n_iters × M loop.
604
+ with_simd_level_256bit([&]<SIMDLevel SL>() {
599
605
  #pragma omp parallel for schedule(dynamic)
600
- for (int64_t i = 0; i < n; i++) {
601
- std::vector<float> objs(K);
602
-
603
- for (size_t iter = 0; iter < n_iters; iter++) {
604
- // condition on the m-th subcode
605
- for (size_t m = 0; m < M; m++) {
606
- // copy
607
- auto u = unaries + m * n * K + i * K;
608
- for (size_t code = 0; code < K; code++) {
609
- objs[code] = u[code];
610
- }
611
-
612
- // compute objective function by adding unary
613
- // and binary terms together
614
- for (size_t other_m = 0; other_m < M; other_m++) {
615
- if (other_m == m) {
616
- continue;
606
+ for (int64_t i = 0; i < static_cast<int64_t>(n); i++) {
607
+ std::vector<float> objs(K);
608
+
609
+ for (size_t iter = 0; iter < n_iters; iter++) {
610
+ // condition on the m-th subcode
611
+ for (size_t m = 0; m < M; m++) {
612
+ // copy
613
+ auto u = unaries + m * n * K + i * K;
614
+ for (size_t code = 0; code < K; code++) {
615
+ objs[code] = u[code];
617
616
  }
618
617
 
619
- #ifdef __AVX2__
620
- // TODO: add platform-independent compiler-independent
621
- // prefetch utilities.
622
- if (other_m + 1 < M) {
623
- // do a single prefetch
624
- int32_t code2 = codes[i * M + other_m + 1];
625
- // for (int32_t code = 0; code < K; code += 64) {
626
- int32_t code = 0;
627
- {
628
- size_t binary_idx = (other_m + 1) * M * K * K +
629
- m * K * K + code2 * K + code;
630
- _mm_prefetch(
631
- (const char*)(binaries + binary_idx),
632
- _MM_HINT_T0);
618
+ // compute objective function by adding unary
619
+ // and binary terms together
620
+ for (size_t other_m = 0; other_m < M; other_m++) {
621
+ if (other_m == m) {
622
+ continue;
623
+ }
624
+
625
+ #ifdef COMPILE_SIMD_AVX2
626
+ // TODO: add platform-independent compiler-independent
627
+ // prefetch utilities.
628
+ if (other_m + 1 < M) {
629
+ // do a single prefetch
630
+ int32_t code2 = codes[i * M + other_m + 1];
631
+ // for (int32_t code = 0; code < K; code += 64) {
632
+ int32_t code = 0;
633
+ {
634
+ size_t binary_idx = (other_m + 1) * M * K * K +
635
+ m * K * K + code2 * K + code;
636
+ _mm_prefetch(
637
+ (const char*)(binaries + binary_idx),
638
+ _MM_HINT_T0);
639
+ }
633
640
  }
634
- }
635
641
  #endif
636
642
 
637
- for (int32_t code = 0; code < K; code++) {
638
- int32_t code2 = codes[i * M + other_m];
639
- size_t binary_idx = other_m * M * K * K + m * K * K +
640
- code2 * K + code;
641
- // binaries[m, other_m, code, code2].
642
- // It is symmetric over (m <-> other_m)
643
- // and (code <-> code2).
644
- // So, replace the op with
645
- // binaries[other_m, m, code2, code].
646
- objs[code] += binaries[binary_idx];
643
+ for (size_t code = 0; code < K; code++) {
644
+ int32_t code2 = codes[i * M + other_m];
645
+ size_t binary_idx = other_m * M * K * K +
646
+ m * K * K + code2 * K + code;
647
+ // binaries[m, other_m, code, code2].
648
+ // It is symmetric over (m <-> other_m)
649
+ // and (code <-> code2).
650
+ // So, replace the op with
651
+ // binaries[other_m, m, code2, code].
652
+ objs[code] += binaries[binary_idx];
653
+ }
647
654
  }
648
- }
649
655
 
650
- // find the optimal value of the m-th subcode
651
- float best_obj = HUGE_VALF;
652
- int32_t best_code = 0;
656
+ // find the optimal value of the m-th subcode
657
+ float best_obj = HUGE_VALF;
658
+ int32_t best_code = 0;
653
659
 
654
- // find one using SIMD. The following operation is similar
655
- // to the search of the smallest element in objs
656
- using C = CMax<float, int>;
657
- HeapWithBuckets<C, 16, 1>::addn(
658
- K, objs.data(), 1, &best_obj, &best_code);
660
+ // find one using SIMD. The following operation is similar
661
+ // to the search of the smallest element in objs
662
+ HeapWithBucketsCMaxFloat<16, 1, SL>::addn(
663
+ K, objs.data(), 1, &best_obj, &best_code);
659
664
 
660
- // done
661
- codes[i * M + m] = best_code;
665
+ // done
666
+ codes[i * M + m] = best_code;
662
667
 
663
- } // loop M
668
+ } // loop M
669
+ }
664
670
  }
665
- }
671
+ });
666
672
  }
667
673
  void LocalSearchQuantizer::perturb_codes(
668
674
  int32_t* codes,
@@ -684,22 +690,24 @@ void LocalSearchQuantizer::perturb_codes(
684
690
  void LocalSearchQuantizer::compute_binary_terms(float* binaries) const {
685
691
  LSQTimerScope scope(&lsq_timer, "compute_binary_terms");
686
692
 
693
+ with_simd_level([&]<SIMDLevel SL>() {
687
694
  #pragma omp parallel for
688
- for (int64_t m12 = 0; m12 < M * M; m12++) {
689
- size_t m1 = m12 / M;
690
- size_t m2 = m12 % M;
691
-
692
- for (size_t code1 = 0; code1 < K; code1++) {
693
- for (size_t code2 = 0; code2 < K; code2++) {
694
- const float* c1 = codebooks.data() + m1 * K * d + code1 * d;
695
- const float* c2 = codebooks.data() + m2 * K * d + code2 * d;
696
- float ip = fvec_inner_product(c1, c2, d);
697
- // binaries[m1, m2, code1, code2] = ip * 2
698
- binaries[m1 * M * K * K + m2 * K * K + code1 * K + code2] =
699
- ip * 2;
695
+ for (int64_t m12 = 0; m12 < static_cast<int64_t>(M * M); m12++) {
696
+ size_t m1 = m12 / M;
697
+ size_t m2 = m12 % M;
698
+
699
+ for (size_t code1 = 0; code1 < K; code1++) {
700
+ for (size_t code2 = 0; code2 < K; code2++) {
701
+ const float* c1 = codebooks.data() + m1 * K * d + code1 * d;
702
+ const float* c2 = codebooks.data() + m2 * K * d + code2 * d;
703
+ float ip = fvec_inner_product<SL>(c1, c2, d);
704
+ // binaries[m1, m2, code1, code2] = ip * 2
705
+ binaries[m1 * M * K * K + m2 * K * K + code1 * K + code2] =
706
+ ip * 2;
707
+ }
700
708
  }
701
709
  }
702
- }
710
+ });
703
711
  }
704
712
 
705
713
  void LocalSearchQuantizer::compute_unary_terms(
@@ -741,7 +749,7 @@ void LocalSearchQuantizer::compute_unary_terms(
741
749
  fvec_norms_L2sqr(norms.data(), codebooks.data(), d, M * K);
742
750
 
743
751
  #pragma omp parallel for
744
- for (int64_t i = 0; i < n; i++) {
752
+ for (int64_t i = 0; i < static_cast<int64_t>(n); i++) {
745
753
  for (size_t m = 0; m < M; m++) {
746
754
  float* u = unaries + m * n * K + i * K;
747
755
  fvec_add(K, u, norms.data() + m * K, u);
@@ -760,23 +768,27 @@ float LocalSearchQuantizer::evaluate(
760
768
  std::vector<float> decoded_x(n * d, 0.0f);
761
769
  float obj = 0.0f;
762
770
 
763
- #pragma omp parallel for reduction(+ : obj)
764
- for (int64_t i = 0; i < n; i++) {
765
- const auto code = codes + i * M;
766
- const auto decoded_i = decoded_x.data() + i * d;
767
- for (size_t m = 0; m < M; m++) {
768
- // c = codebooks[m, code[m]]
769
- const auto c = codebooks.data() + m * K * d + code[m] * d;
770
- fvec_add(d, decoded_i, c, decoded_i);
771
- }
771
+ with_simd_level([&]<SIMDLevel SL>() {
772
+ float local_obj = 0.0f;
773
+ #pragma omp parallel for reduction(+ : local_obj)
774
+ for (int64_t i = 0; i < static_cast<int64_t>(n); i++) {
775
+ const auto code = codes + i * M;
776
+ const auto decoded_i = decoded_x.data() + i * d;
777
+ for (size_t m = 0; m < M; m++) {
778
+ // c = codebooks[m, code[m]]
779
+ const auto c = codebooks.data() + m * K * d + code[m] * d;
780
+ fvec_add(d, decoded_i, c, decoded_i);
781
+ }
772
782
 
773
- float err = faiss::fvec_L2sqr(x + i * d, decoded_i, d);
774
- obj += err;
783
+ float err = fvec_L2sqr<SL>(x + i * d, decoded_i, d);
784
+ local_obj += err;
775
785
 
776
- if (objs) {
777
- objs[i] = err;
786
+ if (objs) {
787
+ objs[i] = err;
788
+ }
778
789
  }
779
- }
790
+ obj = local_obj;
791
+ });
780
792
 
781
793
  obj = obj / n;
782
794
  return obj;
@@ -784,8 +796,8 @@ float LocalSearchQuantizer::evaluate(
784
796
 
785
797
  namespace lsq {
786
798
 
787
- IcmEncoder::IcmEncoder(const LocalSearchQuantizer* lsq)
788
- : verbose(false), lsq(lsq) {}
799
+ IcmEncoder::IcmEncoder(const LocalSearchQuantizer* lsq_in)
800
+ : verbose(false), lsq(lsq_in) {}
789
801
 
790
802
  void IcmEncoder::set_binary_term() {
791
803
  auto M = lsq->M;
@@ -823,8 +835,8 @@ void LSQTimer::reset() {
823
835
  t.clear();
824
836
  }
825
837
 
826
- LSQTimerScope::LSQTimerScope(LSQTimer* timer, std::string name)
827
- : timer(timer), name(std::move(name)), finished(false) {
838
+ LSQTimerScope::LSQTimerScope(LSQTimer* timer_in, std::string name_in)
839
+ : timer(timer_in), name(std::move(name_in)), finished(false) {
828
840
  t0 = getmillisecs();
829
841
  }
830
842