faiss 0.6.0 → 0.6.2

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 (378) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/ext/faiss/extconf.rb +2 -1
  4. data/ext/faiss/{index_rb.cpp → index.cpp} +1 -1
  5. data/ext/faiss/index_binary.cpp +1 -1
  6. data/ext/faiss/kmeans.cpp +1 -1
  7. data/ext/faiss/pca_matrix.cpp +1 -1
  8. data/ext/faiss/product_quantizer.cpp +1 -1
  9. data/ext/faiss/{utils_rb.cpp → utils.cpp} +1 -1
  10. data/lib/faiss/version.rb +1 -1
  11. data/vendor/faiss/faiss/AutoTune.cpp +93 -80
  12. data/vendor/faiss/faiss/Clustering.cpp +39 -240
  13. data/vendor/faiss/faiss/Clustering.h +6 -0
  14. data/vendor/faiss/faiss/IVFlib.cpp +41 -21
  15. data/vendor/faiss/faiss/Index.cpp +6 -5
  16. data/vendor/faiss/faiss/Index.h +5 -5
  17. data/vendor/faiss/faiss/Index2Layer.cpp +37 -53
  18. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +49 -37
  19. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +36 -34
  20. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +4 -1
  21. data/vendor/faiss/faiss/IndexBinary.cpp +5 -3
  22. data/vendor/faiss/faiss/IndexBinary.h +4 -4
  23. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +1 -1
  24. data/vendor/faiss/faiss/IndexBinaryFlat.h +1 -1
  25. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +4 -4
  26. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +88 -97
  27. data/vendor/faiss/faiss/IndexBinaryHNSW.h +9 -3
  28. data/vendor/faiss/faiss/IndexBinaryHash.cpp +45 -236
  29. data/vendor/faiss/faiss/IndexBinaryHash.h +6 -6
  30. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +89 -417
  31. data/vendor/faiss/faiss/IndexFastScan.cpp +72 -109
  32. data/vendor/faiss/faiss/IndexFastScan.h +25 -23
  33. data/vendor/faiss/faiss/IndexFlat.cpp +27 -20
  34. data/vendor/faiss/faiss/IndexFlat.h +21 -18
  35. data/vendor/faiss/faiss/IndexFlatCodes.cpp +42 -19
  36. data/vendor/faiss/faiss/IndexHNSW.cpp +374 -206
  37. data/vendor/faiss/faiss/IndexHNSW.h +16 -2
  38. data/vendor/faiss/faiss/IndexIDMap.cpp +25 -21
  39. data/vendor/faiss/faiss/IndexIDMap.h +9 -7
  40. data/vendor/faiss/faiss/IndexIVF.cpp +467 -364
  41. data/vendor/faiss/faiss/IndexIVF.h +33 -12
  42. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +79 -76
  43. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +96 -93
  44. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +4 -1
  45. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +357 -238
  46. data/vendor/faiss/faiss/IndexIVFFastScan.h +42 -41
  47. data/vendor/faiss/faiss/IndexIVFFlat.cpp +39 -69
  48. data/vendor/faiss/faiss/IndexIVFFlat.h +32 -0
  49. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +56 -33
  50. data/vendor/faiss/faiss/IndexIVFFlatPanorama.h +3 -1
  51. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +18 -15
  52. data/vendor/faiss/faiss/IndexIVFPQ.cpp +73 -846
  53. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +151 -121
  54. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +3 -0
  55. data/vendor/faiss/faiss/IndexIVFPQR.cpp +23 -20
  56. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +30 -52
  57. data/vendor/faiss/faiss/IndexIVFRaBitQ.h +2 -1
  58. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +475 -476
  59. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +248 -93
  60. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +41 -127
  61. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +1 -1
  62. data/vendor/faiss/faiss/IndexLSH.cpp +36 -19
  63. data/vendor/faiss/faiss/IndexLattice.cpp +13 -13
  64. data/vendor/faiss/faiss/IndexNNDescent.cpp +36 -21
  65. data/vendor/faiss/faiss/IndexNNDescent.h +2 -2
  66. data/vendor/faiss/faiss/IndexNSG.cpp +38 -23
  67. data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +31 -11
  68. data/vendor/faiss/faiss/IndexPQ.cpp +128 -221
  69. data/vendor/faiss/faiss/IndexPQ.h +3 -2
  70. data/vendor/faiss/faiss/IndexPQFastScan.cpp +20 -14
  71. data/vendor/faiss/faiss/IndexPQFastScan.h +3 -0
  72. data/vendor/faiss/faiss/IndexPreTransform.cpp +25 -18
  73. data/vendor/faiss/faiss/IndexPreTransform.h +1 -1
  74. data/vendor/faiss/faiss/IndexRaBitQ.cpp +11 -36
  75. data/vendor/faiss/faiss/IndexRaBitQ.h +2 -1
  76. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +41 -277
  77. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +183 -27
  78. data/vendor/faiss/faiss/IndexRefine.cpp +30 -25
  79. data/vendor/faiss/faiss/IndexRefine.h +4 -4
  80. data/vendor/faiss/faiss/IndexReplicas.cpp +6 -6
  81. data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +15 -14
  82. data/vendor/faiss/faiss/IndexRowwiseMinMax.h +1 -1
  83. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +150 -20
  84. data/vendor/faiss/faiss/IndexScalarQuantizer.h +10 -0
  85. data/vendor/faiss/faiss/IndexShards.cpp +10 -9
  86. data/vendor/faiss/faiss/IndexShardsIVF.cpp +21 -15
  87. data/vendor/faiss/faiss/MatrixStats.cpp +5 -4
  88. data/vendor/faiss/faiss/MetaIndexes.cpp +19 -17
  89. data/vendor/faiss/faiss/MetaIndexes.h +1 -1
  90. data/vendor/faiss/faiss/MetricType.h +14 -7
  91. data/vendor/faiss/faiss/SuperKMeans.cpp +656 -0
  92. data/vendor/faiss/faiss/SuperKMeans.h +97 -0
  93. data/vendor/faiss/faiss/VectorTransform.cpp +237 -149
  94. data/vendor/faiss/faiss/VectorTransform.h +16 -16
  95. data/vendor/faiss/faiss/build.cpp +23 -0
  96. data/vendor/faiss/faiss/build.h +15 -0
  97. data/vendor/faiss/faiss/clone_index.cpp +48 -47
  98. data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +1 -1
  99. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +47 -47
  100. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +11 -0
  101. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +902 -12
  102. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +38 -38
  103. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +11 -0
  104. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +702 -10
  105. data/vendor/faiss/faiss/factory_tools.cpp +9 -0
  106. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +6 -5
  107. data/vendor/faiss/faiss/gpu/GpuResources.h +3 -2
  108. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +15 -16
  109. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +5 -4
  110. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +46 -0
  111. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +56 -0
  112. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +78 -1
  113. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +72 -0
  114. data/vendor/faiss/faiss/gpu/test/TestUtils.h +23 -0
  115. data/vendor/faiss/faiss/gpu/utils/CuvsFilterConvert.h +1 -1
  116. data/vendor/faiss/faiss/gpu/utils/CuvsUtils.h +21 -10
  117. data/vendor/faiss/faiss/gpu_metal/GpuIndexFlat.h +22 -0
  118. data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +35 -0
  119. data/vendor/faiss/faiss/gpu_metal/MetalDistance.h +87 -0
  120. data/vendor/faiss/faiss/gpu_metal/MetalFlatKernels.h +40 -0
  121. data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +58 -0
  122. data/vendor/faiss/faiss/gpu_metal/MetalIndexFlat.h +65 -0
  123. data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +181 -0
  124. data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +111 -0
  125. data/vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h +45 -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/gpu_metal/impl/MetalIVFFlat.h +193 -0
  129. data/vendor/faiss/faiss/impl/AdSampling.cpp +103 -0
  130. data/vendor/faiss/faiss/impl/AdSampling.h +35 -0
  131. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +29 -25
  132. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +1 -0
  133. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +10 -9
  134. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +3 -0
  135. data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +244 -0
  136. data/vendor/faiss/faiss/impl/ClusteringHelpers.h +94 -0
  137. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +16 -16
  138. data/vendor/faiss/faiss/impl/CodePacker.cpp +3 -3
  139. data/vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp +1 -1
  140. data/vendor/faiss/faiss/impl/DistanceComputer.h +8 -8
  141. data/vendor/faiss/faiss/impl/FaissAssert.h +6 -3
  142. data/vendor/faiss/faiss/impl/FaissException.h +50 -3
  143. data/vendor/faiss/faiss/impl/HNSW.cpp +639 -507
  144. data/vendor/faiss/faiss/impl/HNSW.h +61 -44
  145. data/vendor/faiss/faiss/impl/IDSelector.cpp +15 -11
  146. data/vendor/faiss/faiss/impl/IDSelector.h +8 -8
  147. data/vendor/faiss/faiss/impl/InvertedListScannerStats.h +26 -0
  148. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +82 -77
  149. data/vendor/faiss/faiss/impl/NNDescent.cpp +62 -25
  150. data/vendor/faiss/faiss/impl/NNDescent.h +6 -2
  151. data/vendor/faiss/faiss/impl/NSG.cpp +53 -32
  152. data/vendor/faiss/faiss/impl/NSG.h +4 -4
  153. data/vendor/faiss/faiss/impl/Panorama.cpp +23 -6
  154. data/vendor/faiss/faiss/impl/Panorama.h +269 -87
  155. data/vendor/faiss/faiss/impl/PdxLayout.cpp +93 -0
  156. data/vendor/faiss/faiss/impl/PdxLayout.h +41 -0
  157. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +46 -32
  158. data/vendor/faiss/faiss/impl/PolysemousTraining.h +3 -3
  159. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +35 -35
  160. data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +21 -16
  161. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +55 -25
  162. data/vendor/faiss/faiss/impl/Quantizer.h +2 -2
  163. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +55 -49
  164. data/vendor/faiss/faiss/impl/RaBitQUtils.h +65 -0
  165. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +302 -283
  166. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +26 -23
  167. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +1 -1
  168. data/vendor/faiss/faiss/impl/ResultHandler.h +100 -75
  169. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +318 -7
  170. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +77 -1
  171. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +14 -11
  172. data/vendor/faiss/faiss/impl/VisitedTable.cpp +10 -10
  173. data/vendor/faiss/faiss/impl/VisitedTable.h +70 -28
  174. data/vendor/faiss/faiss/impl/approx_topk/approx_topk.h +276 -0
  175. data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +68 -0
  176. data/vendor/faiss/faiss/{utils → impl}/approx_topk/generic.h +15 -8
  177. data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +68 -0
  178. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab-inl.h +169 -0
  179. data/vendor/faiss/faiss/impl/approx_topk/rq_beam_search_tab.h +117 -0
  180. data/vendor/faiss/faiss/impl/approx_topk/simdlib256-inl.h +146 -0
  181. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHNSW_impl.h +73 -0
  182. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +270 -0
  183. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +460 -0
  184. data/vendor/faiss/faiss/impl/binary_hamming/IndexIVFSpectralHash_impl.h +159 -0
  185. data/vendor/faiss/faiss/impl/binary_hamming/IndexPQ_impl.h +92 -0
  186. data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +26 -0
  187. data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +26 -0
  188. data/vendor/faiss/faiss/impl/binary_hamming/dispatch.h +143 -0
  189. data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +26 -0
  190. data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +26 -0
  191. data/vendor/faiss/faiss/impl/expanded_scanners.h +8 -3
  192. data/vendor/faiss/faiss/impl/{FastScanDistancePostProcessing.h → fast_scan/FastScanDistancePostProcessing.h} +13 -6
  193. data/vendor/faiss/faiss/impl/{LookupTableScaler.h → fast_scan/LookupTableScaler.h} +16 -5
  194. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +237 -0
  195. data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +185 -0
  196. data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +229 -0
  197. data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +270 -0
  198. data/vendor/faiss/faiss/impl/{pq4_fast_scan.cpp → fast_scan/fast_scan.cpp} +169 -2
  199. data/vendor/faiss/faiss/impl/fast_scan/fast_scan.h +341 -0
  200. data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +36 -0
  201. data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +40 -0
  202. data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +120 -0
  203. data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +104 -0
  204. data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +213 -0
  205. data/vendor/faiss/faiss/impl/{pq4_fast_scan_search_qbs.cpp → fast_scan/kernels_simd512.h} +26 -356
  206. data/vendor/faiss/faiss/impl/fast_scan/rabitq_dispatching.h +90 -0
  207. data/vendor/faiss/faiss/impl/fast_scan/rabitq_result_handler.h +108 -0
  208. data/vendor/faiss/faiss/impl/{simd_result_handlers.h → fast_scan/simd_result_handlers.h} +282 -134
  209. data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +54 -0
  210. data/vendor/faiss/faiss/impl/hnsw/LockVector.h +64 -0
  211. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +83 -0
  212. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +113 -0
  213. data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +150 -0
  214. data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +142 -0
  215. data/vendor/faiss/faiss/impl/index_read.cpp +1227 -79
  216. data/vendor/faiss/faiss/impl/index_read_utils.h +1 -1
  217. data/vendor/faiss/faiss/impl/index_write.cpp +96 -13
  218. data/vendor/faiss/faiss/impl/io.cpp +6 -6
  219. data/vendor/faiss/faiss/impl/io_macros.h +58 -16
  220. data/vendor/faiss/faiss/impl/kmeans1d.cpp +10 -10
  221. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +37 -23
  222. data/vendor/faiss/faiss/impl/lattice_Zn.h +6 -6
  223. data/vendor/faiss/faiss/impl/mapped_io.cpp +6 -6
  224. data/vendor/faiss/faiss/impl/platform_macros.h +15 -4
  225. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +549 -0
  226. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +245 -0
  227. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.h +105 -0
  228. data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +106 -0
  229. data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +23 -0
  230. data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +23 -0
  231. data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +23 -0
  232. data/vendor/faiss/faiss/impl/pq_code_distance/{pq_code_distance-avx2.cpp → pq_code_distance-avx2.h} +9 -13
  233. data/vendor/faiss/faiss/impl/pq_code_distance/{pq_code_distance-avx512.cpp → pq_code_distance-avx512.h} +9 -57
  234. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +45 -107
  235. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +96 -0
  236. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +274 -5
  237. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +10 -7
  238. data/vendor/faiss/faiss/impl/pq_code_distance/pq_scan_impl.h +105 -0
  239. data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +70 -0
  240. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +311 -477
  241. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +1 -1
  242. data/vendor/faiss/faiss/impl/scalar_quantizer/codecs.h +1 -1
  243. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +9 -2
  244. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +419 -19
  245. data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +27 -1
  246. data/vendor/faiss/faiss/impl/scalar_quantizer/similarities.h +3 -3
  247. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +387 -2
  248. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +553 -0
  249. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +559 -0
  250. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +341 -2
  251. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +425 -3
  252. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +290 -2
  253. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +337 -0
  254. data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +192 -8
  255. data/vendor/faiss/faiss/impl/scalar_quantizer/training.h +12 -0
  256. data/vendor/faiss/faiss/impl/simd_dispatch.h +157 -66
  257. data/vendor/faiss/faiss/impl/simdlib/simdlib.h +57 -0
  258. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_avx2.h +264 -172
  259. data/vendor/faiss/faiss/impl/simdlib/simdlib_avx512.h +414 -0
  260. data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +44 -0
  261. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_emulated.h +231 -166
  262. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_neon.h +270 -218
  263. data/vendor/faiss/faiss/{utils → impl/simdlib}/simdlib_ppc64.h +201 -160
  264. data/vendor/faiss/faiss/impl/svs_io.cpp +12 -3
  265. data/vendor/faiss/faiss/impl/svs_io.h +8 -2
  266. data/vendor/faiss/faiss/index_factory.cpp +90 -18
  267. data/vendor/faiss/faiss/index_io.h +40 -0
  268. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +66 -16
  269. data/vendor/faiss/faiss/invlists/DirectMap.cpp +28 -15
  270. data/vendor/faiss/faiss/invlists/DirectMap.h +4 -3
  271. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +170 -86
  272. data/vendor/faiss/faiss/invlists/InvertedLists.h +88 -25
  273. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +4 -4
  274. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +13 -13
  275. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
  276. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +1 -1
  277. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +2 -2
  278. data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +350 -0
  279. data/vendor/faiss/faiss/svs/IndexSVSIVF.h +128 -0
  280. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.cpp +40 -0
  281. data/vendor/faiss/faiss/svs/IndexSVSIVFLVQ.h +43 -0
  282. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +225 -0
  283. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.h +71 -0
  284. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +142 -21
  285. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +33 -7
  286. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +3 -2
  287. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +2 -1
  288. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +77 -27
  289. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +10 -4
  290. data/vendor/faiss/faiss/utils/Heap.cpp +10 -10
  291. data/vendor/faiss/faiss/utils/NeuralNet.cpp +47 -36
  292. data/vendor/faiss/faiss/utils/NeuralNet.h +1 -1
  293. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +10 -4
  294. data/vendor/faiss/faiss/utils/bf16.h +34 -0
  295. data/vendor/faiss/faiss/utils/distances.cpp +390 -560
  296. data/vendor/faiss/faiss/utils/distances.h +20 -1
  297. data/vendor/faiss/faiss/utils/distances_dispatch.h +117 -37
  298. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +8 -7
  299. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +33 -14
  300. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +12 -1
  301. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +16 -293
  302. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +57 -0
  303. data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +290 -0
  304. data/vendor/faiss/faiss/utils/distances_simd.cpp +5 -178
  305. data/vendor/faiss/faiss/utils/extra_distances.cpp +9 -8
  306. data/vendor/faiss/faiss/utils/extra_distances.h +32 -6
  307. data/vendor/faiss/faiss/utils/hamming-inl.h +13 -11
  308. data/vendor/faiss/faiss/utils/hamming.cpp +66 -517
  309. data/vendor/faiss/faiss/utils/hamming.h +92 -2
  310. data/vendor/faiss/faiss/utils/hamming_distance/common.h +287 -10
  311. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +16 -0
  312. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +15 -0
  313. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_spr.cpp +15 -0
  314. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx2.h +142 -0
  315. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +210 -0
  316. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512_spr.h +171 -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 -989
  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 +2 -2
  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 +57 -536
  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 +5 -1
  335. data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +213 -4
  336. data/vendor/faiss/faiss/utils/simd_impl/distances_autovec-inl.h +163 -10
  337. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +250 -4
  338. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +7 -4
  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 +2 -1
  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 +1031 -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_avx512_spr.cpp +343 -0
  350. data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +55 -0
  351. data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +55 -0
  352. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_dispatch.h +32 -0
  353. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +43 -0
  354. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +57 -0
  355. data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +45 -0
  356. data/vendor/faiss/faiss/utils/simd_levels.cpp +29 -7
  357. data/vendor/faiss/faiss/utils/simd_levels.h +93 -1
  358. data/vendor/faiss/faiss/utils/sorting.cpp +48 -36
  359. data/vendor/faiss/faiss/utils/utils.cpp +5 -5
  360. data/vendor/faiss/faiss/utils/utils.h +3 -3
  361. metadata +129 -34
  362. data/vendor/faiss/faiss/impl/RaBitQStats.cpp +0 -29
  363. data/vendor/faiss/faiss/impl/RaBitQStats.h +0 -56
  364. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +0 -224
  365. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +0 -230
  366. data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +0 -84
  367. data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +0 -196
  368. data/vendor/faiss/faiss/utils/approx_topk/mode.h +0 -34
  369. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +0 -36
  370. data/vendor/faiss/faiss/utils/extra_distances-inl.h +0 -235
  371. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +0 -462
  372. data/vendor/faiss/faiss/utils/hamming_distance/avx512-inl.h +0 -490
  373. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +0 -449
  374. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +0 -87
  375. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +0 -524
  376. data/vendor/faiss/faiss/utils/simdlib.h +0 -42
  377. data/vendor/faiss/faiss/utils/simdlib_avx512.h +0 -365
  378. /data/ext/faiss/{utils_rb.h → utils.h} +0 -0
@@ -17,7 +17,6 @@
17
17
  #include <faiss/impl/DistanceComputer.h>
18
18
  #include <faiss/impl/FaissAssert.h>
19
19
  #include <faiss/impl/maybe_owned_vector.h>
20
- #include <faiss/impl/platform_macros.h>
21
20
  #include <faiss/utils/Heap.h>
22
21
  #include <faiss/utils/random.h>
23
22
 
@@ -26,6 +25,10 @@ namespace faiss {
26
25
  // Forward declarations to avoid circular dependency.
27
26
  struct IndexHNSW;
28
27
  struct IndexHNSWFlatPanorama;
28
+ template <class HC_>
29
+ struct MinimaxHeapT;
30
+ using MinimaxHeap = MinimaxHeapT<CMax<float, int32_t>>;
31
+ class LockVector;
29
32
 
30
33
  /** Implementation of the Hierarchical Navigable Small World
31
34
  * datastructure.
@@ -59,56 +62,52 @@ struct HNSW {
59
62
  /// internal storage of vectors (32 bits: this is expensive)
60
63
  using storage_idx_t = int32_t;
61
64
 
62
- // for now we do only these distances
63
- using C = CMax<float, int64_t>;
65
+ // The two comparator flavors HNSW supports. CMax (smaller-is-better)
66
+ // is the default; CMin (larger-is-better) is used when `is_similarity`
67
+ // is set on the owning index.
68
+ using C_distance = CMax<float, int64_t>;
69
+ using C_similarity = CMin<float, int64_t>;
64
70
 
65
- typedef std::pair<float, storage_idx_t> Node;
66
-
67
- /** Heap structure that allows fast access and updates.
68
- */
69
- struct MinimaxHeap {
70
- int n;
71
- int k;
72
- int nvalid;
73
-
74
- std::vector<storage_idx_t> ids;
75
- std::vector<float> dis;
76
- typedef faiss::CMax<float, storage_idx_t> HC;
77
-
78
- explicit MinimaxHeap(int n) : n(n), k(0), nvalid(0), ids(n), dis(n) {}
79
-
80
- void push(storage_idx_t i, float v);
81
-
82
- float max() const;
83
-
84
- int size() const;
85
-
86
- void clear();
71
+ // Back-compat alias: keeps `HNSW::C` resolving to the distance
72
+ // (CMax) comparator everywhere the type is referenced directly.
73
+ using C = C_distance;
87
74
 
88
- int pop_min(float* vmin_out = nullptr);
89
-
90
- int count_below(float thresh);
91
- };
75
+ typedef std::pair<float, storage_idx_t> Node;
92
76
 
93
77
  /// to sort pairs of (id, distance) from nearest to farthest or the reverse
94
- struct NodeDistCloser {
78
+ template <class CT>
79
+ struct NodeDistCloserT {
95
80
  float d;
96
81
  int id;
97
- NodeDistCloser(float d, int id) : d(d), id(id) {}
98
- bool operator<(const NodeDistCloser& obj1) const {
99
- return d < obj1.d;
82
+ NodeDistCloserT(float d_in, int id_in) : d(d_in), id(id_in) {}
83
+ bool operator<(const NodeDistCloserT& obj1) const {
84
+ // priority_queue keeps the "worst" element at the top so that
85
+ // when the queue is full we can pop it. For CMax (distance) the
86
+ // worst element is the largest d; for CMin (similarity) it is
87
+ // the smallest d. Equivalent to: obj1.d "better than" d.
88
+ return CT::cmp(obj1.d, d);
100
89
  }
101
90
  };
102
91
 
103
- struct NodeDistFarther {
92
+ template <class CT>
93
+ struct NodeDistFartherT {
104
94
  float d;
105
95
  int id;
106
- NodeDistFarther(float d, int id) : d(d), id(id) {}
107
- bool operator<(const NodeDistFarther& obj1) const {
108
- return d > obj1.d;
96
+ NodeDistFartherT(float d_in, int id_in) : d(d_in), id(id_in) {}
97
+ bool operator<(const NodeDistFartherT& obj1) const {
98
+ // priority_queue here keeps the "best" element at the top so we
99
+ // can process the nearest candidate first. For CMax (distance)
100
+ // the best is the smallest d; for CMin (similarity) the best is
101
+ // the largest d. Equivalent to: d "better than" obj1.d.
102
+ return CT::cmp(d, obj1.d);
109
103
  }
110
104
  };
111
105
 
106
+ // Back-compat aliases: default to the distance (CMax) comparator so
107
+ // existing call sites that mention `HNSW::NodeDist*` keep working.
108
+ using NodeDistCloser = NodeDistCloserT<C_distance>;
109
+ using NodeDistFarther = NodeDistFartherT<C_distance>;
110
+
112
111
  /// assignment probability to each layer (sum=1)
113
112
  std::vector<double> assign_probas;
114
113
 
@@ -142,6 +141,10 @@ struct HNSW {
142
141
  /// expansion factor at search time
143
142
  int efSearch = 16;
144
143
 
144
+ /// when pruning, leave room for more neighbors to avoid O(n^2)
145
+ /// costs and lock contention on frequently-pruned nodes.
146
+ float prune_headroom = 0.2f;
147
+
145
148
  /// during search: do we check whether the next best distance is good
146
149
  /// enough?
147
150
  bool check_relative_distance = true;
@@ -152,6 +155,12 @@ struct HNSW {
152
155
  /// use Panorama progressive pruning in search
153
156
  bool is_panorama = false;
154
157
 
158
+ /// distance comparison semantics: when true, distances are treated as
159
+ /// similarity scores (larger is better). Default false matches the
160
+ /// historical L2/Hamming behavior (smaller is better).
161
+ /// Not serialized: must be re-set by the owning Index after loading.
162
+ bool is_similarity = false;
163
+
155
164
  // See impl/VisitedTable.h.
156
165
  std::optional<bool> use_visited_hashset;
157
166
 
@@ -191,7 +200,7 @@ struct HNSW {
191
200
  storage_idx_t nearest,
192
201
  float d_nearest,
193
202
  int level,
194
- omp_lock_t* locks,
203
+ LockVector& locks,
195
204
  VisitedTable& vt,
196
205
  bool keep_max_size_level0 = false);
197
206
 
@@ -201,7 +210,7 @@ struct HNSW {
201
210
  DistanceComputer& ptdis,
202
211
  int pt_level,
203
212
  int pt_id,
204
- std::vector<omp_lock_t>& locks,
213
+ LockVector& locks,
205
214
  VisitedTable& vt,
206
215
  bool keep_max_size_level0 = false);
207
216
 
@@ -237,11 +246,12 @@ struct HNSW {
237
246
 
238
247
  int prepare_level_tab(size_t n, bool preset_levels = false);
239
248
 
249
+ template <class C = C_distance>
240
250
  static void shrink_neighbor_list(
241
251
  DistanceComputer& qdis,
242
- std::priority_queue<NodeDistFarther>& input,
243
- std::vector<NodeDistFarther>& output,
244
- int max_size,
252
+ std::priority_queue<NodeDistFartherT<C>>& input,
253
+ std::vector<NodeDistFartherT<C>>& output,
254
+ size_t max_size,
245
255
  bool keep_max_size_level0 = false);
246
256
 
247
257
  void permute_entries(const idx_t* map);
@@ -271,11 +281,16 @@ struct HNSWStats {
271
281
  // global var that collects them all
272
282
  FAISS_API extern HNSWStats hnsw_stats;
273
283
 
284
+ /// Internal HNSW algorithm helpers. These are not part of the public API; they
285
+ /// are exposed here only so that unit tests (and a few cross-TU callers such as
286
+ /// the Panorama search variant) can reach them.
287
+ namespace hnsw_detail {
288
+
274
289
  int search_from_candidates(
275
290
  const HNSW& hnsw,
276
291
  DistanceComputer& qdis,
277
292
  ResultHandler& res,
278
- HNSW::MinimaxHeap& candidates,
293
+ MinimaxHeap& candidates,
279
294
  VisitedTable& vt,
280
295
  HNSWStats& stats,
281
296
  int level,
@@ -291,7 +306,7 @@ int search_from_candidates_panorama(
291
306
  const IndexHNSW* index,
292
307
  DistanceComputer& qdis,
293
308
  ResultHandler& res,
294
- HNSW::MinimaxHeap& candidates,
309
+ MinimaxHeap& candidates,
295
310
  VisitedTable& vt,
296
311
  HNSWStats& stats,
297
312
  int level,
@@ -323,4 +338,6 @@ void search_neighbors_to_add(
323
338
  VisitedTable& vt,
324
339
  bool reference_version = false);
325
340
 
341
+ } // namespace hnsw_detail
342
+
326
343
  } // namespace faiss
@@ -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
@@ -22,11 +22,11 @@
22
22
  #include <faiss/utils/distances.h>
23
23
  #include <faiss/utils/utils.h>
24
24
 
25
- #include <faiss/utils/approx_topk/approx_topk.h>
25
+ #include <faiss/impl/approx_topk/approx_topk.h>
26
26
 
27
27
  // this is needed for prefetching
28
28
 
29
- #ifdef __AVX2__
29
+ #ifdef COMPILE_SIMD_AVX2
30
30
  #include <xmmintrin.h>
31
31
  #endif
32
32
 
@@ -154,12 +154,15 @@ lsq::LSQTimer lsq_timer;
154
154
  using lsq::LSQTimerScope;
155
155
 
156
156
  LocalSearchQuantizer::LocalSearchQuantizer(
157
- size_t d,
158
- size_t M,
159
- size_t nbits,
160
- Search_type_t search_type)
161
- : AdditiveQuantizer(d, std::vector<size_t>(M, nbits), search_type) {
162
- 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);
163
166
  std::srand(random_seed);
164
167
  }
165
168
 
@@ -170,7 +173,7 @@ LocalSearchQuantizer::~LocalSearchQuantizer() {
170
173
  LocalSearchQuantizer::LocalSearchQuantizer() : LocalSearchQuantizer(0, 0, 0) {}
171
174
 
172
175
  void LocalSearchQuantizer::train(size_t n, const float* x) {
173
- FAISS_THROW_IF_NOT(K == (1 << nbits[0]));
176
+ FAISS_THROW_IF_NOT(K == static_cast<size_t>(1 << nbits[0]));
174
177
  nperts = std::min(nperts, M);
175
178
 
176
179
  lsq_timer.reset();
@@ -194,7 +197,7 @@ void LocalSearchQuantizer::train(size_t n, const float* x) {
194
197
  std::vector<float> stddev(d, 0);
195
198
 
196
199
  #pragma omp parallel for
197
- for (int64_t i = 0; i < d; i++) {
200
+ for (int64_t i = 0; i < static_cast<int64_t>(d); i++) {
198
201
  float mean = 0;
199
202
  for (size_t j = 0; j < n; j++) {
200
203
  mean += x[j * d + i];
@@ -362,7 +365,7 @@ void LocalSearchQuantizer::update_codebooks(
362
365
  }
363
366
 
364
367
  // add a regularization term to B'B
365
- for (int64_t i = 0; i < M * K; i++) {
368
+ for (size_t i = 0; i < M * K; i++) {
366
369
  bb[i * (M * K) + i] += lambd;
367
370
  }
368
371
 
@@ -427,7 +430,7 @@ void LocalSearchQuantizer::update_codebooks(
427
430
  }
428
431
 
429
432
  // add a regularization term to B'B
430
- for (int64_t i = 0; i < M * K; i++) {
433
+ for (size_t i = 0; i < M * K; i++) {
431
434
  bb[i * (M * K) + i] += lambd;
432
435
  }
433
436
 
@@ -540,7 +543,7 @@ void LocalSearchQuantizer::icm_encode_impl(
540
543
  std::mt19937& gen,
541
544
  size_t n,
542
545
  size_t ils_iters,
543
- bool verbose) const {
546
+ bool verbose_in) const {
544
547
  std::vector<float> unaries(n * M * K); // [M, n, K]
545
548
  compute_unary_terms(x, unaries.data(), n);
546
549
 
@@ -564,7 +567,7 @@ void LocalSearchQuantizer::icm_encode_impl(
564
567
 
565
568
  // select the best code for every vector xi
566
569
  #pragma omp parallel for reduction(+ : n_betters, mean_obj)
567
- for (int64_t i = 0; i < n; i++) {
570
+ for (int64_t i = 0; i < static_cast<int64_t>(n); i++) {
568
571
  if (icm_objs[i] < best_objs[i]) {
569
572
  best_objs[i] = icm_objs[i];
570
573
  memcpy(best_codes.data() + i * M,
@@ -578,7 +581,7 @@ void LocalSearchQuantizer::icm_encode_impl(
578
581
 
579
582
  memcpy(codes, best_codes.data(), sizeof(int32_t) * n * M);
580
583
 
581
- if (verbose) {
584
+ if (verbose_in) {
582
585
  printf("\tils_iter %zd: obj = %lf, n_betters/n = %zd/%zd\n",
583
586
  iter1,
584
587
  mean_obj,
@@ -597,73 +600,75 @@ void LocalSearchQuantizer::icm_encode_step(
597
600
  FAISS_THROW_IF_NOT(M != 0 && K != 0);
598
601
  FAISS_THROW_IF_NOT(binaries != nullptr);
599
602
 
603
+ // Resolve SIMD level once, not per iteration of the n × n_iters × M loop.
604
+ with_simd_level_256bit([&]<SIMDLevel SL>() {
600
605
  #pragma omp parallel for schedule(dynamic)
601
- for (int64_t i = 0; i < n; i++) {
602
- std::vector<float> objs(K);
603
-
604
- for (size_t iter = 0; iter < n_iters; iter++) {
605
- // condition on the m-th subcode
606
- for (size_t m = 0; m < M; m++) {
607
- // copy
608
- auto u = unaries + m * n * K + i * K;
609
- for (size_t code = 0; code < K; code++) {
610
- objs[code] = u[code];
611
- }
612
-
613
- // compute objective function by adding unary
614
- // and binary terms together
615
- for (size_t other_m = 0; other_m < M; other_m++) {
616
- if (other_m == m) {
617
- 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];
618
616
  }
619
617
 
620
- #ifdef __AVX2__
621
- // TODO: add platform-independent compiler-independent
622
- // prefetch utilities.
623
- if (other_m + 1 < M) {
624
- // do a single prefetch
625
- int32_t code2 = codes[i * M + other_m + 1];
626
- // for (int32_t code = 0; code < K; code += 64) {
627
- int32_t code = 0;
628
- {
629
- size_t binary_idx = (other_m + 1) * M * K * K +
630
- m * K * K + code2 * K + code;
631
- _mm_prefetch(
632
- (const char*)(binaries + binary_idx),
633
- _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
+ }
634
640
  }
635
- }
636
641
  #endif
637
642
 
638
- for (int32_t code = 0; code < K; code++) {
639
- int32_t code2 = codes[i * M + other_m];
640
- size_t binary_idx = other_m * M * K * K + m * K * K +
641
- code2 * K + code;
642
- // binaries[m, other_m, code, code2].
643
- // It is symmetric over (m <-> other_m)
644
- // and (code <-> code2).
645
- // So, replace the op with
646
- // binaries[other_m, m, code2, code].
647
- 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
+ }
648
654
  }
649
- }
650
655
 
651
- // find the optimal value of the m-th subcode
652
- float best_obj = HUGE_VALF;
653
- 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;
654
659
 
655
- // find one using SIMD. The following operation is similar
656
- // to the search of the smallest element in objs
657
- using C = CMax<float, int>;
658
- HeapWithBuckets<C, 16, 1>::addn(
659
- 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);
660
664
 
661
- // done
662
- codes[i * M + m] = best_code;
665
+ // done
666
+ codes[i * M + m] = best_code;
663
667
 
664
- } // loop M
668
+ } // loop M
669
+ }
665
670
  }
666
- }
671
+ });
667
672
  }
668
673
  void LocalSearchQuantizer::perturb_codes(
669
674
  int32_t* codes,
@@ -687,7 +692,7 @@ void LocalSearchQuantizer::compute_binary_terms(float* binaries) const {
687
692
 
688
693
  with_simd_level([&]<SIMDLevel SL>() {
689
694
  #pragma omp parallel for
690
- for (int64_t m12 = 0; m12 < M * M; m12++) {
695
+ for (int64_t m12 = 0; m12 < static_cast<int64_t>(M * M); m12++) {
691
696
  size_t m1 = m12 / M;
692
697
  size_t m2 = m12 % M;
693
698
 
@@ -744,7 +749,7 @@ void LocalSearchQuantizer::compute_unary_terms(
744
749
  fvec_norms_L2sqr(norms.data(), codebooks.data(), d, M * K);
745
750
 
746
751
  #pragma omp parallel for
747
- for (int64_t i = 0; i < n; i++) {
752
+ for (int64_t i = 0; i < static_cast<int64_t>(n); i++) {
748
753
  for (size_t m = 0; m < M; m++) {
749
754
  float* u = unaries + m * n * K + i * K;
750
755
  fvec_add(K, u, norms.data() + m * K, u);
@@ -766,7 +771,7 @@ float LocalSearchQuantizer::evaluate(
766
771
  with_simd_level([&]<SIMDLevel SL>() {
767
772
  float local_obj = 0.0f;
768
773
  #pragma omp parallel for reduction(+ : local_obj)
769
- for (int64_t i = 0; i < n; i++) {
774
+ for (int64_t i = 0; i < static_cast<int64_t>(n); i++) {
770
775
  const auto code = codes + i * M;
771
776
  const auto decoded_i = decoded_x.data() + i * d;
772
777
  for (size_t m = 0; m < M; m++) {
@@ -791,8 +796,8 @@ float LocalSearchQuantizer::evaluate(
791
796
 
792
797
  namespace lsq {
793
798
 
794
- IcmEncoder::IcmEncoder(const LocalSearchQuantizer* lsq)
795
- : verbose(false), lsq(lsq) {}
799
+ IcmEncoder::IcmEncoder(const LocalSearchQuantizer* lsq_in)
800
+ : verbose(false), lsq(lsq_in) {}
796
801
 
797
802
  void IcmEncoder::set_binary_term() {
798
803
  auto M = lsq->M;
@@ -830,8 +835,8 @@ void LSQTimer::reset() {
830
835
  t.clear();
831
836
  }
832
837
 
833
- LSQTimerScope::LSQTimerScope(LSQTimer* timer, std::string name)
834
- : 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) {
835
840
  t0 = getmillisecs();
836
841
  }
837
842