faiss 0.6.4 → 0.6.5
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 +4 -0
- data/ext/faiss/extconf.rb +1 -1
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +175 -0
- data/vendor/faiss/faiss/Clustering.cpp +150 -60
- data/vendor/faiss/faiss/Clustering.h +29 -0
- data/vendor/faiss/faiss/IVFlib.cpp +99 -0
- data/vendor/faiss/faiss/IVFlib.h +15 -0
- data/vendor/faiss/faiss/Index.cpp +44 -0
- data/vendor/faiss/faiss/Index.h +19 -14
- data/vendor/faiss/faiss/IndexBinary.cpp +8 -0
- data/vendor/faiss/faiss/IndexBinary.h +8 -0
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +82 -4
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +19 -0
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +34 -0
- data/vendor/faiss/faiss/IndexFastScan.cpp +33 -17
- data/vendor/faiss/faiss/IndexFastScan.h +6 -3
- data/vendor/faiss/faiss/IndexFlat.cpp +56 -0
- data/vendor/faiss/faiss/IndexFlat.h +31 -0
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +6 -1
- data/vendor/faiss/faiss/IndexHNSW.cpp +456 -10
- data/vendor/faiss/faiss/IndexHNSW.h +38 -0
- data/vendor/faiss/faiss/IndexIDMap.cpp +32 -0
- data/vendor/faiss/faiss/IndexIDMap.h +7 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +281 -31
- data/vendor/faiss/faiss/IndexIVF.h +53 -1
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +46 -14
- data/vendor/faiss/faiss/IndexIVFFastScan.h +4 -2
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +33 -0
- data/vendor/faiss/faiss/IndexIVFFlat.h +16 -0
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +1 -0
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +3 -20
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +50 -14
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -2
- data/vendor/faiss/faiss/IndexIVFSQFastScan.cpp +855 -0
- data/vendor/faiss/faiss/IndexIVFSQFastScan.h +145 -0
- data/vendor/faiss/faiss/IndexNNDescent.cpp +0 -3
- data/vendor/faiss/faiss/IndexPiPNN.cpp +201 -0
- data/vendor/faiss/faiss/IndexPiPNN.h +83 -0
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +6 -3
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +10 -4
- data/vendor/faiss/faiss/IndexReplicas.cpp +20 -0
- data/vendor/faiss/faiss/IndexReplicas.h +9 -0
- data/vendor/faiss/faiss/IndexSQFastScan.cpp +648 -0
- data/vendor/faiss/faiss/IndexSQFastScan.h +129 -0
- data/vendor/faiss/faiss/IndexShards.cpp +10 -0
- data/vendor/faiss/faiss/IndexShards.h +5 -0
- data/vendor/faiss/faiss/SuperKMeans.cpp +57 -15
- data/vendor/faiss/faiss/SuperKMeans.h +9 -4
- data/vendor/faiss/faiss/VectorTransform.cpp +3 -2
- data/vendor/faiss/faiss/clone_index.cpp +24 -0
- data/vendor/faiss/faiss/gpu/Dataset.h +112 -0
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +16 -13
- data/vendor/faiss/faiss/gpu/GpuCloner.h +4 -0
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +3 -0
- data/vendor/faiss/faiss/gpu/GpuIndex.h +4 -13
- data/vendor/faiss/faiss/gpu/GpuIndexBinaryCagra.h +26 -13
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +45 -22
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +6 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuDatasetHeader.cpp +18 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +215 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +98 -0
- data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +11 -0
- data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +1 -1
- data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +11 -0
- data/vendor/faiss/faiss/gpu_metal/MetalDistance.h +92 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +4 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexBinaryFlat.h +69 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +38 -0
- data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +106 -0
- data/vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h +10 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +2 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +1 -6
- data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +134 -45
- data/vendor/faiss/faiss/impl/ClusteringHelpers.h +36 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +286 -136
- data/vendor/faiss/faiss/impl/DistanceComputer.cpp +63 -0
- data/vendor/faiss/faiss/impl/DistanceComputer.h +3 -29
- data/vendor/faiss/faiss/impl/HNSW.cpp +46 -10
- data/vendor/faiss/faiss/impl/HNSW.h +72 -0
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +6 -19
- data/vendor/faiss/faiss/impl/NNDescent.cpp +2 -1
- data/vendor/faiss/faiss/impl/NSG.cpp +3 -2
- data/vendor/faiss/faiss/impl/Panorama.h +3 -2
- data/vendor/faiss/faiss/impl/PiPNN.cpp +822 -0
- data/vendor/faiss/faiss/impl/PiPNN.h +122 -0
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +54 -11
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +1 -1
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +81 -57
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +15 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +29 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +1 -6
- data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +5 -2
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +0 -4
- data/vendor/faiss/faiss/impl/expanded_scanners.h +88 -0
- data/vendor/faiss/faiss/impl/fast_scan/FastScanDistancePostProcessing.h +4 -0
- data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +61 -64
- data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +13 -14
- data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +17 -129
- data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +25 -19
- data/vendor/faiss/faiss/impl/fast_scan/fast_scan.cpp +5 -0
- data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +0 -88
- data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +0 -4
- data/vendor/faiss/faiss/impl/fast_scan/kernels_neon.h +155 -0
- data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +22 -1
- data/vendor/faiss/faiss/impl/fast_scan/kernels_simd512.h +3 -2
- data/vendor/faiss/faiss/impl/fast_scan/simd_result_handlers.h +41 -23
- data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/index_read.cpp +172 -0
- data/vendor/faiss/faiss/impl/index_write.cpp +95 -0
- data/vendor/faiss/faiss/impl/pipnn/HashPrune.cpp +159 -0
- data/vendor/faiss/faiss/impl/pipnn/HashPrune.h +69 -0
- data/vendor/faiss/faiss/impl/pipnn/Partition.cpp +587 -0
- data/vendor/faiss/faiss/impl/pipnn/Partition.h +93 -0
- data/vendor/faiss/faiss/impl/pipnn/kernels.cpp +326 -0
- data/vendor/faiss/faiss/impl/pipnn/kernels.h +92 -0
- data/vendor/faiss/faiss/impl/platform_macros.h +45 -0
- data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +79 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +6 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-avx2.h +4 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-avx512.h +4 -1
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +19 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +6 -6
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +131 -6
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_rvv_kernel.h +89 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_scan_impl.h +21 -10
- data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +45 -18
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +2 -1
- data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +5 -1
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +28 -52
- data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +59 -11
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +226 -77
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +482 -103
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +2 -149
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +3 -698
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +66 -57
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +101 -96
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +3185 -144
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq8_coefficients.h +48 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq8_rvv_kernel.h +546 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +2 -2
- data/vendor/faiss/faiss/impl/simd_dispatch.h +7 -0
- data/vendor/faiss/faiss/impl/simdlib/simdlib_avx2.h +14 -0
- data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +7 -8
- data/vendor/faiss/faiss/impl/sq_fastscan_utils.h +232 -0
- data/vendor/faiss/faiss/index_factory.cpp +76 -0
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +3 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +3 -2
- data/vendor/faiss/faiss/utils/AlignedTable.h +6 -1
- data/vendor/faiss/faiss/utils/Heap.cpp +4 -3
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +16 -5
- data/vendor/faiss/faiss/utils/bf16.h +36 -0
- data/vendor/faiss/faiss/utils/distances.cpp +226 -15
- data/vendor/faiss/faiss/utils/distances.h +34 -0
- data/vendor/faiss/faiss/utils/distances_dispatch.h +6 -4
- data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +2 -5
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +0 -14
- data/vendor/faiss/faiss/utils/distances_fused/rvv.cpp +25 -0
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +0 -4
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +0 -4
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +2 -1
- data/vendor/faiss/faiss/utils/distances_simd.cpp +9 -0
- data/vendor/faiss/faiss/utils/fp16-fp16c.h +4 -0
- data/vendor/faiss/faiss/utils/fp16-inl.h +26 -52
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_vpopcnt.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +33 -5
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512_vpopcnt.h +15 -30
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-neon.h +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +2 -1
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_neon.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_rvv.cpp +0 -4
- data/vendor/faiss/faiss/utils/pq_code_distance.h +8 -4
- data/vendor/faiss/faiss/utils/prefetch.h +1 -26
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +26 -27
- data/vendor/faiss/faiss/utils/quantize_lut.h +11 -0
- data/vendor/faiss/faiss/utils/rabitq_simd.h +51 -16
- data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +9 -4
- data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +37 -5
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +64 -5
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +64 -5
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +353 -71
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv_kernel.h +68 -0
- data/vendor/faiss/faiss/utils/simd_impl/exhaustive_L2sqr_blas_cmax.h +93 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels.h +76 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_avx2.cpp +52 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_avx512.cpp +52 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_neon.cpp +48 -0
- data/vendor/faiss/faiss/utils/simd_impl/masked_sum-avx2.h +44 -0
- data/vendor/faiss/faiss/utils/simd_impl/masked_sum-avx512.h +43 -0
- data/vendor/faiss/faiss/utils/simd_impl/masked_sum.h +38 -0
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_avx2.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_neon.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +54 -15
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +38 -21
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_vpopcnt.cpp +51 -14
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +297 -10
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_sve.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_levels.cpp +19 -3
- data/vendor/faiss/faiss/utils/simd_levels.h +74 -1
- data/vendor/faiss/faiss/utils/transpose/transpose-avx2-inl.h +0 -4
- data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +0 -4
- data/vendor/faiss/faiss/utils/utils.cpp +80 -0
- data/vendor/faiss/faiss/utils/utils.h +24 -0
- metadata +33 -1
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#include <faiss/IVFlib.h>
|
|
9
9
|
#include <omp.h>
|
|
10
10
|
|
|
11
|
+
#include <algorithm>
|
|
11
12
|
#include <memory>
|
|
12
13
|
|
|
13
14
|
#include <faiss/IndexAdditiveQuantizer.h>
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
#include <faiss/impl/FaissAssert.h>
|
|
21
22
|
#include <faiss/impl/simd_dispatch.h>
|
|
22
23
|
#include <faiss/index_io.h>
|
|
24
|
+
#include <faiss/utils/Heap.h>
|
|
23
25
|
#include <faiss/utils/distances.h>
|
|
24
26
|
#include <faiss/utils/hamming.h>
|
|
25
27
|
#include <faiss/utils/utils.h>
|
|
@@ -407,6 +409,103 @@ void search_with_parameters(
|
|
|
407
409
|
}
|
|
408
410
|
}
|
|
409
411
|
|
|
412
|
+
namespace {
|
|
413
|
+
|
|
414
|
+
template <class C>
|
|
415
|
+
void scan_one_query_per_code(
|
|
416
|
+
const IndexIVF& index_ivf,
|
|
417
|
+
InvertedListScanner& scanner,
|
|
418
|
+
const idx_t* keys,
|
|
419
|
+
const float* coarse_dis,
|
|
420
|
+
size_t nprobe,
|
|
421
|
+
idx_t k,
|
|
422
|
+
float* distances,
|
|
423
|
+
idx_t* labels) {
|
|
424
|
+
heap_heapify<C>(k, distances, labels);
|
|
425
|
+
const InvertedLists* invlists = index_ivf.invlists;
|
|
426
|
+
for (size_t j = 0; j < nprobe; j++) {
|
|
427
|
+
const idx_t key = keys[j];
|
|
428
|
+
if (key < 0) {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
scanner.set_list(key, coarse_dis[j]);
|
|
432
|
+
const size_t list_size = invlists->list_size(key);
|
|
433
|
+
InvertedLists::ScopedCodes codes(invlists, key);
|
|
434
|
+
InvertedLists::ScopedIds ids(invlists, key);
|
|
435
|
+
const uint8_t* code = codes.get();
|
|
436
|
+
for (size_t i = 0; i < list_size; i++, code += index_ivf.code_size) {
|
|
437
|
+
const float dis = scanner.distance_to_code(code);
|
|
438
|
+
if (C::cmp(distances[0], dis)) {
|
|
439
|
+
heap_replace_top<C>(k, distances, labels, dis, ids[i]);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
heap_reorder<C>(k, distances, labels);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
} // namespace
|
|
447
|
+
|
|
448
|
+
void search_with_distance_to_code(
|
|
449
|
+
const Index* index,
|
|
450
|
+
idx_t n,
|
|
451
|
+
const float* x,
|
|
452
|
+
idx_t k,
|
|
453
|
+
float* distances,
|
|
454
|
+
idx_t* labels,
|
|
455
|
+
size_t nprobe) {
|
|
456
|
+
std::unique_ptr<const float[]> del;
|
|
457
|
+
if (auto ip = dynamic_cast<const IndexPreTransform*>(index)) {
|
|
458
|
+
const float* xt = ip->apply_chain(n, x);
|
|
459
|
+
if (xt != x) {
|
|
460
|
+
del.reset(xt);
|
|
461
|
+
}
|
|
462
|
+
x = xt;
|
|
463
|
+
index = ip->index;
|
|
464
|
+
}
|
|
465
|
+
const IndexIVF* index_ivf = dynamic_cast<const IndexIVF*>(index);
|
|
466
|
+
FAISS_THROW_IF_NOT(index_ivf);
|
|
467
|
+
nprobe = std::min(nprobe, index_ivf->nlist);
|
|
468
|
+
|
|
469
|
+
std::vector<idx_t> Iq(nprobe * n);
|
|
470
|
+
std::vector<float> Dq(nprobe * n);
|
|
471
|
+
index_ivf->quantizer->search(n, x, nprobe, Dq.data(), Iq.data());
|
|
472
|
+
|
|
473
|
+
#pragma omp parallel
|
|
474
|
+
{
|
|
475
|
+
std::unique_ptr<InvertedListScanner> scanner(
|
|
476
|
+
index_ivf->get_InvertedListScanner());
|
|
477
|
+
#pragma omp for
|
|
478
|
+
for (idx_t q = 0; q < n; q++) {
|
|
479
|
+
scanner->set_query(x + q * index_ivf->d);
|
|
480
|
+
const idx_t* keys = Iq.data() + q * nprobe;
|
|
481
|
+
const float* coarse_dis = Dq.data() + q * nprobe;
|
|
482
|
+
float* D = distances + q * k;
|
|
483
|
+
idx_t* I = labels + q * k;
|
|
484
|
+
if (scanner->keep_max) {
|
|
485
|
+
scan_one_query_per_code<CMin<float, idx_t>>(
|
|
486
|
+
*index_ivf,
|
|
487
|
+
*scanner,
|
|
488
|
+
keys,
|
|
489
|
+
coarse_dis,
|
|
490
|
+
nprobe,
|
|
491
|
+
k,
|
|
492
|
+
D,
|
|
493
|
+
I);
|
|
494
|
+
} else {
|
|
495
|
+
scan_one_query_per_code<CMax<float, idx_t>>(
|
|
496
|
+
*index_ivf,
|
|
497
|
+
*scanner,
|
|
498
|
+
keys,
|
|
499
|
+
coarse_dis,
|
|
500
|
+
nprobe,
|
|
501
|
+
k,
|
|
502
|
+
D,
|
|
503
|
+
I);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
410
509
|
void range_search_with_parameters(
|
|
411
510
|
const Index* index,
|
|
412
511
|
idx_t n,
|
data/vendor/faiss/faiss/IVFlib.h
CHANGED
|
@@ -136,6 +136,21 @@ void search_with_parameters(
|
|
|
136
136
|
size_t* nb_dis = nullptr,
|
|
137
137
|
double* ms_per_stage = nullptr);
|
|
138
138
|
|
|
139
|
+
/** search an IndexIVF, possibly embedded in an IndexPreTransform, scoring
|
|
140
|
+
* every code with InvertedListScanner::distance_to_code, one call per code,
|
|
141
|
+
* as callers that run their own scan loop do (search() uses scan_codes,
|
|
142
|
+
* which batches codes). Meant for benchmarking that path. Each query is
|
|
143
|
+
* scanned by one thread; queries run in parallel.
|
|
144
|
+
*/
|
|
145
|
+
void search_with_distance_to_code(
|
|
146
|
+
const Index* index,
|
|
147
|
+
idx_t n,
|
|
148
|
+
const float* x,
|
|
149
|
+
idx_t k,
|
|
150
|
+
float* distances,
|
|
151
|
+
idx_t* labels,
|
|
152
|
+
size_t nprobe);
|
|
153
|
+
|
|
139
154
|
/** same as search_with_parameters but for range search */
|
|
140
155
|
void range_search_with_parameters(
|
|
141
156
|
const Index* index,
|
|
@@ -13,8 +13,11 @@
|
|
|
13
13
|
#include <faiss/impl/DistanceComputer.h>
|
|
14
14
|
#include <faiss/impl/FaissAssert.h>
|
|
15
15
|
#include <faiss/utils/distances.h>
|
|
16
|
+
#include <faiss/utils/utils.h>
|
|
16
17
|
|
|
18
|
+
#include <algorithm>
|
|
17
19
|
#include <cstring>
|
|
20
|
+
#include <vector>
|
|
18
21
|
|
|
19
22
|
namespace faiss {
|
|
20
23
|
|
|
@@ -24,6 +27,14 @@ void Index::train(idx_t /*n*/, const float* /*x*/) {
|
|
|
24
27
|
// does nothing by default
|
|
25
28
|
}
|
|
26
29
|
|
|
30
|
+
void Index::train(const gpu::Dataset&) {
|
|
31
|
+
FAISS_THROW_MSG("Dataset training not implemented for this type of index");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
void Index::add(const gpu::Dataset&) {
|
|
35
|
+
FAISS_THROW_MSG("Dataset addition not implemented for this type of index");
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
void Index::train_with_queries(
|
|
28
39
|
idx_t /*n*/,
|
|
29
40
|
const float* /*x*/,
|
|
@@ -123,6 +134,39 @@ void Index::search_subset(
|
|
|
123
134
|
FAISS_THROW_MSG("search_subset not implemented for this type of index");
|
|
124
135
|
}
|
|
125
136
|
|
|
137
|
+
void Index::search_ex(
|
|
138
|
+
idx_t n,
|
|
139
|
+
const void* x,
|
|
140
|
+
NumericType numeric_type,
|
|
141
|
+
idx_t k,
|
|
142
|
+
float* distances,
|
|
143
|
+
idx_t* labels,
|
|
144
|
+
const SearchParameters* params) const {
|
|
145
|
+
if (numeric_type == NumericType::Float32) {
|
|
146
|
+
search(n, static_cast<const float*>(x), k, distances, labels, params);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
150
|
+
numeric_type == NumericType::Float16,
|
|
151
|
+
"Index::search: unsupported numeric type");
|
|
152
|
+
FAISS_THROW_IF_NOT(d > 0);
|
|
153
|
+
// widen blocks of at most 64 MiB of fp32 queries
|
|
154
|
+
const idx_t bs = std::max<idx_t>(
|
|
155
|
+
1, idx_t(64) * 1024 * 1024 / (sizeof(float) * idx_t(d)));
|
|
156
|
+
const uint16_t* x16 = static_cast<const uint16_t*>(x);
|
|
157
|
+
std::vector<float> buffer(size_t(std::min(n, bs)) * d);
|
|
158
|
+
for (idx_t i0 = 0; i0 < n; i0 += bs) {
|
|
159
|
+
const idx_t i1 = std::min(n, i0 + bs);
|
|
160
|
+
fp16_to_fp32(size_t(i1 - i0) * d, x16 + i0 * d, buffer.data());
|
|
161
|
+
search(i1 - i0,
|
|
162
|
+
buffer.data(),
|
|
163
|
+
k,
|
|
164
|
+
distances + i0 * k,
|
|
165
|
+
labels + i0 * k,
|
|
166
|
+
params);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
126
170
|
void Index::search1(const float*, ResultHandler&, SearchParameters*) const {
|
|
127
171
|
FAISS_THROW_MSG("search1 not implemented for this type of index");
|
|
128
172
|
}
|
data/vendor/faiss/faiss/Index.h
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
#include <cstdio>
|
|
17
17
|
|
|
18
18
|
#define FAISS_VERSION_MAJOR 1
|
|
19
|
-
#define FAISS_VERSION_MINOR
|
|
20
|
-
#define FAISS_VERSION_PATCH
|
|
19
|
+
#define FAISS_VERSION_MINOR 16
|
|
20
|
+
#define FAISS_VERSION_PATCH 0
|
|
21
21
|
|
|
22
22
|
// Macro to combine the version components into a single string
|
|
23
23
|
#ifndef FAISS_STRINGIFY
|
|
@@ -49,6 +49,10 @@
|
|
|
49
49
|
|
|
50
50
|
namespace faiss {
|
|
51
51
|
|
|
52
|
+
namespace gpu {
|
|
53
|
+
class Dataset;
|
|
54
|
+
}
|
|
55
|
+
|
|
52
56
|
/// Forward declarations see impl/AuxIndexStructures.h, impl/IDSelector.h
|
|
53
57
|
/// and impl/DistanceComputer.h
|
|
54
58
|
struct IDSelector;
|
|
@@ -131,6 +135,9 @@ struct Index {
|
|
|
131
135
|
*/
|
|
132
136
|
virtual void train(idx_t n, const float* x);
|
|
133
137
|
|
|
138
|
+
/// Train from caller-controlled storage. Unsupported by default.
|
|
139
|
+
virtual void train(const gpu::Dataset& dataset);
|
|
140
|
+
|
|
134
141
|
/** Perform training on a representative set of vectors and a representative
|
|
135
142
|
* set of queries
|
|
136
143
|
*
|
|
@@ -163,6 +170,9 @@ struct Index {
|
|
|
163
170
|
*/
|
|
164
171
|
virtual void add(idx_t n, const float* x) = 0;
|
|
165
172
|
|
|
173
|
+
/// Add caller-controlled storage. Unsupported by default.
|
|
174
|
+
virtual void add(const gpu::Dataset& dataset);
|
|
175
|
+
|
|
166
176
|
virtual void add_ex(idx_t n, const void* x, NumericType numeric_type) {
|
|
167
177
|
if (numeric_type == NumericType::Float32) {
|
|
168
178
|
add(n, static_cast<const float*>(x));
|
|
@@ -212,6 +222,12 @@ struct Index {
|
|
|
212
222
|
idx_t* labels,
|
|
213
223
|
const SearchParameters* params = nullptr) const = 0;
|
|
214
224
|
|
|
225
|
+
/** search() for queries of the given numeric type
|
|
226
|
+
*
|
|
227
|
+
* Float32 calls search(). By default, Float16 queries (packed IEEE
|
|
228
|
+
* binary16, size n * d) are widened to fp32 in bounded blocks and passed
|
|
229
|
+
* to search(); indexes with a native fp16 search override this.
|
|
230
|
+
*/
|
|
215
231
|
virtual void search_ex(
|
|
216
232
|
idx_t n,
|
|
217
233
|
const void* x,
|
|
@@ -219,18 +235,7 @@ struct Index {
|
|
|
219
235
|
idx_t k,
|
|
220
236
|
float* distances,
|
|
221
237
|
idx_t* labels,
|
|
222
|
-
const SearchParameters* params = nullptr) const
|
|
223
|
-
if (numeric_type == NumericType::Float32) {
|
|
224
|
-
search(n,
|
|
225
|
-
static_cast<const float*>(x),
|
|
226
|
-
k,
|
|
227
|
-
distances,
|
|
228
|
-
labels,
|
|
229
|
-
params);
|
|
230
|
-
} else {
|
|
231
|
-
FAISS_THROW_MSG("Index::search: unsupported numeric type");
|
|
232
|
-
}
|
|
233
|
-
}
|
|
238
|
+
const SearchParameters* params = nullptr) const;
|
|
234
239
|
|
|
235
240
|
/** search one vector with a custom result handler */
|
|
236
241
|
virtual void search1(
|
|
@@ -29,6 +29,14 @@ void IndexBinary::train(idx_t, const uint8_t*) {
|
|
|
29
29
|
// Does nothing by default.
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
void IndexBinary::train(const gpu::Dataset&) {
|
|
33
|
+
FAISS_THROW_MSG("Dataset training not implemented for this type of index");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void IndexBinary::add(const gpu::Dataset&) {
|
|
37
|
+
FAISS_THROW_MSG("Dataset addition not implemented for this type of index");
|
|
38
|
+
}
|
|
39
|
+
|
|
32
40
|
void IndexBinary::range_search(
|
|
33
41
|
idx_t,
|
|
34
42
|
const uint8_t*,
|
|
@@ -52,6 +52,10 @@ struct IndexBinary {
|
|
|
52
52
|
* @param x training vectors, size n * d / 8
|
|
53
53
|
*/
|
|
54
54
|
virtual void train(idx_t n, const uint8_t* x);
|
|
55
|
+
|
|
56
|
+
/// Train from caller-controlled storage. Unsupported by default.
|
|
57
|
+
virtual void train(const gpu::Dataset& dataset);
|
|
58
|
+
|
|
55
59
|
virtual void train_ex(idx_t n, const void* x, NumericType numeric_type) {
|
|
56
60
|
if (numeric_type == NumericType::UInt8) {
|
|
57
61
|
train(n, static_cast<const uint8_t*>(x));
|
|
@@ -66,6 +70,10 @@ struct IndexBinary {
|
|
|
66
70
|
* @param x input matrix, size n * d / 8
|
|
67
71
|
*/
|
|
68
72
|
virtual void add(idx_t n, const uint8_t* x) = 0;
|
|
73
|
+
|
|
74
|
+
/// Add caller-controlled storage. Unsupported by default.
|
|
75
|
+
virtual void add(const gpu::Dataset& dataset);
|
|
76
|
+
|
|
69
77
|
virtual void add_ex(idx_t n, const void* x, NumericType numeric_type) {
|
|
70
78
|
if (numeric_type == NumericType::UInt8) {
|
|
71
79
|
add(n, static_cast<const uint8_t*>(x));
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
#include <faiss/impl/VisitedTable.h>
|
|
25
25
|
#include <faiss/utils/Heap.h>
|
|
26
26
|
#include <faiss/utils/random.h>
|
|
27
|
+
#include <faiss/utils/utils.h>
|
|
27
28
|
|
|
28
29
|
#include <faiss/impl/simd_dispatch.h>
|
|
29
30
|
|
|
@@ -121,7 +122,9 @@ void IndexBinaryHNSW::search(
|
|
|
121
122
|
}
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
|
|
125
|
+
if (get_search_stats_enabled()) {
|
|
126
|
+
hnsw_stats.combine_atomic({n1, n2, ndis, nhops});
|
|
127
|
+
}
|
|
125
128
|
|
|
126
129
|
#pragma omp parallel for
|
|
127
130
|
for (idx_t i = 0; i < n * k; ++i) {
|
|
@@ -173,6 +176,81 @@ DistanceComputer* IndexBinaryHNSW::get_distance_computer() const {
|
|
|
173
176
|
});
|
|
174
177
|
}
|
|
175
178
|
|
|
179
|
+
namespace {
|
|
180
|
+
|
|
181
|
+
// The sample of an IndexBinaryHNSW. Hamming distances are integers, so a
|
|
182
|
+
// nearer node has a strictly smaller distance.
|
|
183
|
+
struct BinaryLinkSample : HNSWLinkSampleSearch {
|
|
184
|
+
const IndexBinaryHNSW& index;
|
|
185
|
+
const uint8_t* x;
|
|
186
|
+
|
|
187
|
+
BinaryLinkSample(const IndexBinaryHNSW& index, idx_t n, const uint8_t* x)
|
|
188
|
+
: index(index), x(x) {
|
|
189
|
+
this->n = n;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
std::vector<uint8_t> gather(size_t m, const idx_t* ids) const {
|
|
193
|
+
const size_t cs = index.code_size;
|
|
194
|
+
std::vector<uint8_t> rows(m * cs);
|
|
195
|
+
for (size_t j = 0; j < m; j++) {
|
|
196
|
+
memcpy(rows.data() + j * cs, x + ids[j] * cs, cs);
|
|
197
|
+
}
|
|
198
|
+
return rows;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
void search(
|
|
202
|
+
const SearchParametersHNSW* params,
|
|
203
|
+
size_t m,
|
|
204
|
+
const idx_t* ids,
|
|
205
|
+
idx_t* labels) const override {
|
|
206
|
+
std::vector<int32_t> distances(m);
|
|
207
|
+
if (!ids) {
|
|
208
|
+
index.search(m, x, 1, distances.data(), labels, params);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
index.search(
|
|
212
|
+
m, gather(m, ids).data(), 1, distances.data(), labels, params);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
void search_exact(
|
|
216
|
+
size_t m,
|
|
217
|
+
const idx_t* ids,
|
|
218
|
+
const idx_t* found,
|
|
219
|
+
idx_t* exact,
|
|
220
|
+
uint8_t* nearer) const override {
|
|
221
|
+
const size_t cs = index.code_size;
|
|
222
|
+
const std::vector<uint8_t> rows = gather(m, ids);
|
|
223
|
+
std::vector<int32_t> distances(m);
|
|
224
|
+
index.storage->search(m, rows.data(), 1, distances.data(), exact);
|
|
225
|
+
#pragma omp parallel
|
|
226
|
+
{
|
|
227
|
+
std::unique_ptr<DistanceComputer> dis(
|
|
228
|
+
index.get_distance_computer());
|
|
229
|
+
#pragma omp for schedule(static)
|
|
230
|
+
for (int64_t j = 0; j < static_cast<int64_t>(m); j++) {
|
|
231
|
+
if (exact[j] < 0 || exact[j] == found[j]) {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
dis->set_query(
|
|
235
|
+
reinterpret_cast<const float*>(rows.data() + j * cs));
|
|
236
|
+
nearer[j] = (*dis)(exact[j]) < (*dis)(found[j]);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
} // namespace
|
|
243
|
+
|
|
244
|
+
HNSWLevel0LinkStats IndexBinaryHNSW::add_level_0_links_from_sample(
|
|
245
|
+
idx_t n,
|
|
246
|
+
const uint8_t* x,
|
|
247
|
+
const HNSWLevel0LinkParameters& params) {
|
|
248
|
+
const BinaryLinkSample sample(*this, n, x);
|
|
249
|
+
std::unique_ptr<DistanceComputer> dis(get_distance_computer());
|
|
250
|
+
return hnsw_add_level_0_links_from_sample(
|
|
251
|
+
hnsw, ntotal, *dis, false, sample, params);
|
|
252
|
+
}
|
|
253
|
+
|
|
176
254
|
/**************************************************************
|
|
177
255
|
* IndexBinaryHNSWCagra implementation
|
|
178
256
|
**************************************************************/
|
|
@@ -269,10 +347,10 @@ void IndexBinaryHNSWCagra::search(
|
|
|
269
347
|
params);
|
|
270
348
|
|
|
271
349
|
res.end();
|
|
350
|
+
vt->advance();
|
|
272
351
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
hnsw_stats.combine(search_stats);
|
|
352
|
+
if (get_search_stats_enabled()) {
|
|
353
|
+
hnsw_stats.combine_atomic(search_stats);
|
|
276
354
|
}
|
|
277
355
|
}
|
|
278
356
|
|
|
@@ -40,6 +40,14 @@ struct IndexBinaryHNSW : IndexBinary {
|
|
|
40
40
|
// used when GpuIndexBinaryCagra::copyFrom(IndexBinaryHNSW*) is called.
|
|
41
41
|
bool keep_max_size_level0 = false;
|
|
42
42
|
|
|
43
|
+
// When this index is the coarse quantizer of an IndexBinaryIVF,
|
|
44
|
+
// IndexBinaryIVF::train() calls add_level_0_links_from_sample() after it
|
|
45
|
+
// adds the centroids. The sample is the first
|
|
46
|
+
// min(n, level_0_link_samples_per_node * ntotal) training vectors. 0
|
|
47
|
+
// disables the call. Training does not call it when the quantizer is
|
|
48
|
+
// already trained. The index format does not store this value.
|
|
49
|
+
int level_0_link_samples_per_node = 3;
|
|
50
|
+
|
|
43
51
|
explicit IndexBinaryHNSW();
|
|
44
52
|
explicit IndexBinaryHNSW(int d, int M = 32);
|
|
45
53
|
explicit IndexBinaryHNSW(IndexBinary* storage, int M = 32);
|
|
@@ -65,6 +73,17 @@ struct IndexBinaryHNSW : IndexBinary {
|
|
|
65
73
|
void reconstruct(idx_t key, uint8_t* recons) const override;
|
|
66
74
|
|
|
67
75
|
void reset() override;
|
|
76
|
+
|
|
77
|
+
/** Adds level-0 links so that the search no longer stops at "sinks":
|
|
78
|
+
* nodes where it stops for many vectors whose nearest node is elsewhere.
|
|
79
|
+
* See IndexHNSW::add_level_0_links_from_sample(). x holds n binary
|
|
80
|
+
* vectors. Call this function after the last add().
|
|
81
|
+
*/
|
|
82
|
+
HNSWLevel0LinkStats add_level_0_links_from_sample(
|
|
83
|
+
idx_t n,
|
|
84
|
+
const uint8_t* x,
|
|
85
|
+
const HNSWLevel0LinkParameters& params =
|
|
86
|
+
HNSWLevel0LinkParameters());
|
|
68
87
|
};
|
|
69
88
|
|
|
70
89
|
struct IndexBinaryHNSWCagra : IndexBinaryHNSW {
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
#include <limits>
|
|
18
18
|
#include <memory>
|
|
19
19
|
|
|
20
|
+
#include <faiss/IndexBinaryHNSW.h>
|
|
20
21
|
#include <faiss/IndexFlat.h>
|
|
21
22
|
#include <faiss/IndexLSH.h>
|
|
22
23
|
#include <faiss/impl/AuxIndexStructures.h>
|
|
@@ -254,6 +255,21 @@ void IndexBinaryIVF::reconstruct_from_offset(
|
|
|
254
255
|
idx_t list_no,
|
|
255
256
|
idx_t offset,
|
|
256
257
|
uint8_t* recons) const {
|
|
258
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
259
|
+
list_no >= 0 &&
|
|
260
|
+
static_cast<uint64_t>(list_no) <
|
|
261
|
+
static_cast<uint64_t>(nlist),
|
|
262
|
+
"Invalid list_no %" PRId64 " (nlist=%zd)",
|
|
263
|
+
list_no,
|
|
264
|
+
nlist);
|
|
265
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
266
|
+
offset >= 0 &&
|
|
267
|
+
static_cast<uint64_t>(offset) <
|
|
268
|
+
static_cast<uint64_t>(invlists->list_size(list_no)),
|
|
269
|
+
"Invalid offset %" PRId64 " for list %" PRId64 " (size=%zd)",
|
|
270
|
+
offset,
|
|
271
|
+
list_no,
|
|
272
|
+
invlists->list_size(list_no));
|
|
257
273
|
memcpy(recons,
|
|
258
274
|
InvertedLists::ScopedCodes(invlists, list_no, offset).get(),
|
|
259
275
|
code_size);
|
|
@@ -308,6 +324,24 @@ void IndexBinaryIVF::train(idx_t n, const uint8_t* x) {
|
|
|
308
324
|
|
|
309
325
|
quantizer->add(clus.k, x_b.get());
|
|
310
326
|
quantizer->is_trained = true;
|
|
327
|
+
|
|
328
|
+
auto* hnsw = dynamic_cast<IndexBinaryHNSW*>(quantizer);
|
|
329
|
+
if (hnsw && hnsw->level_0_link_samples_per_node > 0) {
|
|
330
|
+
const idx_t samples = std::min<idx_t>(
|
|
331
|
+
n, idx_t(hnsw->level_0_link_samples_per_node) * nlist);
|
|
332
|
+
const HNSWLevel0LinkStats stats =
|
|
333
|
+
hnsw->add_level_0_links_from_sample(samples, x);
|
|
334
|
+
if (verbose) {
|
|
335
|
+
printf("HNSW quantizer level-0 links from %" PRId64
|
|
336
|
+
" samples: %zd sinks found, %zd remaining, %zd links "
|
|
337
|
+
"added, %zd replaced\n",
|
|
338
|
+
samples,
|
|
339
|
+
stats.n_sinks_found,
|
|
340
|
+
stats.n_sinks_remaining,
|
|
341
|
+
stats.n_links_added,
|
|
342
|
+
stats.n_links_replaced);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
311
345
|
}
|
|
312
346
|
|
|
313
347
|
is_trained = true;
|
|
@@ -55,7 +55,7 @@ IndexFastScan::IndexFastScan()
|
|
|
55
55
|
|
|
56
56
|
void IndexFastScan::reset() {
|
|
57
57
|
codes.resize(0);
|
|
58
|
-
ntotal = 0;
|
|
58
|
+
ntotal = ntotal2 = 0;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
void IndexFastScan::add(idx_t n, const float* x) {
|
|
@@ -267,15 +267,16 @@ void IndexFastScan::search(
|
|
|
267
267
|
float* distances,
|
|
268
268
|
idx_t* labels,
|
|
269
269
|
const SearchParameters* params) const {
|
|
270
|
-
FAISS_THROW_IF_MSG(params, "search params not supported for this index");
|
|
271
270
|
FAISS_THROW_IF_NOT(k > 0);
|
|
271
|
+
const IDSelector* sel = params ? params->sel : nullptr;
|
|
272
272
|
|
|
273
273
|
FastScanDistancePostProcessing empty_context{};
|
|
274
274
|
if (metric_type == METRIC_L2) {
|
|
275
|
-
search_dispatch_implem<true>(
|
|
275
|
+
search_dispatch_implem<true>(
|
|
276
|
+
n, x, k, distances, labels, empty_context, sel);
|
|
276
277
|
} else {
|
|
277
278
|
search_dispatch_implem<false>(
|
|
278
|
-
n, x, k, distances, labels, empty_context);
|
|
279
|
+
n, x, k, distances, labels, empty_context, sel);
|
|
279
280
|
}
|
|
280
281
|
}
|
|
281
282
|
|
|
@@ -286,7 +287,8 @@ void IndexFastScan::search_dispatch_implem(
|
|
|
286
287
|
idx_t k,
|
|
287
288
|
float* distances,
|
|
288
289
|
idx_t* labels,
|
|
289
|
-
const FastScanDistancePostProcessing& context
|
|
290
|
+
const FastScanDistancePostProcessing& context,
|
|
291
|
+
const IDSelector* sel) const {
|
|
290
292
|
using Cfloat = typename std::conditional<
|
|
291
293
|
is_max,
|
|
292
294
|
CMax<float, int64_t>,
|
|
@@ -317,6 +319,10 @@ void IndexFastScan::search_dispatch_implem(
|
|
|
317
319
|
FAISS_THROW_MSG("not implemented");
|
|
318
320
|
} else if (implem == 2 || implem == 3 || implem == 4) {
|
|
319
321
|
FAISS_THROW_IF_NOT(orig_codes);
|
|
322
|
+
FAISS_THROW_IF_MSG(
|
|
323
|
+
sel,
|
|
324
|
+
"IDSelector is not supported by implem 2/3/4; leave implem at "
|
|
325
|
+
"0 so a selector-aware kernel is chosen");
|
|
320
326
|
search_implem_234<Cfloat>(n, x, k, distances, labels, context);
|
|
321
327
|
} else if (impl >= 12 && impl <= 15) {
|
|
322
328
|
FAISS_THROW_IF_NOT(ntotal < INT_MAX);
|
|
@@ -328,9 +334,11 @@ void IndexFastScan::search_dispatch_implem(
|
|
|
328
334
|
// - OpenMP disabled (omp_get_max_threads() = 1)
|
|
329
335
|
if (nt < 2) {
|
|
330
336
|
if (impl == 12 || impl == 13) {
|
|
331
|
-
search_implem_12<C>(
|
|
337
|
+
search_implem_12<C>(
|
|
338
|
+
n, x, k, distances, labels, impl, context, sel);
|
|
332
339
|
} else {
|
|
333
|
-
search_implem_14<C>(
|
|
340
|
+
search_implem_14<C>(
|
|
341
|
+
n, x, k, distances, labels, impl, context, sel);
|
|
334
342
|
}
|
|
335
343
|
} else {
|
|
336
344
|
// explicitly slice over threads
|
|
@@ -355,7 +363,8 @@ void IndexFastScan::search_dispatch_implem(
|
|
|
355
363
|
dis_i,
|
|
356
364
|
lab_i,
|
|
357
365
|
impl,
|
|
358
|
-
thread_context
|
|
366
|
+
thread_context,
|
|
367
|
+
sel);
|
|
359
368
|
} else {
|
|
360
369
|
search_implem_14<C>(
|
|
361
370
|
i1 - i0,
|
|
@@ -364,7 +373,8 @@ void IndexFastScan::search_dispatch_implem(
|
|
|
364
373
|
dis_i,
|
|
365
374
|
lab_i,
|
|
366
375
|
impl,
|
|
367
|
-
thread_context
|
|
376
|
+
thread_context,
|
|
377
|
+
sel);
|
|
368
378
|
}
|
|
369
379
|
}
|
|
370
380
|
}
|
|
@@ -440,7 +450,8 @@ void IndexFastScan::search_implem_12(
|
|
|
440
450
|
float* distances,
|
|
441
451
|
idx_t* labels,
|
|
442
452
|
int impl,
|
|
443
|
-
const FastScanDistancePostProcessing& context
|
|
453
|
+
const FastScanDistancePostProcessing& context,
|
|
454
|
+
const IDSelector* sel) const {
|
|
444
455
|
FAISS_THROW_IF_NOT(bbs == 32);
|
|
445
456
|
|
|
446
457
|
// handle qbs2 blocking by recursive call
|
|
@@ -460,7 +471,8 @@ void IndexFastScan::search_implem_12(
|
|
|
460
471
|
distances + i0 * k,
|
|
461
472
|
labels + i0 * k,
|
|
462
473
|
impl,
|
|
463
|
-
sub_context
|
|
474
|
+
sub_context,
|
|
475
|
+
sel);
|
|
464
476
|
}
|
|
465
477
|
return;
|
|
466
478
|
}
|
|
@@ -492,7 +504,7 @@ void IndexFastScan::search_implem_12(
|
|
|
492
504
|
FAISS_THROW_IF_NOT(LUT_nq == n);
|
|
493
505
|
|
|
494
506
|
auto scanner = make_knn_scanner(
|
|
495
|
-
C::is_max, n, k, ntotal, distances, labels,
|
|
507
|
+
C::is_max, n, k, ntotal, distances, labels, sel, impl, context);
|
|
496
508
|
auto* rh = scanner->handler();
|
|
497
509
|
rh->normalizers = normalizers.get();
|
|
498
510
|
// Note: skip & 2 previously set handler->disable (run kernel,
|
|
@@ -525,7 +537,8 @@ void IndexFastScan::search_implem_14(
|
|
|
525
537
|
float* distances,
|
|
526
538
|
idx_t* labels,
|
|
527
539
|
int impl,
|
|
528
|
-
const FastScanDistancePostProcessing& context
|
|
540
|
+
const FastScanDistancePostProcessing& context,
|
|
541
|
+
const IDSelector* sel) const {
|
|
529
542
|
FAISS_THROW_IF_NOT(bbs % 32 == 0);
|
|
530
543
|
|
|
531
544
|
// The accumulate loop dispatch table only instantiates certain
|
|
@@ -553,7 +566,8 @@ void IndexFastScan::search_implem_14(
|
|
|
553
566
|
distances + i0 * k,
|
|
554
567
|
labels + i0 * k,
|
|
555
568
|
impl,
|
|
556
|
-
sub_context
|
|
569
|
+
sub_context,
|
|
570
|
+
sel);
|
|
557
571
|
}
|
|
558
572
|
return;
|
|
559
573
|
}
|
|
@@ -577,7 +591,7 @@ void IndexFastScan::search_implem_14(
|
|
|
577
591
|
LUT.get());
|
|
578
592
|
|
|
579
593
|
auto scanner = make_knn_scanner(
|
|
580
|
-
C::is_max, n, k, ntotal, distances, labels,
|
|
594
|
+
C::is_max, n, k, ntotal, distances, labels, sel, impl, context);
|
|
581
595
|
auto* rh = scanner->handler();
|
|
582
596
|
rh->normalizers = normalizers.get();
|
|
583
597
|
// Note: skip & 2 previously set handler->disable (run kernel,
|
|
@@ -606,7 +620,8 @@ template void IndexFastScan::search_dispatch_implem<true>(
|
|
|
606
620
|
idx_t k,
|
|
607
621
|
float* distances,
|
|
608
622
|
idx_t* labels,
|
|
609
|
-
const FastScanDistancePostProcessing& context
|
|
623
|
+
const FastScanDistancePostProcessing& context,
|
|
624
|
+
const IDSelector* sel) const;
|
|
610
625
|
|
|
611
626
|
template void IndexFastScan::search_dispatch_implem<false>(
|
|
612
627
|
idx_t n,
|
|
@@ -614,7 +629,8 @@ template void IndexFastScan::search_dispatch_implem<false>(
|
|
|
614
629
|
idx_t k,
|
|
615
630
|
float* distances,
|
|
616
631
|
idx_t* labels,
|
|
617
|
-
const FastScanDistancePostProcessing& context
|
|
632
|
+
const FastScanDistancePostProcessing& context,
|
|
633
|
+
const IDSelector* sel) const;
|
|
618
634
|
|
|
619
635
|
void IndexFastScan::reconstruct(idx_t key, float* recons) const {
|
|
620
636
|
FAISS_THROW_IF_NOT_FMT(
|