faiss 0.3.1 → 0.3.3

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 (293) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/LICENSE.txt +1 -1
  4. data/lib/faiss/version.rb +1 -1
  5. data/vendor/faiss/faiss/AutoTune.cpp +2 -2
  6. data/vendor/faiss/faiss/AutoTune.h +3 -3
  7. data/vendor/faiss/faiss/Clustering.cpp +37 -6
  8. data/vendor/faiss/faiss/Clustering.h +12 -3
  9. data/vendor/faiss/faiss/IVFlib.cpp +6 -3
  10. data/vendor/faiss/faiss/IVFlib.h +2 -2
  11. data/vendor/faiss/faiss/Index.cpp +6 -2
  12. data/vendor/faiss/faiss/Index.h +30 -8
  13. data/vendor/faiss/faiss/Index2Layer.cpp +2 -2
  14. data/vendor/faiss/faiss/Index2Layer.h +2 -2
  15. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +7 -7
  16. data/vendor/faiss/faiss/IndexAdditiveQuantizer.h +2 -2
  17. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +14 -16
  18. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.h +2 -2
  19. data/vendor/faiss/faiss/IndexBinary.cpp +13 -2
  20. data/vendor/faiss/faiss/IndexBinary.h +8 -2
  21. data/vendor/faiss/faiss/IndexBinaryFlat.cpp +2 -3
  22. data/vendor/faiss/faiss/IndexBinaryFlat.h +2 -2
  23. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +2 -2
  24. data/vendor/faiss/faiss/IndexBinaryFromFloat.h +2 -2
  25. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +2 -7
  26. data/vendor/faiss/faiss/IndexBinaryHNSW.h +3 -3
  27. data/vendor/faiss/faiss/IndexBinaryHash.cpp +2 -3
  28. data/vendor/faiss/faiss/IndexBinaryHash.h +2 -2
  29. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +3 -3
  30. data/vendor/faiss/faiss/IndexBinaryIVF.h +2 -2
  31. data/vendor/faiss/faiss/IndexFastScan.cpp +32 -18
  32. data/vendor/faiss/faiss/IndexFastScan.h +11 -2
  33. data/vendor/faiss/faiss/IndexFlat.cpp +13 -10
  34. data/vendor/faiss/faiss/IndexFlat.h +2 -2
  35. data/vendor/faiss/faiss/IndexFlatCodes.cpp +170 -7
  36. data/vendor/faiss/faiss/IndexFlatCodes.h +25 -5
  37. data/vendor/faiss/faiss/IndexHNSW.cpp +156 -96
  38. data/vendor/faiss/faiss/IndexHNSW.h +54 -5
  39. data/vendor/faiss/faiss/IndexIDMap.cpp +19 -3
  40. data/vendor/faiss/faiss/IndexIDMap.h +5 -2
  41. data/vendor/faiss/faiss/IndexIVF.cpp +5 -6
  42. data/vendor/faiss/faiss/IndexIVF.h +13 -4
  43. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +21 -7
  44. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h +5 -2
  45. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +3 -14
  46. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h +2 -4
  47. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +201 -91
  48. data/vendor/faiss/faiss/IndexIVFFastScan.h +33 -9
  49. data/vendor/faiss/faiss/IndexIVFFlat.cpp +2 -2
  50. data/vendor/faiss/faiss/IndexIVFFlat.h +2 -2
  51. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +2 -2
  52. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.h +2 -2
  53. data/vendor/faiss/faiss/IndexIVFPQ.cpp +3 -6
  54. data/vendor/faiss/faiss/IndexIVFPQ.h +2 -2
  55. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +7 -14
  56. data/vendor/faiss/faiss/IndexIVFPQFastScan.h +2 -4
  57. data/vendor/faiss/faiss/IndexIVFPQR.cpp +2 -2
  58. data/vendor/faiss/faiss/IndexIVFPQR.h +2 -2
  59. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +2 -3
  60. data/vendor/faiss/faiss/IndexIVFSpectralHash.h +2 -2
  61. data/vendor/faiss/faiss/IndexLSH.cpp +2 -3
  62. data/vendor/faiss/faiss/IndexLSH.h +2 -2
  63. data/vendor/faiss/faiss/IndexLattice.cpp +3 -21
  64. data/vendor/faiss/faiss/IndexLattice.h +5 -24
  65. data/vendor/faiss/faiss/IndexNNDescent.cpp +2 -31
  66. data/vendor/faiss/faiss/IndexNNDescent.h +3 -3
  67. data/vendor/faiss/faiss/IndexNSG.cpp +2 -5
  68. data/vendor/faiss/faiss/IndexNSG.h +3 -3
  69. data/vendor/faiss/faiss/IndexNeuralNetCodec.cpp +56 -0
  70. data/vendor/faiss/faiss/IndexNeuralNetCodec.h +49 -0
  71. data/vendor/faiss/faiss/IndexPQ.cpp +26 -26
  72. data/vendor/faiss/faiss/IndexPQ.h +2 -2
  73. data/vendor/faiss/faiss/IndexPQFastScan.cpp +2 -5
  74. data/vendor/faiss/faiss/IndexPQFastScan.h +2 -11
  75. data/vendor/faiss/faiss/IndexPreTransform.cpp +2 -2
  76. data/vendor/faiss/faiss/IndexPreTransform.h +3 -3
  77. data/vendor/faiss/faiss/IndexRefine.cpp +46 -9
  78. data/vendor/faiss/faiss/IndexRefine.h +9 -2
  79. data/vendor/faiss/faiss/IndexReplicas.cpp +2 -2
  80. data/vendor/faiss/faiss/IndexReplicas.h +2 -2
  81. data/vendor/faiss/faiss/IndexRowwiseMinMax.cpp +2 -2
  82. data/vendor/faiss/faiss/IndexRowwiseMinMax.h +2 -2
  83. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +5 -4
  84. data/vendor/faiss/faiss/IndexScalarQuantizer.h +2 -2
  85. data/vendor/faiss/faiss/IndexShards.cpp +2 -2
  86. data/vendor/faiss/faiss/IndexShards.h +2 -2
  87. data/vendor/faiss/faiss/IndexShardsIVF.cpp +2 -2
  88. data/vendor/faiss/faiss/IndexShardsIVF.h +2 -2
  89. data/vendor/faiss/faiss/MatrixStats.cpp +2 -2
  90. data/vendor/faiss/faiss/MatrixStats.h +2 -2
  91. data/vendor/faiss/faiss/MetaIndexes.cpp +2 -3
  92. data/vendor/faiss/faiss/MetaIndexes.h +2 -2
  93. data/vendor/faiss/faiss/MetricType.h +9 -4
  94. data/vendor/faiss/faiss/VectorTransform.cpp +2 -2
  95. data/vendor/faiss/faiss/VectorTransform.h +2 -2
  96. data/vendor/faiss/faiss/clone_index.cpp +2 -2
  97. data/vendor/faiss/faiss/clone_index.h +2 -2
  98. data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +2 -2
  99. data/vendor/faiss/faiss/cppcontrib/detail/CoarseBitType.h +2 -2
  100. data/vendor/faiss/faiss/cppcontrib/detail/UintReader.h +97 -19
  101. data/vendor/faiss/faiss/cppcontrib/factory_tools.cpp +192 -0
  102. data/vendor/faiss/faiss/cppcontrib/factory_tools.h +29 -0
  103. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-avx2-inl.h +2 -2
  104. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-inl.h +85 -32
  105. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +2 -2
  106. data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMax-inl.h +2 -2
  107. data/vendor/faiss/faiss/cppcontrib/sa_decode/MinMaxFP16-inl.h +2 -2
  108. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-avx2-inl.h +2 -2
  109. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-inl.h +2 -2
  110. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +2 -2
  111. data/vendor/faiss/faiss/gpu/GpuAutoTune.cpp +2 -5
  112. data/vendor/faiss/faiss/gpu/GpuAutoTune.h +2 -2
  113. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +45 -13
  114. data/vendor/faiss/faiss/gpu/GpuCloner.h +2 -2
  115. data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +12 -6
  116. data/vendor/faiss/faiss/gpu/GpuDistance.h +11 -7
  117. data/vendor/faiss/faiss/gpu/GpuFaissAssert.h +3 -3
  118. data/vendor/faiss/faiss/gpu/GpuIcmEncoder.h +2 -2
  119. data/vendor/faiss/faiss/gpu/GpuIndex.h +10 -15
  120. data/vendor/faiss/faiss/gpu/GpuIndexBinaryFlat.h +2 -2
  121. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +285 -0
  122. data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +2 -2
  123. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +8 -2
  124. data/vendor/faiss/faiss/gpu/GpuIndexIVFFlat.h +4 -2
  125. data/vendor/faiss/faiss/gpu/GpuIndexIVFPQ.h +3 -3
  126. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +2 -2
  127. data/vendor/faiss/faiss/gpu/GpuIndicesOptions.h +2 -2
  128. data/vendor/faiss/faiss/gpu/GpuResources.cpp +7 -2
  129. data/vendor/faiss/faiss/gpu/GpuResources.h +11 -4
  130. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +66 -11
  131. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +15 -5
  132. data/vendor/faiss/faiss/gpu/impl/IndexUtils.h +2 -2
  133. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.cpp +28 -23
  134. data/vendor/faiss/faiss/gpu/impl/InterleavedCodes.h +2 -2
  135. data/vendor/faiss/faiss/gpu/impl/RemapIndices.cpp +2 -2
  136. data/vendor/faiss/faiss/gpu/impl/RemapIndices.h +2 -2
  137. data/vendor/faiss/faiss/gpu/perf/IndexWrapper-inl.h +2 -2
  138. data/vendor/faiss/faiss/gpu/perf/IndexWrapper.h +2 -2
  139. data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +8 -2
  140. data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +2 -3
  141. data/vendor/faiss/faiss/gpu/perf/WriteIndex.cpp +2 -2
  142. data/vendor/faiss/faiss/gpu/test/TestCodePacking.cpp +10 -7
  143. data/vendor/faiss/faiss/gpu/test/TestGpuIndexBinaryFlat.cpp +2 -2
  144. data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +54 -54
  145. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +144 -77
  146. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFPQ.cpp +51 -51
  147. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +2 -2
  148. data/vendor/faiss/faiss/gpu/test/TestGpuMemoryException.cpp +3 -3
  149. data/vendor/faiss/faiss/gpu/test/TestGpuResidualQuantizer.cpp +70 -0
  150. data/vendor/faiss/faiss/gpu/test/TestUtils.cpp +74 -4
  151. data/vendor/faiss/faiss/gpu/test/TestUtils.h +2 -2
  152. data/vendor/faiss/faiss/gpu/test/demo_ivfpq_indexing_gpu.cpp +3 -3
  153. data/vendor/faiss/faiss/gpu/utils/{RaftUtils.h → CuvsUtils.h} +12 -11
  154. data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +8 -2
  155. data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +2 -2
  156. data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.h +2 -2
  157. data/vendor/faiss/faiss/gpu/utils/StaticUtils.h +2 -2
  158. data/vendor/faiss/faiss/gpu/utils/Timer.cpp +6 -3
  159. data/vendor/faiss/faiss/gpu/utils/Timer.h +3 -3
  160. data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +79 -11
  161. data/vendor/faiss/faiss/impl/AdditiveQuantizer.h +17 -5
  162. data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +27 -2
  163. data/vendor/faiss/faiss/impl/AuxIndexStructures.h +11 -3
  164. data/vendor/faiss/faiss/impl/CodePacker.cpp +2 -2
  165. data/vendor/faiss/faiss/impl/CodePacker.h +2 -2
  166. data/vendor/faiss/faiss/impl/DistanceComputer.h +48 -2
  167. data/vendor/faiss/faiss/impl/FaissAssert.h +6 -4
  168. data/vendor/faiss/faiss/impl/FaissException.cpp +2 -2
  169. data/vendor/faiss/faiss/impl/FaissException.h +2 -3
  170. data/vendor/faiss/faiss/impl/HNSW.cpp +378 -205
  171. data/vendor/faiss/faiss/impl/HNSW.h +55 -24
  172. data/vendor/faiss/faiss/impl/IDSelector.cpp +2 -2
  173. data/vendor/faiss/faiss/impl/IDSelector.h +2 -2
  174. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +10 -10
  175. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.h +2 -2
  176. data/vendor/faiss/faiss/impl/LookupTableScaler.h +36 -2
  177. data/vendor/faiss/faiss/impl/NNDescent.cpp +15 -10
  178. data/vendor/faiss/faiss/impl/NNDescent.h +2 -2
  179. data/vendor/faiss/faiss/impl/NSG.cpp +26 -49
  180. data/vendor/faiss/faiss/impl/NSG.h +20 -8
  181. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +2 -2
  182. data/vendor/faiss/faiss/impl/PolysemousTraining.h +2 -2
  183. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.cpp +2 -4
  184. data/vendor/faiss/faiss/impl/ProductAdditiveQuantizer.h +2 -2
  185. data/vendor/faiss/faiss/impl/ProductQuantizer-inl.h +2 -2
  186. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +3 -2
  187. data/vendor/faiss/faiss/impl/ProductQuantizer.h +7 -3
  188. data/vendor/faiss/faiss/impl/Quantizer.h +2 -2
  189. data/vendor/faiss/faiss/impl/ResidualQuantizer.cpp +2 -36
  190. data/vendor/faiss/faiss/impl/ResidualQuantizer.h +3 -13
  191. data/vendor/faiss/faiss/impl/ResultHandler.h +153 -34
  192. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +721 -104
  193. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +5 -2
  194. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
  195. data/vendor/faiss/faiss/impl/ThreadedIndex.h +2 -2
  196. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx2.h +7 -2
  197. data/vendor/faiss/faiss/impl/code_distance/code_distance-avx512.h +248 -0
  198. data/vendor/faiss/faiss/impl/code_distance/code_distance-generic.h +2 -2
  199. data/vendor/faiss/faiss/impl/code_distance/code_distance-sve.h +440 -0
  200. data/vendor/faiss/faiss/impl/code_distance/code_distance.h +55 -2
  201. data/vendor/faiss/faiss/impl/index_read.cpp +31 -20
  202. data/vendor/faiss/faiss/impl/index_read_utils.h +37 -0
  203. data/vendor/faiss/faiss/impl/index_write.cpp +30 -16
  204. data/vendor/faiss/faiss/impl/io.cpp +15 -7
  205. data/vendor/faiss/faiss/impl/io.h +6 -6
  206. data/vendor/faiss/faiss/impl/io_macros.h +8 -9
  207. data/vendor/faiss/faiss/impl/kmeans1d.cpp +2 -3
  208. data/vendor/faiss/faiss/impl/kmeans1d.h +2 -2
  209. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +2 -3
  210. data/vendor/faiss/faiss/impl/lattice_Zn.h +2 -2
  211. data/vendor/faiss/faiss/impl/platform_macros.h +34 -2
  212. data/vendor/faiss/faiss/impl/pq4_fast_scan.cpp +13 -2
  213. data/vendor/faiss/faiss/impl/pq4_fast_scan.h +20 -2
  214. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_1.cpp +3 -3
  215. data/vendor/faiss/faiss/impl/pq4_fast_scan_search_qbs.cpp +450 -3
  216. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +8 -8
  217. data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h +3 -3
  218. data/vendor/faiss/faiss/impl/simd_result_handlers.h +151 -67
  219. data/vendor/faiss/faiss/index_factory.cpp +51 -34
  220. data/vendor/faiss/faiss/index_factory.h +2 -2
  221. data/vendor/faiss/faiss/index_io.h +14 -7
  222. data/vendor/faiss/faiss/invlists/BlockInvertedLists.cpp +30 -10
  223. data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +5 -2
  224. data/vendor/faiss/faiss/invlists/DirectMap.cpp +11 -3
  225. data/vendor/faiss/faiss/invlists/DirectMap.h +2 -2
  226. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +57 -19
  227. data/vendor/faiss/faiss/invlists/InvertedLists.h +20 -11
  228. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.cpp +2 -2
  229. data/vendor/faiss/faiss/invlists/InvertedListsIOHook.h +2 -2
  230. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +23 -9
  231. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +4 -3
  232. data/vendor/faiss/faiss/python/python_callbacks.cpp +5 -5
  233. data/vendor/faiss/faiss/python/python_callbacks.h +2 -2
  234. data/vendor/faiss/faiss/utils/AlignedTable.h +5 -3
  235. data/vendor/faiss/faiss/utils/Heap.cpp +2 -2
  236. data/vendor/faiss/faiss/utils/Heap.h +107 -2
  237. data/vendor/faiss/faiss/utils/NeuralNet.cpp +346 -0
  238. data/vendor/faiss/faiss/utils/NeuralNet.h +147 -0
  239. data/vendor/faiss/faiss/utils/WorkerThread.cpp +2 -2
  240. data/vendor/faiss/faiss/utils/WorkerThread.h +2 -2
  241. data/vendor/faiss/faiss/utils/approx_topk/approx_topk.h +2 -2
  242. data/vendor/faiss/faiss/utils/approx_topk/avx2-inl.h +2 -2
  243. data/vendor/faiss/faiss/utils/approx_topk/generic.h +2 -2
  244. data/vendor/faiss/faiss/utils/approx_topk/mode.h +2 -2
  245. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +2 -2
  246. data/vendor/faiss/faiss/utils/bf16.h +36 -0
  247. data/vendor/faiss/faiss/utils/distances.cpp +249 -90
  248. data/vendor/faiss/faiss/utils/distances.h +8 -8
  249. data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +2 -2
  250. data/vendor/faiss/faiss/utils/distances_fused/avx512.h +2 -2
  251. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +2 -2
  252. data/vendor/faiss/faiss/utils/distances_fused/distances_fused.h +2 -2
  253. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +2 -2
  254. data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.h +2 -2
  255. data/vendor/faiss/faiss/utils/distances_simd.cpp +1543 -56
  256. data/vendor/faiss/faiss/utils/extra_distances-inl.h +72 -2
  257. data/vendor/faiss/faiss/utils/extra_distances.cpp +87 -140
  258. data/vendor/faiss/faiss/utils/extra_distances.h +5 -4
  259. data/vendor/faiss/faiss/utils/fp16-arm.h +2 -2
  260. data/vendor/faiss/faiss/utils/fp16-fp16c.h +2 -2
  261. data/vendor/faiss/faiss/utils/fp16-inl.h +2 -2
  262. data/vendor/faiss/faiss/utils/fp16.h +2 -2
  263. data/vendor/faiss/faiss/utils/hamming-inl.h +2 -2
  264. data/vendor/faiss/faiss/utils/hamming.cpp +3 -4
  265. data/vendor/faiss/faiss/utils/hamming.h +2 -2
  266. data/vendor/faiss/faiss/utils/hamming_distance/avx2-inl.h +2 -2
  267. data/vendor/faiss/faiss/utils/hamming_distance/avx512-inl.h +490 -0
  268. data/vendor/faiss/faiss/utils/hamming_distance/common.h +2 -2
  269. data/vendor/faiss/faiss/utils/hamming_distance/generic-inl.h +6 -3
  270. data/vendor/faiss/faiss/utils/hamming_distance/hamdis-inl.h +7 -3
  271. data/vendor/faiss/faiss/utils/hamming_distance/neon-inl.h +5 -5
  272. data/vendor/faiss/faiss/utils/ordered_key_value.h +2 -2
  273. data/vendor/faiss/faiss/utils/partitioning.cpp +2 -2
  274. data/vendor/faiss/faiss/utils/partitioning.h +2 -2
  275. data/vendor/faiss/faiss/utils/prefetch.h +2 -2
  276. data/vendor/faiss/faiss/utils/quantize_lut.cpp +2 -2
  277. data/vendor/faiss/faiss/utils/quantize_lut.h +2 -2
  278. data/vendor/faiss/faiss/utils/random.cpp +45 -2
  279. data/vendor/faiss/faiss/utils/random.h +27 -2
  280. data/vendor/faiss/faiss/utils/simdlib.h +12 -3
  281. data/vendor/faiss/faiss/utils/simdlib_avx2.h +2 -2
  282. data/vendor/faiss/faiss/utils/simdlib_avx512.h +296 -0
  283. data/vendor/faiss/faiss/utils/simdlib_emulated.h +2 -2
  284. data/vendor/faiss/faiss/utils/simdlib_neon.h +7 -4
  285. data/vendor/faiss/faiss/utils/simdlib_ppc64.h +1084 -0
  286. data/vendor/faiss/faiss/utils/sorting.cpp +2 -2
  287. data/vendor/faiss/faiss/utils/sorting.h +2 -2
  288. data/vendor/faiss/faiss/utils/transpose/transpose-avx2-inl.h +2 -2
  289. data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +176 -0
  290. data/vendor/faiss/faiss/utils/utils.cpp +17 -10
  291. data/vendor/faiss/faiss/utils/utils.h +7 -3
  292. metadata +22 -11
  293. data/vendor/faiss/faiss/impl/code_distance/code_distance_avx512.h +0 -102
@@ -1,5 +1,5 @@
1
- /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -23,7 +23,6 @@
23
23
  #include <faiss/impl/pq4_fast_scan.h>
24
24
  #include <faiss/impl/simd_result_handlers.h>
25
25
  #include <faiss/invlists/BlockInvertedLists.h>
26
- #include <faiss/utils/distances.h>
27
26
  #include <faiss/utils/hamming.h>
28
27
  #include <faiss/utils/quantize_lut.h>
29
28
  #include <faiss/utils/utils.h>
@@ -56,20 +55,24 @@ IndexIVFFastScan::IndexIVFFastScan() {
56
55
  }
57
56
 
58
57
  void IndexIVFFastScan::init_fastscan(
58
+ Quantizer* fine_quantizer,
59
59
  size_t M,
60
- size_t nbits,
60
+ size_t nbits_init,
61
61
  size_t nlist,
62
62
  MetricType /* metric */,
63
- int bbs) {
64
- FAISS_THROW_IF_NOT(bbs % 32 == 0);
65
- FAISS_THROW_IF_NOT(nbits == 4);
63
+ int bbs_2) {
64
+ FAISS_THROW_IF_NOT(bbs_2 % 32 == 0);
65
+ FAISS_THROW_IF_NOT(nbits_init == 4);
66
+ FAISS_THROW_IF_NOT(fine_quantizer->d == d);
66
67
 
68
+ this->fine_quantizer = fine_quantizer;
67
69
  this->M = M;
68
- this->nbits = nbits;
69
- this->bbs = bbs;
70
- ksub = (1 << nbits);
70
+ this->nbits = nbits_init;
71
+ this->bbs = bbs_2;
72
+ ksub = (1 << nbits_init);
71
73
  M2 = roundup(M, 2);
72
74
  code_size = M2 / 2;
75
+ FAISS_THROW_IF_NOT(code_size == fine_quantizer->code_size);
73
76
 
74
77
  is_trained = false;
75
78
  replace_invlists(new BlockInvertedLists(nlist, get_CodePacker()), true);
@@ -211,7 +214,7 @@ void estimators_from_tables_generic(
211
214
  int64_t* heap_ids,
212
215
  const NormTableScaler* scaler) {
213
216
  using accu_t = typename C::T;
214
- int nscale = scaler ? scaler->nscale : 0;
217
+ size_t nscale = scaler ? scaler->nscale : 0;
215
218
  for (size_t j = 0; j < ncodes; ++j) {
216
219
  BitstringReader bsr(codes + j * index.code_size, index.code_size);
217
220
  accu_t dis = bias;
@@ -270,6 +273,7 @@ void IndexIVFFastScan::compute_LUT_uint8(
270
273
  biases.resize(n * nprobe);
271
274
  }
272
275
 
276
+ // OMP for MSVC requires i to have signed integral type
273
277
  #pragma omp parallel for if (n > 100)
274
278
  for (int64_t i = 0; i < n; i++) {
275
279
  const float* t_in = dis_tables_float.get() + i * dim123;
@@ -306,11 +310,16 @@ void IndexIVFFastScan::search(
306
310
  idx_t k,
307
311
  float* distances,
308
312
  idx_t* labels,
309
- const SearchParameters* params) const {
310
- auto paramsi = dynamic_cast<const SearchParametersIVF*>(params);
311
- FAISS_THROW_IF_NOT_MSG(!params || paramsi, "need IVFSearchParameters");
313
+ const SearchParameters* params_in) const {
314
+ const IVFSearchParameters* params = nullptr;
315
+ if (params_in) {
316
+ params = dynamic_cast<const IVFSearchParameters*>(params_in);
317
+ FAISS_THROW_IF_NOT_MSG(
318
+ params, "IndexIVFFastScan params have incorrect type");
319
+ }
320
+
312
321
  search_preassigned(
313
- n, x, k, nullptr, nullptr, distances, labels, false, paramsi);
322
+ n, x, k, nullptr, nullptr, distances, labels, false, params);
314
323
  }
315
324
 
316
325
  void IndexIVFFastScan::search_preassigned(
@@ -326,18 +335,17 @@ void IndexIVFFastScan::search_preassigned(
326
335
  IndexIVFStats* stats) const {
327
336
  size_t nprobe = this->nprobe;
328
337
  if (params) {
329
- FAISS_THROW_IF_NOT_MSG(
330
- !params->quantizer_params, "quantizer params not supported");
331
338
  FAISS_THROW_IF_NOT(params->max_codes == 0);
332
339
  nprobe = params->nprobe;
333
340
  }
341
+
334
342
  FAISS_THROW_IF_NOT_MSG(
335
343
  !store_pairs, "store_pairs not supported for this index");
336
344
  FAISS_THROW_IF_NOT_MSG(!stats, "stats not supported for this index");
337
345
  FAISS_THROW_IF_NOT(k > 0);
338
346
 
339
347
  const CoarseQuantized cq = {nprobe, centroid_dis, assign};
340
- search_dispatch_implem(n, x, k, distances, labels, cq, nullptr);
348
+ search_dispatch_implem(n, x, k, distances, labels, cq, nullptr, params);
341
349
  }
342
350
 
343
351
  void IndexIVFFastScan::range_search(
@@ -345,10 +353,18 @@ void IndexIVFFastScan::range_search(
345
353
  const float* x,
346
354
  float radius,
347
355
  RangeSearchResult* result,
348
- const SearchParameters* params) const {
349
- FAISS_THROW_IF_NOT(!params);
356
+ const SearchParameters* params_in) const {
357
+ size_t nprobe = this->nprobe;
358
+ const IVFSearchParameters* params = nullptr;
359
+ if (params_in) {
360
+ params = dynamic_cast<const IVFSearchParameters*>(params_in);
361
+ FAISS_THROW_IF_NOT_MSG(
362
+ params, "IndexIVFFastScan params have incorrect type");
363
+ nprobe = params->nprobe;
364
+ }
365
+
350
366
  const CoarseQuantized cq = {nprobe, nullptr, nullptr};
351
- range_search_dispatch_implem(n, x, radius, *result, cq, nullptr);
367
+ range_search_dispatch_implem(n, x, radius, *result, cq, nullptr, params);
352
368
  }
353
369
 
354
370
  namespace {
@@ -359,17 +375,18 @@ ResultHandlerCompare<C, true>* make_knn_handler_fixC(
359
375
  idx_t n,
360
376
  idx_t k,
361
377
  float* distances,
362
- idx_t* labels) {
378
+ idx_t* labels,
379
+ const IDSelector* sel) {
363
380
  using HeapHC = HeapHandler<C, true>;
364
381
  using ReservoirHC = ReservoirHandler<C, true>;
365
382
  using SingleResultHC = SingleResultHandler<C, true>;
366
383
 
367
384
  if (k == 1) {
368
- return new SingleResultHC(n, 0, distances, labels);
385
+ return new SingleResultHC(n, 0, distances, labels, sel);
369
386
  } else if (impl % 2 == 0) {
370
- return new HeapHC(n, 0, k, distances, labels);
387
+ return new HeapHC(n, 0, k, distances, labels, sel);
371
388
  } else /* if (impl % 2 == 1) */ {
372
- return new ReservoirHC(n, 0, k, 2 * k, distances, labels);
389
+ return new ReservoirHC(n, 0, k, 2 * k, distances, labels, sel);
373
390
  }
374
391
  }
375
392
 
@@ -379,13 +396,14 @@ SIMDResultHandlerToFloat* make_knn_handler(
379
396
  idx_t n,
380
397
  idx_t k,
381
398
  float* distances,
382
- idx_t* labels) {
399
+ idx_t* labels,
400
+ const IDSelector* sel) {
383
401
  if (is_max) {
384
402
  return make_knn_handler_fixC<CMax<uint16_t, int64_t>>(
385
- impl, n, k, distances, labels);
403
+ impl, n, k, distances, labels, sel);
386
404
  } else {
387
405
  return make_knn_handler_fixC<CMin<uint16_t, int64_t>>(
388
- impl, n, k, distances, labels);
406
+ impl, n, k, distances, labels, sel);
389
407
  }
390
408
  }
391
409
 
@@ -402,10 +420,20 @@ struct CoarseQuantizedWithBuffer : CoarseQuantized {
402
420
  std::vector<idx_t> ids_buffer;
403
421
  std::vector<float> dis_buffer;
404
422
 
405
- void quantize(const Index* quantizer, idx_t n, const float* x) {
423
+ void quantize(
424
+ const Index* quantizer,
425
+ idx_t n,
426
+ const float* x,
427
+ const SearchParameters* quantizer_params) {
406
428
  dis_buffer.resize(nprobe * n);
407
429
  ids_buffer.resize(nprobe * n);
408
- quantizer->search(n, x, nprobe, dis_buffer.data(), ids_buffer.data());
430
+ quantizer->search(
431
+ n,
432
+ x,
433
+ nprobe,
434
+ dis_buffer.data(),
435
+ ids_buffer.data(),
436
+ quantizer_params);
409
437
  dis = dis_buffer.data();
410
438
  ids = ids_buffer.data();
411
439
  }
@@ -421,8 +449,11 @@ struct CoarseQuantizedSlice : CoarseQuantizedWithBuffer {
421
449
  }
422
450
  }
423
451
 
424
- void quantize_slice(const Index* quantizer, const float* x) {
425
- quantize(quantizer, i1 - i0, x + quantizer->d * i0);
452
+ void quantize_slice(
453
+ const Index* quantizer,
454
+ const float* x,
455
+ const SearchParameters* quantizer_params) {
456
+ quantize(quantizer, i1 - i0, x + quantizer->d * i0, quantizer_params);
426
457
  }
427
458
  };
428
459
 
@@ -459,7 +490,13 @@ void IndexIVFFastScan::search_dispatch_implem(
459
490
  float* distances,
460
491
  idx_t* labels,
461
492
  const CoarseQuantized& cq_in,
462
- const NormTableScaler* scaler) const {
493
+ const NormTableScaler* scaler,
494
+ const IVFSearchParameters* params) const {
495
+ const idx_t nprobe = params ? params->nprobe : this->nprobe;
496
+ const IDSelector* sel = (params) ? params->sel : nullptr;
497
+ const SearchParameters* quantizer_params =
498
+ params ? params->quantizer_params : nullptr;
499
+
463
500
  bool is_max = !is_similarity_metric(metric_type);
464
501
  using RH = SIMDResultHandlerToFloat;
465
502
 
@@ -489,52 +526,70 @@ void IndexIVFFastScan::search_dispatch_implem(
489
526
  }
490
527
 
491
528
  CoarseQuantizedWithBuffer cq(cq_in);
529
+ cq.nprobe = nprobe;
492
530
 
493
531
  if (!cq.done() && !multiple_threads) {
494
532
  // we do the coarse quantization here execpt when search is
495
533
  // sliced over threads (then it is more efficient to have each thread do
496
534
  // its own coarse quantization)
497
- cq.quantize(quantizer, n, x);
535
+ cq.quantize(quantizer, n, x, quantizer_params);
536
+ invlists->prefetch_lists(cq.ids, n * cq.nprobe);
498
537
  }
499
538
 
500
539
  if (impl == 1) {
501
540
  if (is_max) {
502
541
  search_implem_1<CMax<float, int64_t>>(
503
- n, x, k, distances, labels, cq, scaler);
542
+ n, x, k, distances, labels, cq, scaler, params);
504
543
  } else {
505
544
  search_implem_1<CMin<float, int64_t>>(
506
- n, x, k, distances, labels, cq, scaler);
545
+ n, x, k, distances, labels, cq, scaler, params);
507
546
  }
508
547
  } else if (impl == 2) {
509
548
  if (is_max) {
510
549
  search_implem_2<CMax<uint16_t, int64_t>>(
511
- n, x, k, distances, labels, cq, scaler);
550
+ n, x, k, distances, labels, cq, scaler, params);
512
551
  } else {
513
552
  search_implem_2<CMin<uint16_t, int64_t>>(
514
- n, x, k, distances, labels, cq, scaler);
553
+ n, x, k, distances, labels, cq, scaler, params);
515
554
  }
516
-
517
555
  } else if (impl >= 10 && impl <= 15) {
518
556
  size_t ndis = 0, nlist_visited = 0;
519
557
 
520
558
  if (!multiple_threads) {
521
559
  // clang-format off
522
560
  if (impl == 12 || impl == 13) {
523
- std::unique_ptr<RH> handler(make_knn_handler(is_max, impl, n, k, distances, labels));
561
+ std::unique_ptr<RH> handler(
562
+ make_knn_handler(
563
+ is_max,
564
+ impl,
565
+ n,
566
+ k,
567
+ distances,
568
+ labels, sel
569
+ )
570
+ );
524
571
  search_implem_12(
525
572
  n, x, *handler.get(),
526
- cq, &ndis, &nlist_visited, scaler);
527
-
573
+ cq, &ndis, &nlist_visited, scaler, params);
528
574
  } else if (impl == 14 || impl == 15) {
529
-
530
575
  search_implem_14(
531
576
  n, x, k, distances, labels,
532
- cq, impl, scaler);
577
+ cq, impl, scaler, params);
533
578
  } else {
534
- std::unique_ptr<RH> handler(make_knn_handler(is_max, impl, n, k, distances, labels));
579
+ std::unique_ptr<RH> handler(
580
+ make_knn_handler(
581
+ is_max,
582
+ impl,
583
+ n,
584
+ k,
585
+ distances,
586
+ labels,
587
+ sel
588
+ )
589
+ );
535
590
  search_implem_10(
536
591
  n, x, *handler.get(), cq,
537
- &ndis, &nlist_visited, scaler);
592
+ &ndis, &nlist_visited, scaler, params);
538
593
  }
539
594
  // clang-format on
540
595
  } else {
@@ -543,7 +598,8 @@ void IndexIVFFastScan::search_dispatch_implem(
543
598
  if (impl == 14 || impl == 15) {
544
599
  // this might require slicing if there are too
545
600
  // many queries (for now we keep this simple)
546
- search_implem_14(n, x, k, distances, labels, cq, impl, scaler);
601
+ search_implem_14(
602
+ n, x, k, distances, labels, cq, impl, scaler, params);
547
603
  } else {
548
604
  #pragma omp parallel for reduction(+ : ndis, nlist_visited)
549
605
  for (int slice = 0; slice < nslice; slice++) {
@@ -553,19 +609,19 @@ void IndexIVFFastScan::search_dispatch_implem(
553
609
  idx_t* lab_i = labels + i0 * k;
554
610
  CoarseQuantizedSlice cq_i(cq, i0, i1);
555
611
  if (!cq_i.done()) {
556
- cq_i.quantize_slice(quantizer, x);
612
+ cq_i.quantize_slice(quantizer, x, quantizer_params);
557
613
  }
558
614
  std::unique_ptr<RH> handler(make_knn_handler(
559
- is_max, impl, i1 - i0, k, dis_i, lab_i));
615
+ is_max, impl, i1 - i0, k, dis_i, lab_i, sel));
560
616
  // clang-format off
561
617
  if (impl == 12 || impl == 13) {
562
618
  search_implem_12(
563
619
  i1 - i0, x + i0 * d, *handler.get(),
564
- cq_i, &ndis, &nlist_visited, scaler);
620
+ cq_i, &ndis, &nlist_visited, scaler, params);
565
621
  } else {
566
622
  search_implem_10(
567
623
  i1 - i0, x + i0 * d, *handler.get(),
568
- cq_i, &ndis, &nlist_visited, scaler);
624
+ cq_i, &ndis, &nlist_visited, scaler, params);
569
625
  }
570
626
  // clang-format on
571
627
  }
@@ -585,7 +641,13 @@ void IndexIVFFastScan::range_search_dispatch_implem(
585
641
  float radius,
586
642
  RangeSearchResult& rres,
587
643
  const CoarseQuantized& cq_in,
588
- const NormTableScaler* scaler) const {
644
+ const NormTableScaler* scaler,
645
+ const IVFSearchParameters* params) const {
646
+ // const idx_t nprobe = params ? params->nprobe : this->nprobe;
647
+ const IDSelector* sel = (params) ? params->sel : nullptr;
648
+ const SearchParameters* quantizer_params =
649
+ params ? params->quantizer_params : nullptr;
650
+
589
651
  bool is_max = !is_similarity_metric(metric_type);
590
652
 
591
653
  if (n == 0) {
@@ -613,7 +675,8 @@ void IndexIVFFastScan::range_search_dispatch_implem(
613
675
  }
614
676
 
615
677
  if (!multiple_threads && !cq.done()) {
616
- cq.quantize(quantizer, n, x);
678
+ cq.quantize(quantizer, n, x, quantizer_params);
679
+ invlists->prefetch_lists(cq.ids, n * cq.nprobe);
617
680
  }
618
681
 
619
682
  size_t ndis = 0, nlist_visited = 0;
@@ -622,10 +685,10 @@ void IndexIVFFastScan::range_search_dispatch_implem(
622
685
  std::unique_ptr<SIMDResultHandlerToFloat> handler;
623
686
  if (is_max) {
624
687
  handler.reset(new RangeHandler<CMax<uint16_t, int64_t>, true>(
625
- rres, radius, 0));
688
+ rres, radius, 0, sel));
626
689
  } else {
627
690
  handler.reset(new RangeHandler<CMin<uint16_t, int64_t>, true>(
628
- rres, radius, 0));
691
+ rres, radius, 0, sel));
629
692
  }
630
693
  if (impl == 12) {
631
694
  search_implem_12(
@@ -634,7 +697,7 @@ void IndexIVFFastScan::range_search_dispatch_implem(
634
697
  search_implem_10(
635
698
  n, x, *handler.get(), cq, &ndis, &nlist_visited, scaler);
636
699
  } else {
637
- FAISS_THROW_FMT("Range search implem %d not impemented", impl);
700
+ FAISS_THROW_FMT("Range search implem %d not implemented", impl);
638
701
  }
639
702
  } else {
640
703
  // explicitly slice over threads
@@ -649,17 +712,17 @@ void IndexIVFFastScan::range_search_dispatch_implem(
649
712
  idx_t i1 = n * (slice + 1) / nslice;
650
713
  CoarseQuantizedSlice cq_i(cq, i0, i1);
651
714
  if (!cq_i.done()) {
652
- cq_i.quantize_slice(quantizer, x);
715
+ cq_i.quantize_slice(quantizer, x, quantizer_params);
653
716
  }
654
717
  std::unique_ptr<SIMDResultHandlerToFloat> handler;
655
718
  if (is_max) {
656
719
  handler.reset(new PartialRangeHandler<
657
720
  CMax<uint16_t, int64_t>,
658
- true>(pres, radius, 0, i0, i1));
721
+ true>(pres, radius, 0, i0, i1, sel));
659
722
  } else {
660
723
  handler.reset(new PartialRangeHandler<
661
724
  CMin<uint16_t, int64_t>,
662
- true>(pres, radius, 0, i0, i1));
725
+ true>(pres, radius, 0, i0, i1, sel));
663
726
  }
664
727
 
665
728
  if (impl == 12 || impl == 13) {
@@ -670,7 +733,8 @@ void IndexIVFFastScan::range_search_dispatch_implem(
670
733
  cq_i,
671
734
  &ndis,
672
735
  &nlist_visited,
673
- scaler);
736
+ scaler,
737
+ params);
674
738
  } else {
675
739
  search_implem_10(
676
740
  i1 - i0,
@@ -679,7 +743,8 @@ void IndexIVFFastScan::range_search_dispatch_implem(
679
743
  cq_i,
680
744
  &ndis,
681
745
  &nlist_visited,
682
- scaler);
746
+ scaler,
747
+ params);
683
748
  }
684
749
  }
685
750
  pres.finalize();
@@ -699,7 +764,8 @@ void IndexIVFFastScan::search_implem_1(
699
764
  float* distances,
700
765
  idx_t* labels,
701
766
  const CoarseQuantized& cq,
702
- const NormTableScaler* scaler) const {
767
+ const NormTableScaler* scaler,
768
+ const IVFSearchParameters* params) const {
703
769
  FAISS_THROW_IF_NOT(orig_invlists);
704
770
 
705
771
  size_t dim12 = ksub * M;
@@ -766,7 +832,8 @@ void IndexIVFFastScan::search_implem_2(
766
832
  float* distances,
767
833
  idx_t* labels,
768
834
  const CoarseQuantized& cq,
769
- const NormTableScaler* scaler) const {
835
+ const NormTableScaler* scaler,
836
+ const IVFSearchParameters* params) const {
770
837
  FAISS_THROW_IF_NOT(orig_invlists);
771
838
 
772
839
  size_t dim12 = ksub * M2;
@@ -848,7 +915,8 @@ void IndexIVFFastScan::search_implem_10(
848
915
  const CoarseQuantized& cq,
849
916
  size_t* ndis_out,
850
917
  size_t* nlist_out,
851
- const NormTableScaler* scaler) const {
918
+ const NormTableScaler* scaler,
919
+ const IVFSearchParameters* params) const {
852
920
  size_t dim12 = ksub * M2;
853
921
  AlignedTable<uint8_t> dis_tables;
854
922
  AlignedTable<uint16_t> biases;
@@ -909,6 +977,7 @@ void IndexIVFFastScan::search_implem_10(
909
977
  ndis++;
910
978
  }
911
979
  }
980
+
912
981
  handler.end();
913
982
  *ndis_out = ndis;
914
983
  *nlist_out = nlist;
@@ -921,7 +990,8 @@ void IndexIVFFastScan::search_implem_12(
921
990
  const CoarseQuantized& cq,
922
991
  size_t* ndis_out,
923
992
  size_t* nlist_out,
924
- const NormTableScaler* scaler) const {
993
+ const NormTableScaler* scaler,
994
+ const IVFSearchParameters* params) const {
925
995
  if (n == 0) { // does not work well with reservoir
926
996
  return;
927
997
  }
@@ -933,6 +1003,7 @@ void IndexIVFFastScan::search_implem_12(
933
1003
  std::unique_ptr<float[]> normalizers(new float[2 * n]);
934
1004
 
935
1005
  compute_LUT_uint8(n, x, cq, dis_tables, biases, normalizers.get());
1006
+
936
1007
  handler.begin(skip & 16 ? nullptr : normalizers.get());
937
1008
 
938
1009
  struct QC {
@@ -958,13 +1029,14 @@ void IndexIVFFastScan::search_implem_12(
958
1029
  return a.list_no < b.list_no;
959
1030
  });
960
1031
  }
1032
+
961
1033
  // prepare the result handlers
962
1034
 
963
- int qbs2 = this->qbs2 ? this->qbs2 : 11;
1035
+ int actual_qbs2 = this->qbs2 ? this->qbs2 : 11;
964
1036
 
965
1037
  std::vector<uint16_t> tmp_bias;
966
1038
  if (biases.get()) {
967
- tmp_bias.resize(qbs2);
1039
+ tmp_bias.resize(actual_qbs2);
968
1040
  handler.dbias = tmp_bias.data();
969
1041
  }
970
1042
 
@@ -977,7 +1049,7 @@ void IndexIVFFastScan::search_implem_12(
977
1049
  int list_no = qcs[i0].list_no;
978
1050
  size_t i1 = i0 + 1;
979
1051
 
980
- while (i1 < qcs.size() && i1 < i0 + qbs2) {
1052
+ while (i1 < qcs.size() && i1 < i0 + actual_qbs2) {
981
1053
  if (qcs[i1].list_no != list_no) {
982
1054
  break;
983
1055
  }
@@ -997,7 +1069,7 @@ void IndexIVFFastScan::search_implem_12(
997
1069
  std::vector<int> q_map(nc), lut_entries(nc);
998
1070
  AlignedTable<uint8_t> LUT(nc * dim12);
999
1071
  memset(LUT.get(), -1, nc * dim12);
1000
- int qbs = pq4_preferred_qbs(nc);
1072
+ int qbs_for_list = pq4_preferred_qbs(nc);
1001
1073
 
1002
1074
  for (size_t i = i0; i < i1; i++) {
1003
1075
  const QC& qc = qcs[i];
@@ -1009,7 +1081,11 @@ void IndexIVFFastScan::search_implem_12(
1009
1081
  }
1010
1082
  }
1011
1083
  pq4_pack_LUT_qbs_q_map(
1012
- qbs, M2, dis_tables.get(), lut_entries.data(), LUT.get());
1084
+ qbs_for_list,
1085
+ M2,
1086
+ dis_tables.get(),
1087
+ lut_entries.data(),
1088
+ LUT.get());
1013
1089
 
1014
1090
  // access the inverted list
1015
1091
 
@@ -1025,7 +1101,13 @@ void IndexIVFFastScan::search_implem_12(
1025
1101
  handler.id_map = ids.get();
1026
1102
 
1027
1103
  pq4_accumulate_loop_qbs(
1028
- qbs, list_size, M2, codes.get(), LUT.get(), handler, scaler);
1104
+ qbs_for_list,
1105
+ list_size,
1106
+ M2,
1107
+ codes.get(),
1108
+ LUT.get(),
1109
+ handler,
1110
+ scaler);
1029
1111
  // prepare for next loop
1030
1112
  i0 = i1;
1031
1113
  }
@@ -1049,12 +1131,15 @@ void IndexIVFFastScan::search_implem_14(
1049
1131
  idx_t* labels,
1050
1132
  const CoarseQuantized& cq,
1051
1133
  int impl,
1052
- const NormTableScaler* scaler) const {
1134
+ const NormTableScaler* scaler,
1135
+ const IVFSearchParameters* params) const {
1053
1136
  if (n == 0) { // does not work well with reservoir
1054
1137
  return;
1055
1138
  }
1056
1139
  FAISS_THROW_IF_NOT(bbs == 32);
1057
1140
 
1141
+ const IDSelector* sel = params ? params->sel : nullptr;
1142
+
1058
1143
  size_t dim12 = ksub * M2;
1059
1144
  AlignedTable<uint8_t> dis_tables;
1060
1145
  AlignedTable<uint16_t> biases;
@@ -1157,16 +1242,17 @@ void IndexIVFFastScan::search_implem_14(
1157
1242
 
1158
1243
  // prepare the result handlers
1159
1244
  std::unique_ptr<SIMDResultHandlerToFloat> handler(make_knn_handler(
1160
- is_max, impl, n, k, local_dis.data(), local_idx.data()));
1245
+ is_max, impl, n, k, local_dis.data(), local_idx.data(), sel));
1161
1246
  handler->begin(normalizers.get());
1162
1247
 
1163
- int qbs2 = this->qbs2 ? this->qbs2 : 11;
1248
+ int actual_qbs2 = this->qbs2 ? this->qbs2 : 11;
1164
1249
 
1165
1250
  std::vector<uint16_t> tmp_bias;
1166
1251
  if (biases.get()) {
1167
- tmp_bias.resize(qbs2);
1252
+ tmp_bias.resize(actual_qbs2);
1168
1253
  handler->dbias = tmp_bias.data();
1169
1254
  }
1255
+
1170
1256
  std::set<int> q_set;
1171
1257
  uint64_t t_copy_pack = 0, t_scan = 0;
1172
1258
  #pragma omp for schedule(dynamic)
@@ -1183,7 +1269,7 @@ void IndexIVFFastScan::search_implem_14(
1183
1269
  std::vector<int> q_map(nc), lut_entries(nc);
1184
1270
  AlignedTable<uint8_t> LUT(nc * dim12);
1185
1271
  memset(LUT.get(), -1, nc * dim12);
1186
- int qbs = pq4_preferred_qbs(nc);
1272
+ int qbs_for_list = pq4_preferred_qbs(nc);
1187
1273
 
1188
1274
  for (size_t i = i0; i < i1; i++) {
1189
1275
  const QC& qc = qcs[i];
@@ -1196,7 +1282,11 @@ void IndexIVFFastScan::search_implem_14(
1196
1282
  }
1197
1283
  }
1198
1284
  pq4_pack_LUT_qbs_q_map(
1199
- qbs, M2, dis_tables.get(), lut_entries.data(), LUT.get());
1285
+ qbs_for_list,
1286
+ M2,
1287
+ dis_tables.get(),
1288
+ lut_entries.data(),
1289
+ LUT.get());
1200
1290
 
1201
1291
  // access the inverted list
1202
1292
 
@@ -1212,7 +1302,7 @@ void IndexIVFFastScan::search_implem_14(
1212
1302
  handler->id_map = ids.get();
1213
1303
 
1214
1304
  pq4_accumulate_loop_qbs(
1215
- qbs,
1305
+ qbs_for_list,
1216
1306
  list_size,
1217
1307
  M2,
1218
1308
  codes.get(),
@@ -1267,34 +1357,30 @@ void IndexIVFFastScan::reconstruct_from_offset(
1267
1357
  int64_t offset,
1268
1358
  float* recons) const {
1269
1359
  // unpack codes
1360
+ size_t coarse_size = coarse_code_size();
1361
+ std::vector<uint8_t> code(coarse_size + code_size, 0);
1362
+ encode_listno(list_no, code.data());
1270
1363
  InvertedLists::ScopedCodes list_codes(invlists, list_no);
1271
- std::vector<uint8_t> code(code_size, 0);
1272
- BitstringWriter bsw(code.data(), code_size);
1364
+ BitstringWriter bsw(code.data() + coarse_size, code_size);
1365
+
1273
1366
  for (size_t m = 0; m < M; m++) {
1274
1367
  uint8_t c =
1275
1368
  pq4_get_packed_element(list_codes.get(), bbs, M2, offset, m);
1276
1369
  bsw.write(c, nbits);
1277
1370
  }
1278
- sa_decode(1, code.data(), recons);
1279
1371
 
1280
- // add centroid to it
1281
- if (by_residual) {
1282
- std::vector<float> centroid(d);
1283
- quantizer->reconstruct(list_no, centroid.data());
1284
- for (int i = 0; i < d; ++i) {
1285
- recons[i] += centroid[i];
1286
- }
1287
- }
1372
+ sa_decode(1, code.data(), recons);
1288
1373
  }
1289
1374
 
1290
1375
  void IndexIVFFastScan::reconstruct_orig_invlists() {
1291
1376
  FAISS_THROW_IF_NOT(orig_invlists != nullptr);
1292
1377
  FAISS_THROW_IF_NOT(orig_invlists->list_size(0) == 0);
1293
1378
 
1294
- for (size_t list_no = 0; list_no < nlist; list_no++) {
1379
+ #pragma omp parallel for if (nlist > 100)
1380
+ for (idx_t list_no = 0; list_no < nlist; list_no++) {
1295
1381
  InvertedLists::ScopedCodes codes(invlists, list_no);
1296
1382
  InvertedLists::ScopedIds ids(invlists, list_no);
1297
- size_t list_size = orig_invlists->list_size(list_no);
1383
+ size_t list_size = invlists->list_size(list_no);
1298
1384
  std::vector<uint8_t> code(code_size, 0);
1299
1385
 
1300
1386
  for (size_t offset = 0; offset < list_size; offset++) {
@@ -1314,6 +1400,30 @@ void IndexIVFFastScan::reconstruct_orig_invlists() {
1314
1400
  }
1315
1401
  }
1316
1402
 
1403
+ void IndexIVFFastScan::sa_decode(idx_t n, const uint8_t* codes, float* x)
1404
+ const {
1405
+ size_t coarse_size = coarse_code_size();
1406
+
1407
+ #pragma omp parallel if (n > 1)
1408
+ {
1409
+ std::vector<float> residual(d);
1410
+
1411
+ #pragma omp for
1412
+ for (idx_t i = 0; i < n; i++) {
1413
+ const uint8_t* code = codes + i * (code_size + coarse_size);
1414
+ int64_t list_no = decode_listno(code);
1415
+ float* xi = x + i * d;
1416
+ fine_quantizer->decode(code + coarse_size, xi, 1);
1417
+ if (by_residual) {
1418
+ quantizer->reconstruct(list_no, residual.data());
1419
+ for (size_t j = 0; j < d; j++) {
1420
+ xi[j] += residual[j];
1421
+ }
1422
+ }
1423
+ }
1424
+ }
1425
+ }
1426
+
1317
1427
  IVFFastScanStats IVFFastScan_stats;
1318
1428
 
1319
1429
  } // namespace faiss