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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +3 -1
- data/vendor/faiss/faiss/Clustering.cpp +9 -1
- data/vendor/faiss/faiss/IVFlib.cpp +14 -3
- data/vendor/faiss/faiss/Index.h +2 -2
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +9 -10
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +2 -3
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +1 -2
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +10 -12
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +5 -7
- data/vendor/faiss/faiss/IndexEDEN.cpp +273 -0
- data/vendor/faiss/faiss/IndexEDEN.h +57 -0
- data/vendor/faiss/faiss/IndexFastScan.cpp +15 -4
- data/vendor/faiss/faiss/IndexFlat.cpp +13 -50
- data/vendor/faiss/faiss/IndexHNSW.cpp +177 -148
- data/vendor/faiss/faiss/IndexIDMap.cpp +16 -3
- data/vendor/faiss/faiss/IndexIDMap.h +2 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +19 -8
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +3 -3
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +3 -4
- data/vendor/faiss/faiss/IndexIVFEDEN.cpp +302 -0
- data/vendor/faiss/faiss/IndexIVFEDEN.h +70 -0
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +5 -6
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +6 -5
- data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +3 -3
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +42 -25
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +0 -1
- data/vendor/faiss/faiss/IndexIVFPQR.cpp +2 -3
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +23 -62
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +180 -76
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -4
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +8 -6
- data/vendor/faiss/faiss/IndexLSH.cpp +2 -3
- data/vendor/faiss/faiss/IndexLattice.cpp +5 -0
- data/vendor/faiss/faiss/IndexNNDescent.cpp +10 -3
- data/vendor/faiss/faiss/IndexNSG.cpp +8 -4
- data/vendor/faiss/faiss/IndexPQ.cpp +6 -8
- data/vendor/faiss/faiss/IndexPreTransform.cpp +15 -0
- data/vendor/faiss/faiss/IndexRaBitQ.cpp +2 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +1 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +5 -1
- data/vendor/faiss/faiss/IndexRefine.cpp +30 -1
- data/vendor/faiss/faiss/IndexReplicas.cpp +1 -2
- data/vendor/faiss/faiss/IndexScalarQuantizer.cpp +68 -6
- data/vendor/faiss/faiss/IndexScalarQuantizer.h +10 -0
- data/vendor/faiss/faiss/IndexShards.cpp +2 -2
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +2 -2
- data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
- data/vendor/faiss/faiss/SuperKMeans.cpp +256 -240
- data/vendor/faiss/faiss/SuperKMeans.h +30 -0
- data/vendor/faiss/faiss/VectorTransform.cpp +33 -2
- data/vendor/faiss/faiss/clone_index.cpp +5 -0
- data/vendor/faiss/faiss/cppcontrib/SaDecodeKernels.h +1 -1
- data/vendor/faiss/faiss/cppcontrib/sa_decode/Level2-neon-inl.h +902 -12
- data/vendor/faiss/faiss/cppcontrib/sa_decode/PQ-neon-inl.h +702 -10
- data/vendor/faiss/faiss/factory_tools.cpp +51 -4
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
- data/vendor/faiss/faiss/gpu/GpuIndex.h +34 -11
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +47 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +17 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +16 -0
- data/vendor/faiss/faiss/gpu/GpuResources.h +3 -2
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +11 -12
- data/vendor/faiss/faiss/gpu/StandardGpuResources.h +3 -3
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +1 -1
- data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +2 -2
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +180 -0
- data/vendor/faiss/faiss/gpu_metal/MetalDistance.h +87 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +7 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +177 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +88 -0
- data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +48 -3
- data/vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h +45 -0
- data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFFlat.h +193 -0
- data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFPQ.h +134 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +2 -2
- data/vendor/faiss/faiss/impl/DistanceComputer.h +34 -0
- data/vendor/faiss/faiss/impl/EDENQuantizer.h +119 -0
- data/vendor/faiss/faiss/impl/HNSW.cpp +658 -344
- data/vendor/faiss/faiss/impl/HNSW.h +51 -13
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/impl/NSG.cpp +18 -12
- data/vendor/faiss/faiss/impl/Panorama.h +20 -7
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +59 -24
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +45 -37
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +175 -68
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +19 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +2 -11
- data/vendor/faiss/faiss/impl/ResultHandler.h +26 -31
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +522 -58
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +70 -0
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
- data/vendor/faiss/faiss/impl/VisitedTable.cpp +33 -13
- data/vendor/faiss/faiss/impl/VisitedTable.h +88 -33
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +1 -1
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
- data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +38 -3
- data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +1 -1
- data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.cpp +35 -43
- data/vendor/faiss/faiss/impl/hnsw/MinimaxHeap.h +64 -15
- data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +86 -40
- data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +81 -50
- data/vendor/faiss/faiss/impl/index_read.cpp +476 -75
- data/vendor/faiss/faiss/impl/index_write.cpp +56 -4
- data/vendor/faiss/faiss/impl/io_macros.h +25 -0
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +8 -9
- data/vendor/faiss/faiss/impl/platform_macros.h +15 -9
- data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +284 -0
- data/vendor/faiss/faiss/impl/polysemous_training/dispatch.h +115 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +0 -1
- data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +26 -15
- data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +6 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +2 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +2 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +20 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +36 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +5 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_scan_impl.h +105 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +2 -0
- data/vendor/faiss/faiss/impl/result_handler/ResultHandler.cpp +195 -0
- data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +133 -0
- data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +281 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +72 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +228 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp +882 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +6 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +336 -26
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +331 -32
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +553 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +558 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +284 -45
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +502 -3
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +157 -32
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +26 -0
- data/vendor/faiss/faiss/impl/simd_dispatch.h +86 -8
- data/vendor/faiss/faiss/index_factory.cpp +37 -7
- data/vendor/faiss/faiss/index_io.h +16 -0
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +5 -2
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +15 -15
- data/vendor/faiss/faiss/invlists/InvertedLists.h +2 -2
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +19 -4
- data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -1
- data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +60 -0
- data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +26 -1
- data/vendor/faiss/faiss/svs/IndexSVSFlat.h +13 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +150 -23
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +30 -7
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +3 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +2 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +65 -25
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +3 -2
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
- data/vendor/faiss/faiss/utils/bf16.h +34 -0
- data/vendor/faiss/faiss/utils/distances.cpp +14 -2
- data/vendor/faiss/faiss/utils/distances_simd.cpp +4 -4
- data/vendor/faiss/faiss/utils/extra_distances.cpp +4 -14
- data/vendor/faiss/faiss/utils/extra_distances.h +1 -2
- data/vendor/faiss/faiss/utils/hamming.cpp +9 -9
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +2 -1
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_spr.cpp +15 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +6 -30
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512_spr.h +171 -0
- data/vendor/faiss/faiss/utils/partitioning.cpp +0 -2
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +29 -8
- data/vendor/faiss/faiss/utils/rabitq_simd.h +202 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +0 -1
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +263 -15
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +160 -18
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_simdlib256.h +14 -68
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +273 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_spr.cpp +435 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +11 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +143 -6
- data/vendor/faiss/faiss/utils/simd_levels.cpp +56 -2
- data/vendor/faiss/faiss/utils/simd_levels.h +14 -0
- data/vendor/faiss/faiss/utils/utils.cpp +9 -27
- metadata +27 -2
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
#include <faiss/gpu/StandardGpuResources.h>
|
|
12
12
|
#include <faiss/gpu/test/TestUtils.h>
|
|
13
13
|
#include <faiss/gpu/utils/DeviceUtils.h>
|
|
14
|
+
#include <faiss/impl/IDSelector.h>
|
|
14
15
|
#include <gtest/gtest.h>
|
|
15
16
|
#include <cmath>
|
|
17
|
+
#include <limits> // IWYU pragma: keep
|
|
16
18
|
#include <sstream>
|
|
17
19
|
#include <vector>
|
|
18
20
|
|
|
@@ -74,6 +76,7 @@ void runCopyToTest(faiss::ScalarQuantizer::QuantizerType qtype) {
|
|
|
74
76
|
|
|
75
77
|
auto config = GpuIndexIVFScalarQuantizerConfig();
|
|
76
78
|
config.device = opt.device;
|
|
79
|
+
config.use_cuvs = false;
|
|
77
80
|
|
|
78
81
|
GpuIndexIVFScalarQuantizer gpuIndex(
|
|
79
82
|
&res, opt.dim, opt.numCentroids, qtype, METRIC_L2, true, config);
|
|
@@ -163,6 +166,7 @@ void runCopyFromTest(faiss::ScalarQuantizer::QuantizerType qtype) {
|
|
|
163
166
|
|
|
164
167
|
auto config = GpuIndexIVFScalarQuantizerConfig();
|
|
165
168
|
config.device = opt.device;
|
|
169
|
+
config.use_cuvs = false;
|
|
166
170
|
|
|
167
171
|
GpuIndexIVFScalarQuantizer gpuIndex(
|
|
168
172
|
&res,
|
|
@@ -223,6 +227,182 @@ TEST(TestGpuIndexIVFScalarQuantizer, CopyFrom_4bit_uniform) {
|
|
|
223
227
|
runCopyFromTest(faiss::ScalarQuantizer::QuantizerType::QT_4bit_uniform);
|
|
224
228
|
}
|
|
225
229
|
|
|
230
|
+
#if defined USE_NVIDIA_CUVS
|
|
231
|
+
void runCuvsSQ8Test(faiss::MetricType metricType) {
|
|
232
|
+
using namespace faiss;
|
|
233
|
+
using namespace faiss::gpu;
|
|
234
|
+
|
|
235
|
+
Options opt;
|
|
236
|
+
opt.indicesOpt = INDICES_64_BIT;
|
|
237
|
+
|
|
238
|
+
std::vector<float> trainVecs = randVecs(opt.numTrain, opt.dim);
|
|
239
|
+
std::vector<float> addVecs = randVecs(opt.numAdd, opt.dim);
|
|
240
|
+
std::vector<float> queryVecs = randVecs(opt.numQuery, opt.dim);
|
|
241
|
+
|
|
242
|
+
StandardGpuResources res;
|
|
243
|
+
res.noTempMemory();
|
|
244
|
+
|
|
245
|
+
auto config = GpuIndexIVFScalarQuantizerConfig();
|
|
246
|
+
config.device = opt.device;
|
|
247
|
+
config.indicesOptions = INDICES_64_BIT;
|
|
248
|
+
config.use_cuvs = true;
|
|
249
|
+
if (!should_use_cuvs(config)) {
|
|
250
|
+
GTEST_SKIP() << "cuVS is not enabled for this GPU";
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
GpuIndexIVFScalarQuantizer gpuIndex(
|
|
254
|
+
&res,
|
|
255
|
+
opt.dim,
|
|
256
|
+
opt.numCentroids,
|
|
257
|
+
ScalarQuantizer::QT_8bit,
|
|
258
|
+
metricType,
|
|
259
|
+
true,
|
|
260
|
+
config);
|
|
261
|
+
gpuIndex.train(opt.numTrain, trainVecs.data());
|
|
262
|
+
gpuIndex.add(opt.numAdd, addVecs.data());
|
|
263
|
+
gpuIndex.nprobe = opt.nprobe;
|
|
264
|
+
|
|
265
|
+
std::vector<float> distances(opt.numQuery * opt.k);
|
|
266
|
+
std::vector<idx_t> labels(opt.numQuery * opt.k);
|
|
267
|
+
gpuIndex.search(
|
|
268
|
+
opt.numQuery,
|
|
269
|
+
queryVecs.data(),
|
|
270
|
+
opt.k,
|
|
271
|
+
distances.data(),
|
|
272
|
+
labels.data());
|
|
273
|
+
EXPECT_EQ(gpuIndex.ntotal, opt.numAdd);
|
|
274
|
+
EXPECT_NE(labels[0], idx_t(-1));
|
|
275
|
+
|
|
276
|
+
IndexFlatL2 quantizerL2(opt.dim);
|
|
277
|
+
IndexFlatIP quantizerIP(opt.dim);
|
|
278
|
+
Index* quantizer = metricType == METRIC_L2 ? (Index*)&quantizerL2
|
|
279
|
+
: (Index*)&quantizerIP;
|
|
280
|
+
|
|
281
|
+
IndexIVFScalarQuantizer cpuCopy(
|
|
282
|
+
quantizer,
|
|
283
|
+
opt.dim,
|
|
284
|
+
opt.numCentroids,
|
|
285
|
+
ScalarQuantizer::QT_8bit,
|
|
286
|
+
metricType,
|
|
287
|
+
true);
|
|
288
|
+
gpuIndex.copyTo(&cpuCopy);
|
|
289
|
+
cpuCopy.nprobe = opt.nprobe;
|
|
290
|
+
|
|
291
|
+
EXPECT_EQ(cpuCopy.ntotal, gpuIndex.ntotal);
|
|
292
|
+
EXPECT_EQ(cpuCopy.d, gpuIndex.d);
|
|
293
|
+
EXPECT_EQ(cpuCopy.nlist, gpuIndex.getNumLists());
|
|
294
|
+
EXPECT_EQ(cpuCopy.sq.qtype, ScalarQuantizer::QT_8bit);
|
|
295
|
+
EXPECT_EQ(cpuCopy.sq.trained.size(), 2 * opt.dim);
|
|
296
|
+
EXPECT_TRUE(cpuCopy.by_residual);
|
|
297
|
+
|
|
298
|
+
compareIndices(
|
|
299
|
+
cpuCopy,
|
|
300
|
+
gpuIndex,
|
|
301
|
+
opt.numQuery,
|
|
302
|
+
opt.dim,
|
|
303
|
+
opt.k,
|
|
304
|
+
opt.toString(),
|
|
305
|
+
0.08f,
|
|
306
|
+
0.2f,
|
|
307
|
+
0.05f);
|
|
308
|
+
|
|
309
|
+
GpuIndexIVFScalarQuantizer copiedGpuIndex(
|
|
310
|
+
&res, 1, 1, ScalarQuantizer::QT_4bit, METRIC_L2, false, config);
|
|
311
|
+
copiedGpuIndex.copyFrom(&cpuCopy);
|
|
312
|
+
copiedGpuIndex.nprobe = opt.nprobe;
|
|
313
|
+
EXPECT_EQ(copiedGpuIndex.ntotal, cpuCopy.ntotal);
|
|
314
|
+
testIVFEquality(cpuCopy, copiedGpuIndex);
|
|
315
|
+
|
|
316
|
+
compareIndices(
|
|
317
|
+
cpuCopy,
|
|
318
|
+
copiedGpuIndex,
|
|
319
|
+
opt.numQuery,
|
|
320
|
+
opt.dim,
|
|
321
|
+
opt.k,
|
|
322
|
+
opt.toString(),
|
|
323
|
+
0.08f,
|
|
324
|
+
0.2f,
|
|
325
|
+
0.05f);
|
|
326
|
+
|
|
327
|
+
SearchParametersIVF searchParams;
|
|
328
|
+
searchParams.nprobe = opt.nprobe;
|
|
329
|
+
TestIDSelectorStruct selectorStruct(opt.numAdd);
|
|
330
|
+
for (auto& [selectorName, selector] : selectorStruct.selector_map) {
|
|
331
|
+
searchParams.sel = selector.get();
|
|
332
|
+
testIDSelectorSearch(
|
|
333
|
+
&gpuIndex,
|
|
334
|
+
&searchParams,
|
|
335
|
+
queryVecs,
|
|
336
|
+
opt.numQuery,
|
|
337
|
+
opt.k,
|
|
338
|
+
selectorName);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
GpuIndexIVFScalarQuantizer shiftedGpuIndex(
|
|
342
|
+
&res,
|
|
343
|
+
opt.dim,
|
|
344
|
+
opt.numCentroids,
|
|
345
|
+
ScalarQuantizer::QT_8bit,
|
|
346
|
+
metricType,
|
|
347
|
+
true,
|
|
348
|
+
config);
|
|
349
|
+
shiftedGpuIndex.train(opt.numTrain, trainVecs.data());
|
|
350
|
+
std::vector<idx_t> shiftedIds(opt.numAdd);
|
|
351
|
+
idx_t shiftedIdBase = opt.numAdd * 4 + 123;
|
|
352
|
+
for (int i = 0; i < opt.numAdd; ++i) {
|
|
353
|
+
shiftedIds[i] = shiftedIdBase + i;
|
|
354
|
+
}
|
|
355
|
+
shiftedGpuIndex.add_with_ids(opt.numAdd, addVecs.data(), shiftedIds.data());
|
|
356
|
+
shiftedGpuIndex.nprobe = opt.nprobe;
|
|
357
|
+
|
|
358
|
+
SearchParametersIVF shiftedSearchParams;
|
|
359
|
+
shiftedSearchParams.nprobe = opt.nprobe;
|
|
360
|
+
IDSelectorRange shiftedSelector(shiftedIdBase, shiftedIdBase + opt.numAdd);
|
|
361
|
+
shiftedSearchParams.sel = &shiftedSelector;
|
|
362
|
+
std::vector<float> shiftedDistances(opt.numQuery * opt.k);
|
|
363
|
+
std::vector<idx_t> shiftedLabels(opt.numQuery * opt.k, -1);
|
|
364
|
+
shiftedGpuIndex.search(
|
|
365
|
+
opt.numQuery,
|
|
366
|
+
queryVecs.data(),
|
|
367
|
+
opt.k,
|
|
368
|
+
shiftedDistances.data(),
|
|
369
|
+
shiftedLabels.data(),
|
|
370
|
+
&shiftedSearchParams);
|
|
371
|
+
|
|
372
|
+
bool foundShiftedLabel = false;
|
|
373
|
+
for (idx_t label : shiftedLabels) {
|
|
374
|
+
if (label >= 0) {
|
|
375
|
+
foundShiftedLabel = true;
|
|
376
|
+
EXPECT_TRUE(shiftedSelector.is_member(label));
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
EXPECT_TRUE(foundShiftedLabel);
|
|
380
|
+
|
|
381
|
+
auto nanQueries = queryVecs;
|
|
382
|
+
nanQueries[opt.dim + 3] = std::numeric_limits<float>::quiet_NaN();
|
|
383
|
+
gpuIndex.search(
|
|
384
|
+
2, nanQueries.data(), opt.k, distances.data(), labels.data());
|
|
385
|
+
for (int j = 0; j < opt.k; ++j) {
|
|
386
|
+
EXPECT_EQ(labels[opt.k + j], idx_t(-1));
|
|
387
|
+
EXPECT_EQ(distances[opt.k + j], std::numeric_limits<float>::max());
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
gpuIndex.reset();
|
|
391
|
+
EXPECT_EQ(gpuIndex.ntotal, 0);
|
|
392
|
+
for (int i = 0; i < opt.numCentroids; ++i) {
|
|
393
|
+
EXPECT_EQ(gpuIndex.getListLength(i), 0);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
TEST(TestCuvsGpuIndexIVFScalarQuantizer, SQ8_L2) {
|
|
398
|
+
runCuvsSQ8Test(faiss::METRIC_L2);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
TEST(TestCuvsGpuIndexIVFScalarQuantizer, SQ8_IP) {
|
|
402
|
+
runCuvsSQ8Test(faiss::METRIC_INNER_PRODUCT);
|
|
403
|
+
}
|
|
404
|
+
#endif
|
|
405
|
+
|
|
226
406
|
int main(int argc, char** argv) {
|
|
227
407
|
testing::InitGoogleTest(&argc, argv);
|
|
228
408
|
|
|
@@ -0,0 +1,87 @@
|
|
|
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
|
+
* IVF distance computation and scan dispatch for Metal backend.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#pragma once
|
|
12
|
+
|
|
13
|
+
#import <Metal/Metal.h>
|
|
14
|
+
|
|
15
|
+
#include <cstddef>
|
|
16
|
+
#include <cstdint>
|
|
17
|
+
#include <memory>
|
|
18
|
+
|
|
19
|
+
namespace faiss {
|
|
20
|
+
namespace gpu_metal {
|
|
21
|
+
|
|
22
|
+
class MetalResources;
|
|
23
|
+
|
|
24
|
+
int getMetalDistanceMaxK();
|
|
25
|
+
|
|
26
|
+
bool runMetalComputeNorms(
|
|
27
|
+
id<MTLDevice> device,
|
|
28
|
+
id<MTLCommandQueue> queue,
|
|
29
|
+
id<MTLBuffer> vectors,
|
|
30
|
+
int nb,
|
|
31
|
+
int d,
|
|
32
|
+
id<MTLBuffer> normsBuf,
|
|
33
|
+
bool waitForCompletion = true);
|
|
34
|
+
|
|
35
|
+
bool runMetalIVFFlatScan(
|
|
36
|
+
id<MTLDevice> device,
|
|
37
|
+
id<MTLCommandQueue> queue,
|
|
38
|
+
id<MTLBuffer> queries,
|
|
39
|
+
id<MTLBuffer> codes,
|
|
40
|
+
id<MTLBuffer> ids,
|
|
41
|
+
id<MTLBuffer> listOffset,
|
|
42
|
+
id<MTLBuffer> listLength,
|
|
43
|
+
id<MTLBuffer> coarseAssign,
|
|
44
|
+
int nq,
|
|
45
|
+
int d,
|
|
46
|
+
int k,
|
|
47
|
+
int nprobe,
|
|
48
|
+
bool isL2,
|
|
49
|
+
id<MTLBuffer> outDistances,
|
|
50
|
+
id<MTLBuffer> outIndices,
|
|
51
|
+
id<MTLBuffer> perListDistBuf,
|
|
52
|
+
id<MTLBuffer> perListIdxBuf,
|
|
53
|
+
id<MTLBuffer> interleavedCodes = nil,
|
|
54
|
+
id<MTLBuffer> interleavedCodesOffset = nil,
|
|
55
|
+
bool waitForCompletion = true);
|
|
56
|
+
|
|
57
|
+
bool runMetalIVFFlatFullSearch(
|
|
58
|
+
id<MTLDevice> device,
|
|
59
|
+
id<MTLCommandQueue> queue,
|
|
60
|
+
id<MTLBuffer> queries,
|
|
61
|
+
int nq,
|
|
62
|
+
int d,
|
|
63
|
+
int k,
|
|
64
|
+
int nprobe,
|
|
65
|
+
bool isL2,
|
|
66
|
+
id<MTLBuffer> centroids,
|
|
67
|
+
int nlist,
|
|
68
|
+
id<MTLBuffer> codes,
|
|
69
|
+
id<MTLBuffer> ids,
|
|
70
|
+
id<MTLBuffer> listOffset,
|
|
71
|
+
id<MTLBuffer> listLength,
|
|
72
|
+
id<MTLBuffer> outDistances,
|
|
73
|
+
id<MTLBuffer> outIndices,
|
|
74
|
+
id<MTLBuffer> perListDistBuf,
|
|
75
|
+
id<MTLBuffer> perListIdxBuf,
|
|
76
|
+
id<MTLBuffer> coarseDistBuf,
|
|
77
|
+
id<MTLBuffer> coarseIdxBuf,
|
|
78
|
+
id<MTLBuffer> distMatrixBuf,
|
|
79
|
+
id<MTLBuffer> centroidNormsBuf = nil,
|
|
80
|
+
int avgListLen = 256,
|
|
81
|
+
id<MTLBuffer> interleavedCodes = nil,
|
|
82
|
+
id<MTLBuffer> interleavedCodesOffset = nil,
|
|
83
|
+
bool centroidsAreFP16 = false,
|
|
84
|
+
bool waitForCompletion = true);
|
|
85
|
+
|
|
86
|
+
} // namespace gpu_metal
|
|
87
|
+
} // namespace faiss
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
#pragma once
|
|
12
12
|
|
|
13
13
|
#include <faiss/Index.h>
|
|
14
|
+
#include <faiss/gpu/GpuIndicesOptions.h>
|
|
14
15
|
#include <faiss/gpu_metal/MetalResources.h>
|
|
15
16
|
#include <memory>
|
|
16
17
|
|
|
@@ -20,6 +21,12 @@ namespace gpu_metal {
|
|
|
20
21
|
/// Configuration for Metal index (mirrors GpuIndexConfig roles).
|
|
21
22
|
struct MetalIndexConfig {
|
|
22
23
|
int device = 0;
|
|
24
|
+
|
|
25
|
+
bool useFloat16CoarseQuantizer = false;
|
|
26
|
+
|
|
27
|
+
faiss::gpu::IndicesOptions indicesOptions = faiss::gpu::INDICES_64_BIT;
|
|
28
|
+
|
|
29
|
+
bool interleavedLayout = true;
|
|
23
30
|
};
|
|
24
31
|
|
|
25
32
|
/// Base class for Metal-backed indexes. Mirrors faiss::gpu::GpuIndex.
|
|
@@ -0,0 +1,177 @@
|
|
|
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
|
+
* Minimal Metal IVFFlat wrapper.
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
#pragma once
|
|
13
|
+
|
|
14
|
+
#import <Metal/Metal.h>
|
|
15
|
+
|
|
16
|
+
#include <faiss/IndexIVFFlat.h>
|
|
17
|
+
#include <faiss/gpu/GpuIndicesOptions.h>
|
|
18
|
+
#include <faiss/gpu_metal/MetalIndex.h>
|
|
19
|
+
|
|
20
|
+
#include <memory>
|
|
21
|
+
|
|
22
|
+
namespace faiss {
|
|
23
|
+
namespace gpu_metal {
|
|
24
|
+
|
|
25
|
+
class MetalIVFFlatImpl;
|
|
26
|
+
|
|
27
|
+
/// IVFFlat index wrapper for Metal backend.
|
|
28
|
+
/// Currently delegates to an internal CPU IndexIVFFlat; later phases
|
|
29
|
+
/// may move list scanning to GPU.
|
|
30
|
+
class MetalIndexIVFFlat : public MetalIndex {
|
|
31
|
+
public:
|
|
32
|
+
struct AppendDebugStats {
|
|
33
|
+
size_t relayoutEvents = 0;
|
|
34
|
+
size_t movedLists = 0;
|
|
35
|
+
size_t movedVectors = 0;
|
|
36
|
+
size_t reusedSegmentAllocs = 0;
|
|
37
|
+
size_t tailSegmentAllocs = 0;
|
|
38
|
+
size_t reusedCapacityVecs = 0;
|
|
39
|
+
size_t tailCapacityVecs = 0;
|
|
40
|
+
size_t tailShrinkEvents = 0;
|
|
41
|
+
size_t tailShrunkVecs = 0;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/// Construct empty IVFFlat index with its own CPU quantizer.
|
|
45
|
+
MetalIndexIVFFlat(
|
|
46
|
+
std::shared_ptr<MetalResources> resources,
|
|
47
|
+
int dims,
|
|
48
|
+
idx_t nlist,
|
|
49
|
+
faiss::MetricType metric,
|
|
50
|
+
float metricArg = 0.0f,
|
|
51
|
+
MetalIndexConfig config = MetalIndexConfig());
|
|
52
|
+
|
|
53
|
+
/// Construct empty IVFFlat index with caller-provided coarse quantizer.
|
|
54
|
+
/// If ownFields is true, this index takes ownership of `coarseQuantizer`.
|
|
55
|
+
MetalIndexIVFFlat(
|
|
56
|
+
std::shared_ptr<MetalResources> resources,
|
|
57
|
+
faiss::Index* coarseQuantizer,
|
|
58
|
+
int dims,
|
|
59
|
+
idx_t nlist,
|
|
60
|
+
faiss::MetricType metric,
|
|
61
|
+
float metricArg = 0.0f,
|
|
62
|
+
MetalIndexConfig config = MetalIndexConfig(),
|
|
63
|
+
bool ownFields = false);
|
|
64
|
+
|
|
65
|
+
/// Construct from an existing CPU IndexIVFFlat (used by cloners later).
|
|
66
|
+
MetalIndexIVFFlat(
|
|
67
|
+
std::shared_ptr<MetalResources> resources,
|
|
68
|
+
const faiss::IndexIVFFlat* cpuIndex,
|
|
69
|
+
MetalIndexConfig config = MetalIndexConfig());
|
|
70
|
+
|
|
71
|
+
~MetalIndexIVFFlat() override;
|
|
72
|
+
|
|
73
|
+
void train(idx_t n, const float* x) override;
|
|
74
|
+
void add(idx_t n, const float* x) override;
|
|
75
|
+
void add_with_ids(idx_t n, const float* x, const idx_t* xids) override;
|
|
76
|
+
void reset() override;
|
|
77
|
+
|
|
78
|
+
void search(
|
|
79
|
+
idx_t n,
|
|
80
|
+
const float* x,
|
|
81
|
+
idx_t k,
|
|
82
|
+
float* distances,
|
|
83
|
+
idx_t* labels,
|
|
84
|
+
const SearchParameters* params = nullptr) const override;
|
|
85
|
+
|
|
86
|
+
/// Search with caller-provided coarse assignments (skips coarse quantizer).
|
|
87
|
+
/// @param assign Coarse list assignments (n x nprobe), row-major idx_t
|
|
88
|
+
/// @param centroid_dis Distances to assigned centroids (n x nprobe); unused
|
|
89
|
+
/// by GPU scan but accepted for API compatibility
|
|
90
|
+
/// @param store_pairs Ignored (always false for GPU path)
|
|
91
|
+
void search_preassigned(
|
|
92
|
+
idx_t n,
|
|
93
|
+
const float* x,
|
|
94
|
+
idx_t k,
|
|
95
|
+
const idx_t* assign,
|
|
96
|
+
const float* centroid_dis,
|
|
97
|
+
float* distances,
|
|
98
|
+
idx_t* labels,
|
|
99
|
+
bool store_pairs,
|
|
100
|
+
const IVFSearchParameters* params = nullptr,
|
|
101
|
+
IndexIVFStats* stats = nullptr) const;
|
|
102
|
+
|
|
103
|
+
/// Copy from a CPU IndexIVFFlat (helper for future cloner support).
|
|
104
|
+
void copyFrom(const faiss::IndexIVFFlat* index);
|
|
105
|
+
|
|
106
|
+
/// Copy to a CPU IndexIVFFlat.
|
|
107
|
+
void copyTo(faiss::IndexIVFFlat* index) const;
|
|
108
|
+
|
|
109
|
+
/// Reconstruct a single stored vector by internal key.
|
|
110
|
+
void reconstruct(idx_t key, float* recons) const override;
|
|
111
|
+
|
|
112
|
+
/// Reconstruct n contiguous stored vectors starting at i0.
|
|
113
|
+
void reconstruct_n(idx_t i0, idx_t ni, float* recons) const override;
|
|
114
|
+
|
|
115
|
+
/// Re-upload coarse quantizer centroids to GPU after external changes.
|
|
116
|
+
void updateQuantizer();
|
|
117
|
+
|
|
118
|
+
/// Return the vector indices in inverted list `listId`.
|
|
119
|
+
std::vector<idx_t> getListIndices(idx_t listId) const;
|
|
120
|
+
|
|
121
|
+
/// Return raw vector data from inverted list `listId`.
|
|
122
|
+
std::vector<float> getListVectorData(idx_t listId) const;
|
|
123
|
+
|
|
124
|
+
/// Release unused GPU memory.
|
|
125
|
+
void reclaimMemory();
|
|
126
|
+
|
|
127
|
+
/// Pre-allocate GPU storage for the given total number of vectors.
|
|
128
|
+
void reserveMemory(idx_t numVecs);
|
|
129
|
+
|
|
130
|
+
/// Accessors (needed by cloner and tests).
|
|
131
|
+
idx_t nlist() const;
|
|
132
|
+
size_t nprobe() const;
|
|
133
|
+
bool interleavedLayout() const;
|
|
134
|
+
faiss::gpu::IndicesOptions indicesOptions() const;
|
|
135
|
+
AppendDebugStats appendDebugStats() const;
|
|
136
|
+
void resetAppendDebugStats();
|
|
137
|
+
|
|
138
|
+
private:
|
|
139
|
+
std::unique_ptr<faiss::IndexIVFFlat> cpuIndex_;
|
|
140
|
+
std::unique_ptr<MetalIVFFlatImpl> gpuIvf_;
|
|
141
|
+
faiss::gpu::IndicesOptions indicesOptions_;
|
|
142
|
+
bool interleavedLayout_;
|
|
143
|
+
|
|
144
|
+
// Persistent search buffers — allocated once, grown lazily.
|
|
145
|
+
// Declared mutable so search() (const) can resize them.
|
|
146
|
+
mutable id<MTLBuffer> searchQueriesBuf_ = nil;
|
|
147
|
+
mutable id<MTLBuffer> searchCoarseBuf_ = nil;
|
|
148
|
+
mutable id<MTLBuffer> searchOutDistBuf_ = nil;
|
|
149
|
+
mutable id<MTLBuffer> searchOutIdxBuf_ = nil;
|
|
150
|
+
mutable size_t searchQueriesCap_ = 0; // bytes
|
|
151
|
+
mutable size_t searchCoarseCap_ = 0;
|
|
152
|
+
mutable size_t searchOutDistCap_ = 0;
|
|
153
|
+
mutable size_t searchOutIdxCap_ = 0;
|
|
154
|
+
mutable id<MTLBuffer> searchPerListDistBuf_ = nil;
|
|
155
|
+
mutable id<MTLBuffer> searchPerListIdxBuf_ = nil;
|
|
156
|
+
mutable size_t searchPerListDistCap_ = 0;
|
|
157
|
+
mutable size_t searchPerListIdxCap_ = 0;
|
|
158
|
+
|
|
159
|
+
// GPU coarse quantizer buffers (cached, rebuilt on train)
|
|
160
|
+
mutable id<MTLBuffer> centroidBuf_ = nil;
|
|
161
|
+
mutable id<MTLBuffer> centroidNormsBuf_ = nil; // pre-computed ||c||²
|
|
162
|
+
mutable id<MTLBuffer> coarseOutDistBuf_ = nil;
|
|
163
|
+
mutable id<MTLBuffer> coarseOutIdxBuf_ = nil;
|
|
164
|
+
mutable size_t coarseOutDistCap_ = 0;
|
|
165
|
+
mutable size_t coarseOutIdxCap_ = 0;
|
|
166
|
+
mutable id<MTLBuffer> distMatrixBuf_ = nil;
|
|
167
|
+
mutable size_t distMatrixCap_ = 0;
|
|
168
|
+
|
|
169
|
+
/// Ensures buf is at least `needed` bytes, reallocating if necessary.
|
|
170
|
+
void ensureSearchBuf_(id<MTLBuffer>& buf, size_t& cap, size_t needed) const;
|
|
171
|
+
|
|
172
|
+
/// (Re)uploads quantizer centroids to centroidBuf_.
|
|
173
|
+
void uploadCentroids_() const;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
} // namespace gpu_metal
|
|
177
|
+
} // namespace faiss
|
|
@@ -0,0 +1,88 @@
|
|
|
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 index: 8-bit product quantization with precomputed
|
|
9
|
+
* per-query lookup tables and GPU IVF list scanning.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
#pragma once
|
|
13
|
+
|
|
14
|
+
#import <Metal/Metal.h>
|
|
15
|
+
|
|
16
|
+
#include <faiss/IndexIVFPQ.h>
|
|
17
|
+
#include <faiss/gpu_metal/MetalIndex.h>
|
|
18
|
+
|
|
19
|
+
#include <memory>
|
|
20
|
+
|
|
21
|
+
namespace faiss {
|
|
22
|
+
namespace gpu_metal {
|
|
23
|
+
|
|
24
|
+
class MetalIVFPQImpl;
|
|
25
|
+
|
|
26
|
+
class MetalIndexIVFPQ : public MetalIndex {
|
|
27
|
+
public:
|
|
28
|
+
MetalIndexIVFPQ(
|
|
29
|
+
std::shared_ptr<MetalResources> resources,
|
|
30
|
+
int dims,
|
|
31
|
+
idx_t nlist,
|
|
32
|
+
int M,
|
|
33
|
+
int nbitsPerIdx,
|
|
34
|
+
faiss::MetricType metric,
|
|
35
|
+
float metricArg = 0.0f,
|
|
36
|
+
MetalIndexConfig config = MetalIndexConfig());
|
|
37
|
+
|
|
38
|
+
MetalIndexIVFPQ(
|
|
39
|
+
std::shared_ptr<MetalResources> resources,
|
|
40
|
+
const faiss::IndexIVFPQ* cpuIndex,
|
|
41
|
+
MetalIndexConfig config = MetalIndexConfig());
|
|
42
|
+
|
|
43
|
+
~MetalIndexIVFPQ() override;
|
|
44
|
+
|
|
45
|
+
void train(idx_t n, const float* x) override;
|
|
46
|
+
void add(idx_t n, const float* x) override;
|
|
47
|
+
void add_with_ids(idx_t n, const float* x, const idx_t* xids) override;
|
|
48
|
+
void reset() override;
|
|
49
|
+
|
|
50
|
+
void search(
|
|
51
|
+
idx_t n,
|
|
52
|
+
const float* x,
|
|
53
|
+
idx_t k,
|
|
54
|
+
float* distances,
|
|
55
|
+
idx_t* labels,
|
|
56
|
+
const SearchParameters* params = nullptr) const override;
|
|
57
|
+
|
|
58
|
+
void copyFrom(const faiss::IndexIVFPQ* index);
|
|
59
|
+
void copyTo(faiss::IndexIVFPQ* index) const;
|
|
60
|
+
|
|
61
|
+
void updateQuantizer();
|
|
62
|
+
std::vector<idx_t> getListIndices(idx_t listId) const;
|
|
63
|
+
void reclaimMemory();
|
|
64
|
+
|
|
65
|
+
/// Pre-allocate GPU storage for the given total number of vectors.
|
|
66
|
+
void reserveMemory(idx_t numVecs);
|
|
67
|
+
|
|
68
|
+
idx_t nlist() const;
|
|
69
|
+
size_t nprobe() const;
|
|
70
|
+
int getNumSubQuantizers() const;
|
|
71
|
+
void setUsePrecomputedTables(bool enable);
|
|
72
|
+
bool getUsePrecomputedTables() const;
|
|
73
|
+
|
|
74
|
+
private:
|
|
75
|
+
std::unique_ptr<faiss::IndexIVFPQ> cpuIndex_;
|
|
76
|
+
std::unique_ptr<MetalIVFPQImpl> gpuIvf_;
|
|
77
|
+
|
|
78
|
+
void verifyPQSettings_() const;
|
|
79
|
+
|
|
80
|
+
void encodeResidualAndAppend_(
|
|
81
|
+
idx_t n,
|
|
82
|
+
const float* x,
|
|
83
|
+
const idx_t* list_nos,
|
|
84
|
+
const idx_t* xids);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
} // namespace gpu_metal
|
|
88
|
+
} // namespace faiss
|
|
@@ -19,13 +19,15 @@
|
|
|
19
19
|
namespace faiss {
|
|
20
20
|
namespace gpu_metal {
|
|
21
21
|
|
|
22
|
+
enum class IVFScanVariant { Standard, Small, Interleaved };
|
|
23
|
+
|
|
22
24
|
class MetalKernels {
|
|
23
25
|
public:
|
|
24
26
|
explicit MetalKernels(id<MTLDevice> device);
|
|
25
27
|
~MetalKernels();
|
|
26
28
|
|
|
27
29
|
bool isValid() const;
|
|
28
|
-
static constexpr int kMaxK =
|
|
30
|
+
static constexpr int kMaxK = 2048;
|
|
29
31
|
|
|
30
32
|
void encodeDistanceMatrix(
|
|
31
33
|
id<MTLComputeCommandEncoder> enc,
|
|
@@ -37,6 +39,23 @@ class MetalKernels {
|
|
|
37
39
|
int d,
|
|
38
40
|
MetricType metric);
|
|
39
41
|
|
|
42
|
+
void encodeL2WithNorms(
|
|
43
|
+
id<MTLComputeCommandEncoder> enc,
|
|
44
|
+
id<MTLBuffer> queries,
|
|
45
|
+
id<MTLBuffer> vectors,
|
|
46
|
+
id<MTLBuffer> distances,
|
|
47
|
+
id<MTLBuffer> vecNorms,
|
|
48
|
+
int nq,
|
|
49
|
+
int nb,
|
|
50
|
+
int d);
|
|
51
|
+
|
|
52
|
+
void encodeComputeNorms(
|
|
53
|
+
id<MTLComputeCommandEncoder> enc,
|
|
54
|
+
id<MTLBuffer> vectors,
|
|
55
|
+
id<MTLBuffer> norms,
|
|
56
|
+
int nb,
|
|
57
|
+
int d);
|
|
58
|
+
|
|
40
59
|
void encodeTopKThreadgroup(
|
|
41
60
|
id<MTLComputeCommandEncoder> enc,
|
|
42
61
|
id<MTLBuffer> distances,
|
|
@@ -47,6 +66,31 @@ class MetalKernels {
|
|
|
47
66
|
int k,
|
|
48
67
|
bool wantMin);
|
|
49
68
|
|
|
69
|
+
void encodeIVFScanList(
|
|
70
|
+
id<MTLComputeCommandEncoder> enc,
|
|
71
|
+
IVFScanVariant variant,
|
|
72
|
+
id<MTLBuffer> queries,
|
|
73
|
+
id<MTLBuffer> codes,
|
|
74
|
+
id<MTLBuffer> ids,
|
|
75
|
+
id<MTLBuffer> listOffset,
|
|
76
|
+
id<MTLBuffer> listLength,
|
|
77
|
+
id<MTLBuffer> coarseAssign,
|
|
78
|
+
id<MTLBuffer> perListDist,
|
|
79
|
+
id<MTLBuffer> perListIdx,
|
|
80
|
+
id<MTLBuffer> paramsBuf,
|
|
81
|
+
int nq,
|
|
82
|
+
int nprobe,
|
|
83
|
+
id<MTLBuffer> ilCodesOffset = nil);
|
|
84
|
+
|
|
85
|
+
void encodeIVFMergeLists(
|
|
86
|
+
id<MTLComputeCommandEncoder> enc,
|
|
87
|
+
id<MTLBuffer> perListDist,
|
|
88
|
+
id<MTLBuffer> perListIdx,
|
|
89
|
+
id<MTLBuffer> outDist,
|
|
90
|
+
id<MTLBuffer> outIdx,
|
|
91
|
+
id<MTLBuffer> paramsBuf,
|
|
92
|
+
int nq);
|
|
93
|
+
|
|
50
94
|
static int selectTopKVariantIndex(int k);
|
|
51
95
|
|
|
52
96
|
private:
|
|
@@ -56,8 +100,9 @@ class MetalKernels {
|
|
|
56
100
|
id<MTLLibrary> library_;
|
|
57
101
|
std::unordered_map<std::string, id<MTLComputePipelineState>> cache_;
|
|
58
102
|
|
|
59
|
-
static constexpr int kTopKVariantSizes[] =
|
|
60
|
-
|
|
103
|
+
static constexpr int kTopKVariantSizes[] =
|
|
104
|
+
{32, 64, 128, 256, 512, 1024, 2048};
|
|
105
|
+
static constexpr int kNumTopKVariants = 7;
|
|
61
106
|
};
|
|
62
107
|
|
|
63
108
|
MetalKernels& getMetalKernels(id<MTLDevice> device);
|