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
@@ -10,10 +10,10 @@
10
10
  #include <faiss/impl/NNDescent.h>
11
11
 
12
12
  #include <mutex>
13
- #include <string>
14
13
 
15
14
  #include <faiss/impl/AuxIndexStructures.h>
16
15
  #include <faiss/impl/DistanceComputer.h>
16
+ #include <faiss/impl/VisitedTable.h>
17
17
 
18
18
  namespace faiss {
19
19
 
@@ -23,7 +23,7 @@ namespace nndescent {
23
23
 
24
24
  void gen_random(std::mt19937& rng, int* addr, const int size, const int N);
25
25
 
26
- Nhood::Nhood(int l, int s, std::mt19937& rng, int N) {
26
+ Nhood::Nhood(int /* l */, int s, std::mt19937& rng, int N) {
27
27
  M = s;
28
28
  nn_new.resize(s * 2);
29
29
  gen_random(rng, nn_new.data(), (int)nn_new.size(), N);
@@ -31,25 +31,46 @@ Nhood::Nhood(int l, int s, std::mt19937& rng, int N) {
31
31
 
32
32
  /// Copy operator
33
33
  Nhood& Nhood::operator=(const Nhood& other) {
34
- M = other.M;
35
- std::copy(
36
- other.nn_new.begin(),
37
- other.nn_new.end(),
38
- std::back_inserter(nn_new));
39
- nn_new.reserve(other.nn_new.capacity());
40
- pool.reserve(other.pool.capacity());
34
+ if (this != &other) {
35
+ M = other.M;
36
+ nn_new = other.nn_new;
37
+ nn_old = other.nn_old;
38
+ rnn_new = other.rnn_new;
39
+ rnn_old = other.rnn_old;
40
+ pool = other.pool;
41
+ }
41
42
  return *this;
42
43
  }
43
44
 
44
45
  /// Copy constructor
45
- Nhood::Nhood(const Nhood& other) {
46
- M = other.M;
47
- std::copy(
48
- other.nn_new.begin(),
49
- other.nn_new.end(),
50
- std::back_inserter(nn_new));
51
- nn_new.reserve(other.nn_new.capacity());
52
- pool.reserve(other.pool.capacity());
46
+ Nhood::Nhood(const Nhood& other)
47
+ : pool(other.pool),
48
+ M(other.M),
49
+ nn_old(other.nn_old),
50
+ nn_new(other.nn_new),
51
+ rnn_old(other.rnn_old),
52
+ rnn_new(other.rnn_new) {}
53
+
54
+ /// Move constructor
55
+ Nhood::Nhood(Nhood&& other) noexcept
56
+ : pool(std::move(other.pool)),
57
+ M(other.M),
58
+ nn_old(std::move(other.nn_old)),
59
+ nn_new(std::move(other.nn_new)),
60
+ rnn_old(std::move(other.rnn_old)),
61
+ rnn_new(std::move(other.rnn_new)) {}
62
+
63
+ /// Move assignment operator
64
+ Nhood& Nhood::operator=(Nhood&& other) noexcept {
65
+ if (this != &other) {
66
+ M = other.M;
67
+ nn_new = std::move(other.nn_new);
68
+ nn_old = std::move(other.nn_old);
69
+ rnn_new = std::move(other.rnn_new);
70
+ rnn_old = std::move(other.rnn_old);
71
+ pool = std::move(other.pool);
72
+ }
73
+ return *this;
53
74
  }
54
75
 
55
76
  /// Insert a point into the candidate pool
@@ -58,7 +79,7 @@ void Nhood::insert(int id, float dist) {
58
79
  if (dist > pool.front().distance) {
59
80
  return;
60
81
  }
61
- for (int i = 0; i < pool.size(); i++) {
82
+ for (size_t i = 0; i < pool.size(); i++) {
62
83
  if (id == pool[i].id) {
63
84
  return;
64
85
  }
@@ -90,6 +111,22 @@ void Nhood::join(C callback) const {
90
111
  }
91
112
 
92
113
  void gen_random(std::mt19937& rng, int* addr, const int size, const int N) {
114
+ FAISS_THROW_IF_NOT_FMT(
115
+ size > 0 && size <= N,
116
+ "gen_random: size (%d) must be > 0 and <= N (%d)",
117
+ size,
118
+ N);
119
+ if (size == N) {
120
+ // Special case: return all indices in random order
121
+ for (int i = 0; i < size; ++i) {
122
+ addr[i] = i;
123
+ }
124
+ for (int i = size - 1; i > 0; --i) {
125
+ int j = rng() % (i + 1);
126
+ std::swap(addr[i], addr[j]);
127
+ }
128
+ return;
129
+ }
93
130
  for (int i = 0; i < size; ++i) {
94
131
  addr[i] = rng() % (N - size);
95
132
  }
@@ -153,7 +190,7 @@ using namespace nndescent;
153
190
 
154
191
  constexpr int NUM_EVAL_POINTS = 100;
155
192
 
156
- NNDescent::NNDescent(const int d, const int K) : K(K), d(d) {
193
+ NNDescent::NNDescent(const int d_in, const int K_in) : K(K_in), d(d_in) {
157
194
  L = K + 50;
158
195
  }
159
196
 
@@ -197,7 +234,7 @@ void NNDescent::update() {
197
234
  auto& nn = graph[n];
198
235
  std::sort(nn.pool.begin(), nn.pool.end());
199
236
 
200
- if (nn.pool.size() > L) {
237
+ if (nn.pool.size() > static_cast<size_t>(L)) {
201
238
  nn.pool.resize(L);
202
239
  }
203
240
  nn.pool.reserve(L); // keep the pool size be L
@@ -238,7 +275,7 @@ void NNDescent::update() {
238
275
  // the candidate pool of the other side
239
276
  if (nn.distance > other.pool.back().distance) {
240
277
  LockGuard guard(other.lock);
241
- if (other.rnn_new.size() < R) {
278
+ if (other.rnn_new.size() < static_cast<size_t>(R)) {
242
279
  other.rnn_new.push_back(n);
243
280
  } else {
244
281
  int pos = rng() % R;
@@ -254,7 +291,7 @@ void NNDescent::update() {
254
291
  // the candidate pool of the other side
255
292
  if (nn.distance > other.pool.back().distance) {
256
293
  LockGuard guard(other.lock);
257
- if (other.rnn_old.size() < R) {
294
+ if (other.rnn_old.size() < static_cast<size_t>(R)) {
258
295
  other.rnn_old.push_back(n);
259
296
  } else {
260
297
  int pos = rng() % R;
@@ -280,7 +317,7 @@ void NNDescent::update() {
280
317
 
281
318
  nn_new.insert(nn_new.end(), rnn_new.begin(), rnn_new.end());
282
319
  nn_old.insert(nn_old.end(), rnn_old.begin(), rnn_old.end());
283
- if (nn_old.size() > R * 2) {
320
+ if (nn_old.size() > static_cast<size_t>(R * 2)) {
284
321
  nn_old.resize(R * 2);
285
322
  nn_old.reserve(R * 2);
286
323
  }
@@ -294,7 +331,7 @@ void NNDescent::nndescent(DistanceComputer& qdis, bool verbose) {
294
331
  int num_eval_points = std::min(NUM_EVAL_POINTS, ntotal);
295
332
  std::vector<int> eval_points(num_eval_points);
296
333
  std::vector<std::vector<int>> acc_eval_set(num_eval_points);
297
- std::mt19937 rng(random_seed * 6577 + omp_get_thread_num());
334
+ std::mt19937 rng(random_seed * 6577);
298
335
  gen_random(rng, eval_points.data(), eval_points.size(), ntotal);
299
336
  generate_eval_set(qdis, eval_points, acc_eval_set, ntotal);
300
337
  for (int it = 0; it < iter; it++) {
@@ -315,7 +352,7 @@ void NNDescent::generate_eval_set(
315
352
  std::vector<std::vector<int>>& v,
316
353
  int N) {
317
354
  #pragma omp parallel for
318
- for (int i = 0; i < c.size(); i++) {
355
+ for (int i = 0; i < static_cast<int>(c.size()); i++) {
319
356
  std::vector<Neighbor> tmp;
320
357
  for (int j = 0; j < N; j++) {
321
358
  if (c[i] == j) {
@@ -488,7 +525,7 @@ void NNDescent::search(
488
525
  ++k;
489
526
  }
490
527
  }
491
- for (size_t i = 0; i < topk; i++) {
528
+ for (int i = 0; i < topk; i++) {
492
529
  indices[i] = retset[i].id;
493
530
  dists[i] = retset[i].distance;
494
531
  }
@@ -54,8 +54,8 @@ struct Neighbor {
54
54
  bool flag;
55
55
 
56
56
  Neighbor() = default;
57
- Neighbor(int id, float distance, bool f)
58
- : id(id), distance(distance), flag(f) {}
57
+ Neighbor(int id_in, float distance_in, bool f)
58
+ : id(id_in), distance(distance_in), flag(f) {}
59
59
 
60
60
  inline bool operator<(const Neighbor& other) const {
61
61
  return distance < other.distance;
@@ -80,6 +80,10 @@ struct Nhood {
80
80
 
81
81
  Nhood(const Nhood& other);
82
82
 
83
+ Nhood(Nhood&& other) noexcept;
84
+
85
+ Nhood& operator=(Nhood&& other) noexcept;
86
+
83
87
  void insert(int id, float dist);
84
88
 
85
89
  template <typename C>
@@ -8,11 +8,13 @@
8
8
  #include <faiss/impl/NSG.h>
9
9
 
10
10
  #include <algorithm>
11
+ #include <limits>
11
12
  #include <memory>
12
13
  #include <mutex>
13
14
  #include <stack>
14
15
 
15
16
  #include <faiss/impl/DistanceComputer.h>
17
+ #include <faiss/impl/VisitedTable.h>
16
18
 
17
19
  namespace faiss {
18
20
 
@@ -41,8 +43,8 @@ struct Neighbor {
41
43
  bool flag;
42
44
 
43
45
  Neighbor() = default;
44
- Neighbor(int id, float distance, bool f)
45
- : id(id), distance(distance), flag(f) {}
46
+ Neighbor(int id_in, float distance_in, bool f)
47
+ : id(id_in), distance(distance_in), flag(f) {}
46
48
 
47
49
  inline bool operator<(const Neighbor& other) const {
48
50
  return distance < other.distance;
@@ -54,7 +56,7 @@ struct Node {
54
56
  float distance;
55
57
 
56
58
  Node() = default;
57
- Node(int id, float distance) : id(id), distance(distance) {}
59
+ Node(int id_in, float distance_in) : id(id_in), distance(distance_in) {}
58
60
 
59
61
  inline bool operator<(const Node& other) const {
60
62
  return distance < other.distance;
@@ -109,10 +111,9 @@ inline int insert_into_pool(Neighbor* addr, int K, Neighbor nn) {
109
111
 
110
112
  using namespace nsg;
111
113
 
112
- NSG::NSG(int R) : R(R), rng(0x0903) {
114
+ NSG::NSG(int R_in) : R(R_in), rng(0x0903) {
113
115
  L = R + 32;
114
116
  C = R + 100;
115
- srand(0x1998);
116
117
  }
117
118
 
118
119
  void NSG::search(
@@ -130,7 +131,7 @@ void NSG::search(
130
131
  search_on_graph<false>(
131
132
  *final_graph, dis, vt, enterpoint, pool_size, retset, tmp);
132
133
 
133
- for (size_t i = 0; i < k; i++) {
134
+ for (int i = 0; i < k; i++) {
134
135
  I[i] = retset[i].id;
135
136
  D[i] = retset[i].distance;
136
137
  }
@@ -178,7 +179,7 @@ void NSG::build(
178
179
  is_built = true;
179
180
 
180
181
  if (verbose) {
181
- int max = 0, min = 1e6;
182
+ int max = 0, min = std::numeric_limits<int>::max();
182
183
  double avg = 0;
183
184
 
184
185
  for (int i = 0; i < n; i++) {
@@ -233,7 +234,7 @@ void NSG::init_graph(Index* storage, const nsg::Graph<idx_t>& knn_graph) {
233
234
  std::unique_ptr<DistanceComputer> dis(storage_distance_computer(storage));
234
235
 
235
236
  dis->set_query(center.get());
236
- VisitedTable vt(ntotal);
237
+ VisitedTable vt(ntotal, use_visited_hashset);
237
238
 
238
239
  // Do not collect the visited nodes
239
240
  search_on_graph<false>(knn_graph, *dis, vt, ep, L, retset, tmpset);
@@ -255,16 +256,18 @@ void NSG::search_on_graph(
255
256
  retset.resize(pool_size + 1);
256
257
  std::vector<int> init_ids(pool_size);
257
258
 
259
+ vt.reserve(pool_size);
260
+
258
261
  int num_ids = 0;
259
262
  std::vector<index_t> neighbors(graph.K);
260
263
  size_t nneigh = graph.get_neighbors(ep, neighbors.data());
261
- for (int i = 0; i < init_ids.size() && i < nneigh; i++) {
264
+ for (size_t i = 0; i < init_ids.size() && i < nneigh; i++) {
262
265
  int id = (int)neighbors[i];
263
266
  if (id >= ntotal) {
264
267
  continue;
265
268
  }
266
269
 
267
- init_ids[i] = id;
270
+ init_ids[num_ids] = id;
268
271
  vt.set(id);
269
272
  num_ids += 1;
270
273
  }
@@ -280,7 +283,7 @@ void NSG::search_on_graph(
280
283
  vt.set(id);
281
284
  }
282
285
 
283
- for (int i = 0; i < init_ids.size(); i++) {
286
+ for (size_t i = 0; i < init_ids.size(); i++) {
284
287
  int id = init_ids[i];
285
288
 
286
289
  float dist = dis(id);
@@ -302,9 +305,9 @@ void NSG::search_on_graph(
302
305
  int n = retset[k].id;
303
306
 
304
307
  size_t nneigh_for_n = graph.get_neighbors(n, neighbors.data());
305
- for (int m = 0; m < nneigh_for_n; m++) {
308
+ for (size_t m = 0; m < nneigh_for_n; m++) {
306
309
  int id = neighbors[m];
307
- if (id > ntotal || vt.get(id)) {
310
+ if (id >= ntotal || vt.get(id)) {
308
311
  continue;
309
312
  }
310
313
  vt.set(id);
@@ -341,7 +344,7 @@ void NSG::link(
341
344
  std::vector<Node> pool;
342
345
  std::vector<Neighbor> tmp;
343
346
 
344
- VisitedTable vt(ntotal);
347
+ VisitedTable vt(ntotal, use_visited_hashset);
345
348
  std::unique_ptr<DistanceComputer> dis(
346
349
  storage_distance_computer(storage));
347
350
 
@@ -396,16 +399,30 @@ void NSG::sync_prune(
396
399
 
397
400
  std::vector<Node> result;
398
401
 
402
+ if (pool.empty()) {
403
+ for (int i = 0; i < R; i++) {
404
+ graph.at(q, i).id = EMPTY_ID;
405
+ }
406
+ return;
407
+ }
408
+
399
409
  int start = 0;
400
410
  if (pool[start].id == q) {
401
411
  start++;
402
412
  }
413
+ if (start >= static_cast<int>(pool.size())) {
414
+ for (int i = 0; i < R; i++) {
415
+ graph.at(q, i).id = EMPTY_ID;
416
+ }
417
+ return;
418
+ }
403
419
  result.push_back(pool[start]);
404
420
 
405
- while (result.size() < R && (++start) < pool.size() && start < C) {
421
+ while (result.size() < static_cast<size_t>(R) &&
422
+ (++start) < static_cast<int>(pool.size()) && start < C) {
406
423
  auto& p = pool[start];
407
424
  bool occlude = false;
408
- for (int t = 0; t < result.size(); t++) {
425
+ for (size_t t = 0; t < result.size(); t++) {
409
426
  if (p.id == result[t].id) {
410
427
  occlude = true;
411
428
  break;
@@ -421,8 +438,8 @@ void NSG::sync_prune(
421
438
  }
422
439
  }
423
440
 
424
- for (size_t i = 0; i < R; i++) {
425
- if (i < result.size()) {
441
+ for (int i = 0; i < R; i++) {
442
+ if (static_cast<size_t>(i) < result.size()) {
426
443
  graph.at(q, i).id = result[i].id;
427
444
  graph.at(q, i).distance = result[i].distance;
428
445
  } else {
@@ -436,7 +453,7 @@ void NSG::add_reverse_links(
436
453
  std::vector<std::mutex>& locks,
437
454
  DistanceComputer& dis,
438
455
  nsg::Graph<Node>& graph) {
439
- for (size_t i = 0; i < R; i++) {
456
+ for (int i = 0; i < R; i++) {
440
457
  if (graph.at(q, i).id == EMPTY_ID) {
441
458
  break;
442
459
  }
@@ -465,17 +482,18 @@ void NSG::add_reverse_links(
465
482
  }
466
483
 
467
484
  tmp_pool.push_back(sn);
468
- if (tmp_pool.size() > R) {
485
+ if (tmp_pool.size() > static_cast<size_t>(R)) {
469
486
  std::vector<Node> result;
470
487
  int start = 0;
471
488
  std::sort(tmp_pool.begin(), tmp_pool.end());
472
489
  result.push_back(tmp_pool[start]);
473
490
 
474
- while (result.size() < R && (++start) < tmp_pool.size()) {
491
+ while (result.size() < static_cast<size_t>(R) &&
492
+ (++start) < static_cast<int>(tmp_pool.size())) {
475
493
  auto& p = tmp_pool[start];
476
494
  bool occlude = false;
477
495
 
478
- for (int t = 0; t < result.size(); t++) {
496
+ for (size_t t = 0; t < result.size(); t++) {
479
497
  if (p.id == result[t].id) {
480
498
  occlude = true;
481
499
  break;
@@ -494,7 +512,7 @@ void NSG::add_reverse_links(
494
512
 
495
513
  {
496
514
  LockGuard guard(locks[des]);
497
- for (int t = 0; t < result.size(); t++) {
515
+ for (size_t t = 0; t < result.size(); t++) {
498
516
  graph.at(des, t) = result[t];
499
517
  }
500
518
  }
@@ -513,8 +531,8 @@ void NSG::add_reverse_links(
513
531
 
514
532
  int NSG::tree_grow(Index* storage, std::vector<int>& degrees) {
515
533
  int root = enterpoint;
516
- VisitedTable vt(ntotal);
517
- VisitedTable vt2(ntotal);
534
+ VisitedTable vt(ntotal, use_visited_hashset);
535
+ VisitedTable vt2(ntotal, use_visited_hashset);
518
536
 
519
537
  int num_attached = 0;
520
538
  int cnt = 0;
@@ -613,7 +631,7 @@ int NSG::attach_unlinked(
613
631
 
614
632
  int node;
615
633
  bool found = false;
616
- for (int i = 0; i < pool.size(); i++) {
634
+ for (size_t i = 0; i < pool.size(); i++) {
617
635
  node = pool[i].id;
618
636
  if (degrees[node] < R && node != id) {
619
637
  found = true;
@@ -9,12 +9,12 @@
9
9
 
10
10
  #include <memory>
11
11
  #include <mutex>
12
+ #include <optional>
12
13
  #include <vector>
13
14
 
14
15
  #include <omp.h>
15
16
 
16
17
  #include <faiss/Index.h>
17
- #include <faiss/impl/AuxIndexStructures.h>
18
18
  #include <faiss/impl/FaissAssert.h>
19
19
  #include <faiss/utils/Heap.h>
20
20
  #include <faiss/utils/random.h>
@@ -38,6 +38,7 @@ namespace faiss {
38
38
  */
39
39
 
40
40
  struct DistanceComputer; // from AuxIndexStructures
41
+ struct VisitedTable;
41
42
 
42
43
  namespace nsg {
43
44
 
@@ -59,18 +60,20 @@ struct Graph {
59
60
  bool own_fields; ///< the underlying data owned by itself or not
60
61
 
61
62
  // construct from a known graph
62
- Graph(node_t* data, int N, int K)
63
- : data(data), K(K), N(N), own_fields(false) {}
63
+ Graph(node_t* data_in, int N_in, int K_in)
64
+ : data(data_in), K(K_in), N(N_in), own_fields(false) {}
64
65
 
65
66
  // construct an empty graph
66
67
  // NOTE: the newly allocated data needs to be destroyed at destruction time
67
- Graph(int N, int K) : K(K), N(N), own_fields(true) {
68
- data = new node_t[N * K];
68
+ Graph(int N_in, int K_in) : K(K_in), N(N_in), own_fields(true) {
69
+ size_t total = faiss::mul_no_overflow(
70
+ (size_t)N_in, (size_t)K_in, "Graph allocation");
71
+ data = new node_t[total];
69
72
  }
70
73
 
71
74
  // copy constructor
72
75
  Graph(const Graph& g) : Graph(g.N, g.K) {
73
- memcpy(data, g.data, N * K * sizeof(node_t));
76
+ memcpy(data, g.data, (size_t)N * (size_t)K * sizeof(node_t));
74
77
  }
75
78
 
76
79
  // release the allocated memory if needed
@@ -82,21 +85,25 @@ struct Graph {
82
85
 
83
86
  // access the j-th neighbor of node i
84
87
  inline node_t at(int i, int j) const {
85
- return data[i * K + j];
88
+ FAISS_CHECK_RANGE_DEBUG(i, 0, N);
89
+ FAISS_CHECK_RANGE_DEBUG(j, 0, K);
90
+ return data[(size_t)i * K + j];
86
91
  }
87
92
 
88
93
  // access the j-th neighbor of node i by reference
89
94
  inline node_t& at(int i, int j) {
90
- return data[i * K + j];
95
+ FAISS_CHECK_RANGE_DEBUG(i, 0, N);
96
+ FAISS_CHECK_RANGE_DEBUG(j, 0, K);
97
+ return data[(size_t)i * K + j];
91
98
  }
92
99
 
93
100
  // get all neighbors of node i (used during search only)
94
101
  virtual size_t get_neighbors(int i, node_t* neighbors) const {
95
102
  for (int j = 0; j < K; j++) {
96
- if (data[i * K + j] < 0) {
103
+ if (data[(size_t)i * K + j] < 0) {
97
104
  return j;
98
105
  }
99
- neighbors[j] = data[i * K + j];
106
+ neighbors[j] = data[(size_t)i * K + j];
100
107
  }
101
108
  return K;
102
109
  }
@@ -122,6 +129,9 @@ struct NSG {
122
129
  // search-time parameters
123
130
  int search_L = 16; ///< length of the search path
124
131
 
132
+ // See impl/VisitedTable.h.
133
+ std::optional<bool> use_visited_hashset;
134
+
125
135
  int enterpoint; ///< enterpoint
126
136
 
127
137
  std::shared_ptr<nsg::Graph<int32_t>> final_graph; ///< NSG graph structure
@@ -10,23 +10,77 @@
10
10
  #include <algorithm>
11
11
  #include <cmath>
12
12
  #include <cstring>
13
- #include <vector>
13
+
14
+ #include <faiss/impl/FaissAssert.h>
14
15
 
15
16
  namespace faiss {
16
17
 
18
+ namespace {
19
+
20
+ /// Helper function to compute cumulative sums by iterating backwards through
21
+ /// levels. This is the core logic shared by compute_cumulative_sums and
22
+ /// compute_query_cum_sums.
23
+ template <typename OffsetFunc>
24
+ inline void compute_cum_sums_impl(
25
+ const float* vector,
26
+ float* output,
27
+ size_t d,
28
+ size_t n_levels,
29
+ size_t level_width_floats,
30
+ OffsetFunc&& get_offset) {
31
+ // Iterate backwards through levels, accumulating sum as we go.
32
+ // This avoids computing the suffix sum for each vector, which takes
33
+ // extra memory.
34
+ float sum = 0.0f;
35
+
36
+ for (int level = n_levels - 1; level >= 0; level--) {
37
+ size_t start_idx = level * level_width_floats;
38
+ size_t end_idx = std::min(
39
+ (level + 1) * level_width_floats, static_cast<size_t>(d));
40
+
41
+ for (size_t j = start_idx; j < end_idx; j++) {
42
+ sum += vector[j] * vector[j];
43
+ }
44
+
45
+ output[get_offset(level)] = std::sqrt(sum);
46
+ }
47
+
48
+ output[get_offset(n_levels)] = 0.0f;
49
+ }
50
+
51
+ } // namespace
52
+
17
53
  /**************************************************************
18
54
  * Panorama structure implementation
19
55
  **************************************************************/
20
56
 
21
- Panorama::Panorama(size_t code_size, size_t n_levels, size_t batch_size)
22
- : code_size(code_size), n_levels(n_levels), batch_size(batch_size) {
57
+ Panorama::Panorama(
58
+ size_t code_size_in,
59
+ size_t n_levels_in,
60
+ size_t batch_size_in)
61
+ : code_size(code_size_in),
62
+ n_levels(n_levels_in),
63
+ batch_size(batch_size_in) {
23
64
  set_derived_values();
24
65
  }
25
66
 
26
67
  void Panorama::set_derived_values() {
68
+ FAISS_THROW_IF_NOT_MSG(n_levels > 0, "Panorama: n_levels must be > 0");
27
69
  this->d = code_size / sizeof(float);
70
+ FAISS_THROW_IF_NOT_MSG(n_levels <= d, "Panorama: n_levels must be <= d");
28
71
  this->level_width_floats = ((d + n_levels - 1) / n_levels);
29
72
  this->level_width = this->level_width_floats * sizeof(float);
73
+ size_t n_real_levels = d / level_width_floats;
74
+ if (d > n_real_levels * level_width_floats) {
75
+ n_real_levels++;
76
+ }
77
+ if (this->n_levels != n_real_levels) {
78
+ fprintf(stderr,
79
+ "WARNING truncating nlevels from %zu to %zu\n",
80
+ this->n_levels,
81
+ n_real_levels);
82
+ this->n_levels = n_real_levels;
83
+ }
30
84
  }
31
85
 
32
86
  /**
@@ -69,64 +123,34 @@ void Panorama::compute_cumulative_sums(
69
123
  float* cumsum_base,
70
124
  size_t offset,
71
125
  size_t n_entry,
72
- const float* vectors) {
73
- std::vector<float> suffix_sums(d + 1);
74
-
126
+ const float* vectors) const {
75
127
  for (size_t entry_idx = 0; entry_idx < n_entry; entry_idx++) {
76
128
  size_t current_pos = offset + entry_idx;
77
129
  size_t batch_no = current_pos / batch_size;
78
130
  size_t pos_in_batch = current_pos % batch_size;
79
131
 
80
132
  const float* vector = vectors + entry_idx * d;
81
-
82
- // Compute suffix sums of squared values.
83
- suffix_sums[d] = 0.0f;
84
- for (int j = d - 1; j >= 0; j--) {
85
- float squared_val = vector[j] * vector[j];
86
- suffix_sums[j] = suffix_sums[j + 1] + squared_val;
87
- }
88
-
89
- // Store cumulative sums in batch-oriented layout.
90
133
  size_t cumsum_batch_offset = batch_no * batch_size * (n_levels + 1);
91
134
 
92
- for (size_t level = 0; level < n_levels; level++) {
93
- size_t start_idx = level * level_width_floats;
94
- size_t cumsum_offset =
95
- cumsum_batch_offset + level * batch_size + pos_in_batch;
96
- if (start_idx < d) {
97
- cumsum_base[cumsum_offset] = std::sqrt(suffix_sums[start_idx]);
98
- } else {
99
- cumsum_base[cumsum_offset] = 0.0f;
100
- }
101
- }
102
-
103
- // Last level sum is always 0.
104
- size_t cumsum_offset =
105
- cumsum_batch_offset + n_levels * batch_size + pos_in_batch;
106
- cumsum_base[cumsum_offset] = 0.0f;
135
+ auto get_offset = [&](size_t level) {
136
+ return cumsum_batch_offset + level * batch_size + pos_in_batch;
137
+ };
138
+
139
+ compute_cum_sums_impl(
140
+ vector,
141
+ cumsum_base,
142
+ d,
143
+ n_levels,
144
+ level_width_floats,
145
+ get_offset);
107
146
  }
108
147
  }
109
148
 
110
149
  void Panorama::compute_query_cum_sums(const float* query, float* query_cum_sums)
111
150
  const {
112
- std::vector<float> suffix_sums(d + 1);
113
- suffix_sums[d] = 0.0f;
114
-
115
- for (int j = d - 1; j >= 0; j--) {
116
- float squared_val = query[j] * query[j];
117
- suffix_sums[j] = suffix_sums[j + 1] + squared_val;
118
- }
119
-
120
- for (size_t level = 0; level < n_levels; level++) {
121
- size_t start_idx = level * level_width_floats;
122
- if (start_idx < d) {
123
- query_cum_sums[level] = std::sqrt(suffix_sums[start_idx]);
124
- } else {
125
- query_cum_sums[level] = 0.0f;
126
- }
127
- }
128
-
129
- query_cum_sums[n_levels] = 0.0f;
151
+ auto get_offset = [](size_t level) { return level; };
152
+ compute_cum_sums_impl(
153
+ query, query_cum_sums, d, n_levels, level_width_floats, get_offset);
130
154
  }
131
155
 
132
156
  void Panorama::reconstruct(idx_t key, float* recons, const uint8_t* codes_base)
@@ -139,12 +163,12 @@ void Panorama::reconstruct(idx_t key, float* recons, const uint8_t* codes_base)
139
163
 
140
164
  for (size_t level = 0; level < n_levels; level++) {
141
165
  size_t level_offset = level * level_width * batch_size;
166
+ size_t actual_level_width =
167
+ std::min(level_width, code_size - level * level_width);
142
168
  const uint8_t* src = codes_base + batch_offset + level_offset +
143
- pos_in_batch * level_width;
169
+ pos_in_batch * actual_level_width;
144
170
  uint8_t* dest = recons_buffer + level * level_width;
145
- size_t copy_size =
146
- std::min(level_width, code_size - level * level_width);
147
- memcpy(dest, src, copy_size);
171
+ memcpy(dest, src, actual_level_width);
148
172
  }
149
173
  }
150
174