faiss 0.6.1 → 0.6.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 (186) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/lib/faiss/version.rb +1 -1
  4. data/vendor/faiss/faiss/AutoTune.cpp +3 -1
  5. data/vendor/faiss/faiss/Clustering.cpp +9 -1
  6. data/vendor/faiss/faiss/IVFlib.cpp +14 -3
  7. data/vendor/faiss/faiss/Index.h +2 -2
  8. data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +9 -10
  9. data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +2 -3
  10. data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +1 -2
  11. data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +10 -12
  12. data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
  13. data/vendor/faiss/faiss/IndexBinaryIVF.cpp +5 -7
  14. data/vendor/faiss/faiss/IndexEDEN.cpp +273 -0
  15. data/vendor/faiss/faiss/IndexEDEN.h +57 -0
  16. data/vendor/faiss/faiss/IndexFastScan.cpp +15 -4
  17. data/vendor/faiss/faiss/IndexFlat.cpp +13 -50
  18. data/vendor/faiss/faiss/IndexHNSW.cpp +177 -148
  19. data/vendor/faiss/faiss/IndexIDMap.cpp +16 -3
  20. data/vendor/faiss/faiss/IndexIDMap.h +2 -0
  21. data/vendor/faiss/faiss/IndexIVF.cpp +19 -8
  22. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +3 -3
  23. data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +3 -4
  24. data/vendor/faiss/faiss/IndexIVFEDEN.cpp +302 -0
  25. data/vendor/faiss/faiss/IndexIVFEDEN.h +70 -0
  26. data/vendor/faiss/faiss/IndexIVFFastScan.cpp +5 -6
  27. data/vendor/faiss/faiss/IndexIVFFlat.cpp +6 -5
  28. data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +3 -3
  29. data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +1 -1
  30. data/vendor/faiss/faiss/IndexIVFPQ.cpp +42 -25
  31. data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +0 -1
  32. data/vendor/faiss/faiss/IndexIVFPQR.cpp +2 -3
  33. data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +23 -62
  34. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +180 -76
  35. data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -4
  36. data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +8 -6
  37. data/vendor/faiss/faiss/IndexLSH.cpp +2 -3
  38. data/vendor/faiss/faiss/IndexLattice.cpp +5 -0
  39. data/vendor/faiss/faiss/IndexNNDescent.cpp +10 -3
  40. data/vendor/faiss/faiss/IndexNSG.cpp +8 -4
  41. data/vendor/faiss/faiss/IndexPQ.cpp +6 -8
  42. data/vendor/faiss/faiss/IndexPreTransform.cpp +15 -0
  43. data/vendor/faiss/faiss/IndexRaBitQ.cpp +2 -2
  44. data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +1 -2
  45. data/vendor/faiss/faiss/IndexRaBitQFastScan.h +5 -1
  46. data/vendor/faiss/faiss/IndexRefine.cpp +30 -1
  47. data/vendor/faiss/faiss/IndexReplicas.cpp +1 -2
  48. data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +68 -6
  49. data/vendor/faiss/faiss/IndexScalarQuantizer.h +10 -0
  50. data/vendor/faiss/faiss/IndexShards.cpp +2 -2
  51. data/vendor/faiss/faiss/IndexShardsIVF.cpp +2 -2
  52. data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
  53. data/vendor/faiss/faiss/SuperKMeans.cpp +256 -240
  54. data/vendor/faiss/faiss/SuperKMeans.h +30 -0
  55. data/vendor/faiss/faiss/VectorTransform.cpp +33 -2
  56. data/vendor/faiss/faiss/clone_index.cpp +5 -0
  57. data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +1 -1
  58. data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +902 -12
  59. data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +702 -10
  60. data/vendor/faiss/faiss/factory_tools.cpp +51 -4
  61. data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
  62. data/vendor/faiss/faiss/gpu/GpuIndex.h +34 -11
  63. data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +47 -0
  64. data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +17 -0
  65. data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +16 -0
  66. data/vendor/faiss/faiss/gpu/GpuResources.h +3 -2
  67. data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +11 -12
  68. data/vendor/faiss/faiss/gpu/StandardGpuResources.h +3 -3
  69. data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +1 -1
  70. data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +2 -2
  71. data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +180 -0
  72. data/vendor/faiss/faiss/gpu_metal/MetalDistance.h +87 -0
  73. data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +7 -0
  74. data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +177 -0
  75. data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +88 -0
  76. data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +48 -3
  77. data/vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h +45 -0
  78. data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFFlat.h +193 -0
  79. data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFPQ.h +134 -0
  80. data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +2 -2
  81. data/vendor/faiss/faiss/impl/DistanceComputer.h +34 -0
  82. data/vendor/faiss/faiss/impl/EDENQuantizer.h +119 -0
  83. data/vendor/faiss/faiss/impl/HNSW.cpp +658 -344
  84. data/vendor/faiss/faiss/impl/HNSW.h +51 -13
  85. data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
  86. data/vendor/faiss/faiss/impl/NSG.cpp +18 -12
  87. data/vendor/faiss/faiss/impl/Panorama.h +20 -7
  88. data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
  89. data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +59 -24
  90. data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +45 -37
  91. data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
  92. data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +175 -68
  93. data/vendor/faiss/faiss/impl/RaBitQuantizer.h +19 -0
  94. data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +2 -11
  95. data/vendor/faiss/faiss/impl/ResultHandler.h +26 -31
  96. data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +522 -58
  97. data/vendor/faiss/faiss/impl/ScalarQuantizer.h +70 -0
  98. data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
  99. data/vendor/faiss/faiss/impl/VisitedTable.cpp +33 -13
  100. data/vendor/faiss/faiss/impl/VisitedTable.h +88 -33
  101. data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +1 -1
  102. data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
  103. data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +38 -3
  104. data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +1 -1
  105. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +35 -43
  106. data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +64 -15
  107. data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +86 -40
  108. data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +81 -50
  109. data/vendor/faiss/faiss/impl/index_read.cpp +476 -75
  110. data/vendor/faiss/faiss/impl/index_write.cpp +56 -4
  111. data/vendor/faiss/faiss/impl/io_macros.h +25 -0
  112. data/vendor/faiss/faiss/impl/lattice_Zn.cpp +8 -9
  113. data/vendor/faiss/faiss/impl/platform_macros.h +15 -9
  114. data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +284 -0
  115. data/vendor/faiss/faiss/impl/polysemous_training/dispatch.h +115 -0
  116. data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +0 -1
  117. data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +26 -15
  118. data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +6 -4
  119. data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +2 -0
  120. data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +2 -0
  121. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +20 -0
  122. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +36 -0
  123. data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +5 -0
  124. data/vendor/faiss/faiss/impl/pq_code_distance/pq_scan_impl.h +105 -0
  125. data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +2 -0
  126. data/vendor/faiss/faiss/impl/result_handler/ResultHandler.cpp +195 -0
  127. data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +133 -0
  128. data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +281 -0
  129. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +72 -0
  130. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +228 -0
  131. data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp +882 -0
  132. data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +6 -0
  133. data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +336 -26
  134. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +331 -32
  135. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +553 -0
  136. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +558 -0
  137. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +284 -45
  138. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +502 -3
  139. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +157 -32
  140. data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +26 -0
  141. data/vendor/faiss/faiss/impl/simd_dispatch.h +86 -8
  142. data/vendor/faiss/faiss/index_factory.cpp +37 -7
  143. data/vendor/faiss/faiss/index_io.h +16 -0
  144. data/vendor/faiss/faiss/invlists/DirectMap.cpp +5 -2
  145. data/vendor/faiss/faiss/invlists/InvertedLists.cpp +15 -15
  146. data/vendor/faiss/faiss/invlists/InvertedLists.h +2 -2
  147. data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +19 -4
  148. data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -1
  149. data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +60 -0
  150. data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +26 -1
  151. data/vendor/faiss/faiss/svs/IndexSVSFlat.h +13 -0
  152. data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +1 -1
  153. data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +1 -1
  154. data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +150 -23
  155. data/vendor/faiss/faiss/svs/IndexSVSVamana.h +30 -7
  156. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +3 -2
  157. data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +2 -1
  158. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +65 -25
  159. data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +3 -2
  160. data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
  161. data/vendor/faiss/faiss/utils/bf16.h +34 -0
  162. data/vendor/faiss/faiss/utils/distances.cpp +14 -2
  163. data/vendor/faiss/faiss/utils/distances_simd.cpp +4 -4
  164. data/vendor/faiss/faiss/utils/extra_distances.cpp +4 -14
  165. data/vendor/faiss/faiss/utils/extra_distances.h +1 -2
  166. data/vendor/faiss/faiss/utils/hamming.cpp +9 -9
  167. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +2 -1
  168. data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_spr.cpp +15 -0
  169. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +6 -30
  170. data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512_spr.h +171 -0
  171. data/vendor/faiss/faiss/utils/partitioning.cpp +0 -2
  172. data/vendor/faiss/faiss/utils/quantize_lut.cpp +29 -8
  173. data/vendor/faiss/faiss/utils/rabitq_simd.h +202 -0
  174. data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +0 -1
  175. data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +263 -15
  176. data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +160 -18
  177. data/vendor/faiss/faiss/utils/simd_impl/partitioning_simdlib256.h +14 -68
  178. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
  179. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +273 -0
  180. data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_spr.cpp +435 -0
  181. data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +11 -0
  182. data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +143 -6
  183. data/vendor/faiss/faiss/utils/simd_levels.cpp +56 -2
  184. data/vendor/faiss/faiss/utils/simd_levels.h +14 -0
  185. data/vendor/faiss/faiss/utils/utils.cpp +9 -27
  186. metadata +27 -2
@@ -0,0 +1,45 @@
1
+ // @lint-ignore-every LICENSELINT
2
+ /**
3
+ * Copyright (c) Meta Platforms, Inc. and its affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * C++-only API for Python/SWIG. No Objective-C types so SWIG can
9
+ * parse it. Implemented in MetalPythonBridge.mm.
10
+ */
11
+
12
+ #pragma once
13
+
14
+ #include <faiss/Index.h>
15
+
16
+ namespace faiss {
17
+ namespace gpu_metal {
18
+
19
+ /// Opaque holder for Metal resources.
20
+ struct StandardMetalResourcesHolder {
21
+ void* impl = nullptr;
22
+ StandardMetalResourcesHolder();
23
+ ~StandardMetalResourcesHolder();
24
+ StandardMetalResourcesHolder(const StandardMetalResourcesHolder&) = delete;
25
+ StandardMetalResourcesHolder& operator=(
26
+ const StandardMetalResourcesHolder&) = delete;
27
+ };
28
+
29
+ /// Same names as GPU API for unified Python binding.
30
+ int get_num_gpus();
31
+ void gpu_profiler_start();
32
+ void gpu_profiler_stop();
33
+ void gpu_sync_all_devices();
34
+
35
+ /// Clone CPU index to Metal GPU. Caller owns returned index.
36
+ faiss::Index* index_cpu_to_gpu(
37
+ StandardMetalResourcesHolder* res,
38
+ int device,
39
+ const faiss::Index* index);
40
+
41
+ /// Copy Metal index back to CPU. Caller owns returned index.
42
+ faiss::Index* index_gpu_to_cpu(const faiss::Index* index);
43
+
44
+ } // namespace gpu_metal
45
+ } // namespace faiss
@@ -0,0 +1,193 @@
1
+ // @lint-ignore-every LICENSELINT
2
+ /**
3
+ * Copyright (c) Meta Platforms, Inc. and its affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * Metal IVF Flat implementation: GPU-resident IVF list storage and helpers.
9
+ * Mirrors the roles of faiss/gpu/impl/IVFFlat.cuh (storage side only).
10
+ */
11
+
12
+ #pragma once
13
+
14
+ #import <Metal/Metal.h>
15
+
16
+ #include <cstddef>
17
+ #include <cstdint>
18
+ #include <memory>
19
+ #include <vector>
20
+
21
+ #include <faiss/Index.h>
22
+ #include <faiss/MetricType.h>
23
+ #include <faiss/gpu/GpuIndicesOptions.h>
24
+ #include <faiss/gpu_metal/MetalResources.h>
25
+
26
+ namespace faiss {
27
+ namespace gpu_metal {
28
+
29
+ /// GPU-resident IVF list storage for flat (float32) codes.
30
+ /// Layout: all lists are stored contiguously in a single codes/ids buffer;
31
+ /// lists are described by (listOffset[list], listLength[list]).
32
+ class MetalIVFFlatImpl {
33
+ public:
34
+ struct AppendDebugStats {
35
+ size_t relayoutEvents = 0;
36
+ size_t movedLists = 0;
37
+ size_t movedVectors = 0;
38
+ size_t reusedSegmentAllocs = 0;
39
+ size_t tailSegmentAllocs = 0;
40
+ size_t reusedCapacityVecs = 0;
41
+ size_t tailCapacityVecs = 0;
42
+ size_t tailShrinkEvents = 0;
43
+ size_t tailShrunkVecs = 0;
44
+ };
45
+
46
+ MetalIVFFlatImpl(
47
+ std::shared_ptr<MetalResources> resources,
48
+ int dim,
49
+ idx_t nlist,
50
+ faiss::MetricType metric,
51
+ float metricArg,
52
+ faiss::gpu::IndicesOptions indicesOptions,
53
+ bool interleavedLayout);
54
+
55
+ ~MetalIVFFlatImpl();
56
+
57
+ /// Reset all IVF lists and free GPU storage.
58
+ void reset();
59
+
60
+ /// Reserve host/GPU storage for at least totalVecs vectors.
61
+ void reserveMemory(idx_t totalVecs);
62
+
63
+ /// Append a batch of vectors to IVF lists.
64
+ /// - x: host pointer, size n * dim
65
+ /// - list_nos: host pointer, size n; -1 entries are skipped
66
+ /// - xids: host pointer, size n (may be null to use internal ids)
67
+ void appendVectors(
68
+ idx_t n,
69
+ const float* x,
70
+ const idx_t* list_nos,
71
+ const idx_t* xids);
72
+
73
+ /// Accessors for future GPU search path.
74
+ int dim() const {
75
+ return dim_;
76
+ }
77
+ idx_t nlist() const {
78
+ return nlist_;
79
+ }
80
+ faiss::MetricType metricType() const {
81
+ return metric_type_;
82
+ }
83
+ float metricArg() const {
84
+ return metric_arg_;
85
+ }
86
+
87
+ const std::vector<size_t>& listLength() const {
88
+ return listLength_;
89
+ }
90
+ const std::vector<size_t>& listOffset() const {
91
+ return listOffset_;
92
+ }
93
+
94
+ id<MTLBuffer> codesBuffer() const {
95
+ return codesBuffer_;
96
+ }
97
+ id<MTLBuffer> idsBuffer() const {
98
+ return idsBuffer_;
99
+ }
100
+ /// Pre-built GPU buffer of (nlist) uint32_t offsets (updated on every add).
101
+ id<MTLBuffer> listOffsetGpuBuffer() const {
102
+ return listOffsetBuf_;
103
+ }
104
+ /// Pre-built GPU buffer of (nlist) uint32_t lengths (updated on every add).
105
+ id<MTLBuffer> listLengthGpuBuffer() const {
106
+ return listLengthBuf_;
107
+ }
108
+
109
+ size_t totalVecs() const {
110
+ return totalVecs_;
111
+ }
112
+
113
+ /// Interleaved codes buffer (blocks of 32 vectors, dims interleaved).
114
+ id<MTLBuffer> interleavedCodesBuffer() const {
115
+ return interleavedCodesBuf_;
116
+ }
117
+ /// Per-list float offsets into the interleaved codes buffer.
118
+ id<MTLBuffer> interleavedCodesOffsetBuffer() const {
119
+ return interleavedCodesOffsetBuf_;
120
+ }
121
+ bool interleavedLayout() const {
122
+ return interleavedLayout_;
123
+ }
124
+ /// Rebuild interleaved buffers from host storage if they are stale.
125
+ void ensureInterleavedLayoutUpToDate();
126
+ const AppendDebugStats& appendDebugStats() const {
127
+ return appendStats_;
128
+ }
129
+ void resetAppendDebugStats() {
130
+ appendStats_ = AppendDebugStats{};
131
+ }
132
+
133
+ private:
134
+ struct FreeSegment {
135
+ size_t offset = 0;
136
+ size_t length = 0;
137
+ };
138
+
139
+ bool ensureCapacityForAppend_(
140
+ const std::vector<size_t>& addPerList,
141
+ std::vector<uint8_t>* movedLists);
142
+ void uploadToGpu_(
143
+ const std::vector<size_t>& oldLength,
144
+ const std::vector<size_t>& addPerList,
145
+ const std::vector<uint8_t>& movedLists,
146
+ bool forceFullUpload);
147
+ void rebuildInterleavedBuffers_();
148
+ size_t allocSegment_(size_t length);
149
+ void freeSegment_(
150
+ size_t offset,
151
+ size_t length,
152
+ bool allowTailShrink = true);
153
+ void coalesceFreeSegments_();
154
+ void tryShrinkTail_();
155
+
156
+ std::shared_ptr<MetalResources> resources_;
157
+
158
+ int dim_;
159
+ idx_t nlist_;
160
+ faiss::MetricType metric_type_;
161
+ float metric_arg_;
162
+ faiss::gpu::IndicesOptions indicesOptions_;
163
+ bool interleavedLayout_;
164
+
165
+ // Per-list metadata
166
+ std::vector<size_t> listLength_;
167
+ std::vector<size_t> listOffset_;
168
+ std::vector<size_t> listCapacity_;
169
+
170
+ // Host copies of IVF data (flat layout)
171
+ std::vector<float> hostCodes_; // size = totalVecs_ * dim_
172
+ std::vector<idx_t> hostIds_; // size = totalVecs_
173
+ std::vector<FreeSegment> freeSegments_;
174
+ AppendDebugStats appendStats_;
175
+ size_t totalVecs_;
176
+ size_t totalCapacityVecs_;
177
+
178
+ // GPU storage
179
+ id<MTLBuffer> codesBuffer_;
180
+ id<MTLBuffer> idsBuffer_;
181
+ id<MTLBuffer> listOffsetBuf_; // (nlist) uint32_t, list element offsets
182
+ id<MTLBuffer> listLengthBuf_; // (nlist) uint32_t, list sizes
183
+
184
+ // Interleaved codes layout (blocks of 32 vectors, dims interleaved)
185
+ id<MTLBuffer> interleavedCodesBuf_;
186
+ id<MTLBuffer> interleavedCodesOffsetBuf_; // (nlist) uint32_t, float offsets
187
+ bool interleavedDirty_ = true;
188
+
189
+ static constexpr int kInterleavedGroupSize = 32;
190
+ };
191
+
192
+ } // namespace gpu_metal
193
+ } // namespace faiss
@@ -0,0 +1,134 @@
1
+ // @lint-ignore-every LICENSELINT
2
+ /**
3
+ * Copyright (c) Meta Platforms, Inc. and its affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * Metal IVF PQ implementation: GPU-resident IVF list storage for
9
+ * 8-bit product-quantized codes. Each vector is M bytes (one byte
10
+ * per subquantizer, ksub=256).
11
+ */
12
+
13
+ #pragma once
14
+
15
+ #import <Metal/Metal.h>
16
+
17
+ #include <cstddef>
18
+ #include <cstdint>
19
+ #include <memory>
20
+ #include <vector>
21
+
22
+ #include <faiss/Index.h>
23
+ #include <faiss/MetricType.h>
24
+ #include <faiss/gpu_metal/MetalResources.h>
25
+
26
+ namespace faiss {
27
+ namespace gpu_metal {
28
+
29
+ class MetalIVFPQImpl {
30
+ public:
31
+ MetalIVFPQImpl(
32
+ std::shared_ptr<MetalResources> resources,
33
+ int dim,
34
+ idx_t nlist,
35
+ int numSubQuantizers,
36
+ int bitsPerCode,
37
+ faiss::MetricType metric,
38
+ float metricArg);
39
+
40
+ ~MetalIVFPQImpl();
41
+
42
+ void reset();
43
+ void reserveMemory(idx_t totalVecs);
44
+
45
+ /// Append PQ-encoded vectors. codes: n * codeSize bytes.
46
+ void appendCodes(
47
+ idx_t n,
48
+ const uint8_t* codes,
49
+ const idx_t* list_nos,
50
+ const idx_t* xids);
51
+
52
+ /// Upload PQ centroids: M * ksub * dsub floats, row-major.
53
+ /// Layout: pqCentroids[m][c][dsub_dim]
54
+ void setPQCentroids(const float* centroids);
55
+
56
+ int dim() const {
57
+ return dim_;
58
+ }
59
+ idx_t nlist() const {
60
+ return nlist_;
61
+ }
62
+ int numSubQuantizers() const {
63
+ return M_;
64
+ }
65
+ int bitsPerCode() const {
66
+ return bitsPerCode_;
67
+ }
68
+ int ksub() const {
69
+ return ksub_;
70
+ }
71
+ int dsub() const {
72
+ return dsub_;
73
+ }
74
+ size_t codeSize() const {
75
+ return codeSize_;
76
+ }
77
+
78
+ const std::vector<size_t>& listLength() const {
79
+ return listLength_;
80
+ }
81
+ const std::vector<size_t>& listOffset() const {
82
+ return listOffset_;
83
+ }
84
+
85
+ id<MTLBuffer> codesBuffer() const {
86
+ return codesBuffer_;
87
+ }
88
+ id<MTLBuffer> idsBuffer() const {
89
+ return idsBuffer_;
90
+ }
91
+ id<MTLBuffer> listOffsetGpuBuffer() const {
92
+ return listOffsetBuf_;
93
+ }
94
+ id<MTLBuffer> listLengthGpuBuffer() const {
95
+ return listLengthBuf_;
96
+ }
97
+ id<MTLBuffer> pqCentroidsBuffer() const {
98
+ return pqCentroidsBuf_;
99
+ }
100
+ size_t totalVecs() const {
101
+ return totalVecs_;
102
+ }
103
+
104
+ private:
105
+ void uploadToGpu();
106
+
107
+ std::shared_ptr<MetalResources> resources_;
108
+
109
+ int dim_;
110
+ idx_t nlist_;
111
+ int M_;
112
+ int bitsPerCode_;
113
+ int ksub_;
114
+ int dsub_;
115
+ size_t codeSize_;
116
+ faiss::MetricType metric_type_;
117
+ float metric_arg_;
118
+
119
+ std::vector<size_t> listLength_;
120
+ std::vector<size_t> listOffset_;
121
+
122
+ std::vector<uint8_t> hostCodes_;
123
+ std::vector<idx_t> hostIds_;
124
+ size_t totalVecs_;
125
+
126
+ id<MTLBuffer> codesBuffer_;
127
+ id<MTLBuffer> idsBuffer_;
128
+ id<MTLBuffer> listOffsetBuf_;
129
+ id<MTLBuffer> listLengthBuf_;
130
+ id<MTLBuffer> pqCentroidsBuf_;
131
+ };
132
+
133
+ } // namespace gpu_metal
134
+ } // namespace faiss
@@ -157,8 +157,8 @@ void ClusteringInitialization::init_centroids(
157
157
  n,
158
158
  k);
159
159
  FAISS_THROW_IF_NOT(d > 0);
160
- FAISS_THROW_IF_NOT(x != nullptr);
161
- FAISS_THROW_IF_NOT(centroids != nullptr);
160
+ FAISS_THROW_IF_NOT(x);
161
+ FAISS_THROW_IF_NOT(centroids);
162
162
  FAISS_THROW_IF_NOT(
163
163
  n_existing_centroids == 0 || existing_centroids != nullptr);
164
164
 
@@ -130,6 +130,26 @@ struct FlatCodesDistanceComputer : DistanceComputer {
130
130
  return distance_to_code(codes + i * code_size);
131
131
  }
132
132
 
133
+ void distances_batch_4(
134
+ const idx_t idx0,
135
+ const idx_t idx1,
136
+ const idx_t idx2,
137
+ const idx_t idx3,
138
+ float& dis0,
139
+ float& dis1,
140
+ float& dis2,
141
+ float& dis3) override {
142
+ distance_to_code_batch_4(
143
+ codes + idx0 * code_size,
144
+ codes + idx1 * code_size,
145
+ codes + idx2 * code_size,
146
+ codes + idx3 * code_size,
147
+ dis0,
148
+ dis1,
149
+ dis2,
150
+ dis3);
151
+ }
152
+
133
153
  /// Computes a partial dot product over a slice of the query vector.
134
154
  /// The slice is defined by the following parameters:
135
155
  /// — `offset`: the starting index of the first component to include
@@ -167,6 +187,20 @@ struct FlatCodesDistanceComputer : DistanceComputer {
167
187
 
168
188
  /// compute distance of current query to an encoded vector
169
189
  virtual float distance_to_code(const uint8_t* code) = 0;
190
+ virtual void distance_to_code_batch_4(
191
+ const uint8_t* c1,
192
+ const uint8_t* c2,
193
+ const uint8_t* c3,
194
+ const uint8_t* c4,
195
+ float& d1,
196
+ float& d2,
197
+ float& d3,
198
+ float& d4) {
199
+ d1 = distance_to_code(c1);
200
+ d2 = distance_to_code(c2);
201
+ d3 = distance_to_code(c3);
202
+ d4 = distance_to_code(c4);
203
+ }
170
204
 
171
205
  /// Compute partial dot products of current query to 4 stored vectors.
172
206
  /// See `partial_dot_product` for more details.
@@ -0,0 +1,119 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #pragma once
9
+
10
+ #include <cstddef>
11
+ #include <cstdint>
12
+
13
+ #include <faiss/MetricType.h>
14
+ #include <faiss/impl/DistanceComputer.h>
15
+ #include <faiss/impl/ScalarQuantizer.h>
16
+ #include <faiss/impl/platform_macros.h>
17
+
18
+ namespace faiss {
19
+
20
+ enum EDENScaleType {
21
+ // Original EDEN unbiased scale.
22
+ EDENScaleType_UNBIASED = 1,
23
+ // Biased DRIVE scale (NeurIPS 2021, arXiv:2105.08339), generalized to
24
+ // multi-bit EDEN; see also https://arxiv.org/abs/2604.18555.
25
+ EDENScaleType_BIASED = 2,
26
+ };
27
+
28
+ FAISS_PACK_STRUCTS_BEGIN
29
+ struct FAISS_PACKED EDENCodeFactors {
30
+ // L2 term used by the distance computer. For the unbiased scale this is
31
+ // ||r||^2. For the biased scale this is S^2 * ||q_code||^2, the
32
+ // reconstructed-code norm.
33
+ float l2_norm_term = 0;
34
+ // Per-vector reconstruction scale.
35
+ float scale = 0;
36
+ };
37
+ FAISS_PACK_STRUCTS_END
38
+
39
+ struct EDENFlatCodesDistanceComputer : FlatCodesDistanceComputer {
40
+ using FlatCodesDistanceComputer::FlatCodesDistanceComputer;
41
+
42
+ virtual void consecutive_distances_batch_8(idx_t first, float* distances) {
43
+ distances_batch_4(
44
+ first,
45
+ first + 1,
46
+ first + 2,
47
+ first + 3,
48
+ distances[0],
49
+ distances[1],
50
+ distances[2],
51
+ distances[3]);
52
+ distances_batch_4(
53
+ first + 4,
54
+ first + 5,
55
+ first + 6,
56
+ first + 7,
57
+ distances[4],
58
+ distances[5],
59
+ distances[6],
60
+ distances[7]);
61
+ }
62
+
63
+ virtual void consecutive_distances_batch_16(idx_t first, float* distances) {
64
+ consecutive_distances_batch_8(first, distances);
65
+ consecutive_distances_batch_8(first + 8, distances + 8);
66
+ }
67
+ };
68
+
69
+ // EDEN Lloyd-Max quantizer from the EDEN ICML 2022 paper:
70
+ // https://proceedings.mlr.press/v162/vargaftik22a.html.
71
+ //
72
+ // EDEN operates on the vectors supplied to it. Optional preprocessing such as
73
+ // a random rotation can be applied externally with IndexPreTransform. The
74
+ // scalar assignment itself is a ScalarQuantizer::QT_*_eden qtype. EDEN adds
75
+ // per-vector scale factors after the packed scalar code and computes them
76
+ // against an externally supplied centroid; nullptr means a zero centroid. The
77
+ // default stored scale is EDEN's original unbiased scale. The biased scale
78
+ // follows DRIVE's MSE-minimizing scale for the chosen Lloyd-Max codeword; see
79
+ // also
80
+ // https://arxiv.org/abs/2604.18555.
81
+
82
+ namespace eden_utils {
83
+
84
+ ScalarQuantizer::QuantizerType quantizer_type_for_bits(size_t nb_bits);
85
+
86
+ bool is_eden_quantizer_type(ScalarQuantizer::QuantizerType qtype);
87
+
88
+ size_t nb_bits_for_qtype(ScalarQuantizer::QuantizerType qtype);
89
+
90
+ size_t packed_code_size(size_t d, size_t nb_bits);
91
+
92
+ size_t code_size(size_t d, size_t nb_bits);
93
+
94
+ uint8_t extract_code(const uint8_t* codes, size_t index, size_t nb_bits);
95
+
96
+ void compute_codes(
97
+ const ScalarQuantizer& sq,
98
+ MetricType metric_type,
99
+ EDENScaleType scale_type,
100
+ const float* x,
101
+ uint8_t* codes,
102
+ size_t n,
103
+ const float* centroid = nullptr);
104
+
105
+ void decode(
106
+ const ScalarQuantizer& sq,
107
+ const uint8_t* codes,
108
+ float* x,
109
+ size_t n,
110
+ const float* centroid = nullptr);
111
+
112
+ EDENFlatCodesDistanceComputer* get_distance_computer(
113
+ const ScalarQuantizer& sq,
114
+ MetricType metric_type,
115
+ const float* centroid = nullptr);
116
+
117
+ } // namespace eden_utils
118
+
119
+ } // namespace faiss