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
|
@@ -0,0 +1,129 @@
|
|
|
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 <vector>
|
|
11
|
+
|
|
12
|
+
#include <faiss/IndexFastScan.h>
|
|
13
|
+
#include <faiss/IndexFlatCodes.h>
|
|
14
|
+
#include <faiss/IndexScalarQuantizer.h>
|
|
15
|
+
#include <faiss/impl/ScalarQuantizer.h>
|
|
16
|
+
|
|
17
|
+
namespace faiss {
|
|
18
|
+
|
|
19
|
+
/** Fast scan version of IndexScalarQuantizer.
|
|
20
|
+
*
|
|
21
|
+
* Supported quantizer types:
|
|
22
|
+
* - QT_4bit, QT_4bit_uniform: native 4-bit codes mapped onto the
|
|
23
|
+
* PQ4 FastScan SIMD (vpshufb / equivalent).
|
|
24
|
+
*
|
|
25
|
+
* - QT_6bit, QT_8bit, QT_8bit_uniform, QT_8bit_direct,
|
|
26
|
+
* QT_8bit_direct_signed: re-quantised to 4-bit for the scan, reranked
|
|
27
|
+
* against the originals in orig_codes.
|
|
28
|
+
*
|
|
29
|
+
* - All other types (QT_fp16, QT_bf16): use IndexScalarQuantizer directly.
|
|
30
|
+
*/
|
|
31
|
+
struct IndexSQFastScan : IndexFastScan {
|
|
32
|
+
ScalarQuantizer sq;
|
|
33
|
+
|
|
34
|
+
/// Overselection ratio for reranking.
|
|
35
|
+
float rerank_factor = 2;
|
|
36
|
+
|
|
37
|
+
/// Low nibbles of the 8-bit codes, two dimensions per byte, indexed by
|
|
38
|
+
/// id. The high nibbles live in the packed scan codes. Empty for the
|
|
39
|
+
/// native 4-bit types, which need no rerank.
|
|
40
|
+
std::vector<uint8_t> lo_codes;
|
|
41
|
+
|
|
42
|
+
/** Constructor.
|
|
43
|
+
*
|
|
44
|
+
* @param d dimensionality of input vectors
|
|
45
|
+
* @param qtype any native 4-bit or reranked type (see above)
|
|
46
|
+
* @param metric distance metric (METRIC_L2 or METRIC_INNER_PRODUCT)
|
|
47
|
+
* @param bbs block size for SIMD processing (multiple of 32)
|
|
48
|
+
*/
|
|
49
|
+
IndexSQFastScan(
|
|
50
|
+
int d,
|
|
51
|
+
ScalarQuantizer::QuantizerType qtype,
|
|
52
|
+
MetricType metric = METRIC_L2,
|
|
53
|
+
int bbs = 32);
|
|
54
|
+
|
|
55
|
+
IndexSQFastScan();
|
|
56
|
+
|
|
57
|
+
/// Build from an existing IndexScalarQuantizer
|
|
58
|
+
explicit IndexSQFastScan(const IndexScalarQuantizer& orig, int bbs = 32);
|
|
59
|
+
|
|
60
|
+
void train(idx_t n, const float* x) override;
|
|
61
|
+
|
|
62
|
+
void add(idx_t n, const float* x) override;
|
|
63
|
+
|
|
64
|
+
void reset() override;
|
|
65
|
+
|
|
66
|
+
void search(
|
|
67
|
+
idx_t n,
|
|
68
|
+
const float* x,
|
|
69
|
+
idx_t k,
|
|
70
|
+
float* distances,
|
|
71
|
+
idx_t* labels,
|
|
72
|
+
const SearchParameters* params = nullptr) const override;
|
|
73
|
+
|
|
74
|
+
void compute_codes(uint8_t* codes, idx_t n, const float* x) const override;
|
|
75
|
+
|
|
76
|
+
void check_compatible_for_merge(const Index& otherIndex) const override;
|
|
77
|
+
|
|
78
|
+
void compute_float_LUT(
|
|
79
|
+
float* lut,
|
|
80
|
+
idx_t n,
|
|
81
|
+
const float* x,
|
|
82
|
+
const FastScanDistancePostProcessing& context) const override;
|
|
83
|
+
|
|
84
|
+
void sa_decode(idx_t n, const uint8_t* bytes, float* x) const override;
|
|
85
|
+
|
|
86
|
+
void sa_encode(idx_t n, const float* x, uint8_t* bytes) const override;
|
|
87
|
+
|
|
88
|
+
void reconstruct(idx_t key, float* recons) const override;
|
|
89
|
+
|
|
90
|
+
void reconstruct_n(idx_t i0, idx_t ni, float* recons) const override;
|
|
91
|
+
|
|
92
|
+
void add_sa_codes(idx_t n, const uint8_t* codes, const idx_t* xids)
|
|
93
|
+
override;
|
|
94
|
+
|
|
95
|
+
void permute_entries(const idx_t* perm);
|
|
96
|
+
|
|
97
|
+
FlatCodesDistanceComputer* get_FlatCodesDistanceComputer() const;
|
|
98
|
+
|
|
99
|
+
DistanceComputer* get_distance_computer() const override;
|
|
100
|
+
|
|
101
|
+
void range_search(
|
|
102
|
+
idx_t n,
|
|
103
|
+
const float* x,
|
|
104
|
+
float radius,
|
|
105
|
+
RangeSearchResult* result,
|
|
106
|
+
const SearchParameters* params = nullptr) const override;
|
|
107
|
+
|
|
108
|
+
size_t remove_ids(const IDSelector& sel) override;
|
|
109
|
+
|
|
110
|
+
void merge_from(Index& otherIndex, idx_t add_id = 0) override;
|
|
111
|
+
|
|
112
|
+
void search1(
|
|
113
|
+
const float* x,
|
|
114
|
+
ResultHandler& handler,
|
|
115
|
+
SearchParameters* params = nullptr) const override;
|
|
116
|
+
|
|
117
|
+
size_t sa_code_size() const override;
|
|
118
|
+
|
|
119
|
+
void fill_sa_code(
|
|
120
|
+
const CodePacker& packer,
|
|
121
|
+
idx_t id,
|
|
122
|
+
uint8_t* scratch,
|
|
123
|
+
int* values,
|
|
124
|
+
uint8_t* code_out) const;
|
|
125
|
+
|
|
126
|
+
size_t fast_scan_code_size() const override;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
} // namespace faiss
|
|
@@ -193,6 +193,16 @@ void IndexShardsTemplate<IndexT>::add_with_ids(
|
|
|
193
193
|
syncWithSubIndexes();
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
template <typename IndexT>
|
|
197
|
+
size_t IndexShardsTemplate<IndexT>::remove_ids(const IDSelector& sel) {
|
|
198
|
+
FAISS_THROW_IF_MSG(
|
|
199
|
+
successive_ids, "remove_ids needs successive_ids = false");
|
|
200
|
+
const idx_t before = this->ntotal;
|
|
201
|
+
this->runOnIndex([&sel](int, IndexT* index) { index->remove_ids(sel); });
|
|
202
|
+
syncWithSubIndexes();
|
|
203
|
+
return before - this->ntotal;
|
|
204
|
+
}
|
|
205
|
+
|
|
196
206
|
template <typename IndexT>
|
|
197
207
|
void IndexShardsTemplate<IndexT>::search(
|
|
198
208
|
idx_t n,
|
|
@@ -91,6 +91,11 @@ struct IndexShardsTemplate : public ThreadedIndex<IndexT> {
|
|
|
91
91
|
|
|
92
92
|
void train(idx_t n, const component_t* x) override;
|
|
93
93
|
|
|
94
|
+
/// Removes the ids from every shard, and returns the sum of the counts.
|
|
95
|
+
/// Needs successive_ids = false: with successive ids, the ids of a shard
|
|
96
|
+
/// depend on the sizes of the shards before it.
|
|
97
|
+
size_t remove_ids(const IDSelector& sel) override;
|
|
98
|
+
|
|
94
99
|
bool successive_ids;
|
|
95
100
|
|
|
96
101
|
/// Synchronize the top-level index (IndexShards) with data in the
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
#include <faiss/impl/ClusteringHelpers.h>
|
|
23
23
|
#include <faiss/impl/FaissAssert.h>
|
|
24
24
|
#include <faiss/impl/PdxLayout.h>
|
|
25
|
+
#include <faiss/impl/platform_macros.h>
|
|
25
26
|
#include <faiss/impl/simd_dispatch.h>
|
|
26
27
|
#include <faiss/utils/distances.h>
|
|
27
28
|
#include <faiss/utils/random.h>
|
|
@@ -266,9 +267,9 @@ float adapt_d_prime(
|
|
|
266
267
|
}
|
|
267
268
|
|
|
268
269
|
/// Pre-loop setup: subsample, rotate, Forgy init, build ADSampling table,
|
|
269
|
-
/// size the label scratch.
|
|
270
|
-
///
|
|
271
|
-
|
|
270
|
+
/// and size the label scratch. The subsampled input only needs to remain alive
|
|
271
|
+
/// through the rotation and is released before the iteration loop starts.
|
|
272
|
+
void setup_train_state(
|
|
272
273
|
TrainState& state,
|
|
273
274
|
std::vector<int64_t>& labels64,
|
|
274
275
|
std::vector<float>& hassign,
|
|
@@ -276,10 +277,13 @@ std::unique_ptr<uint8_t[]> setup_train_state(
|
|
|
276
277
|
int d,
|
|
277
278
|
int k,
|
|
278
279
|
idx_t n,
|
|
279
|
-
const
|
|
280
|
-
|
|
280
|
+
const void* x,
|
|
281
|
+
NumericType numeric_type) {
|
|
282
|
+
const bool fp16 = numeric_type == NumericType::Float16;
|
|
283
|
+
const size_t line_size =
|
|
284
|
+
(fp16 ? sizeof(uint16_t) : sizeof(float)) * static_cast<size_t>(d);
|
|
281
285
|
idx_t nx = n;
|
|
282
|
-
const uint8_t* x_bytes =
|
|
286
|
+
const uint8_t* x_bytes = static_cast<const uint8_t*>(x);
|
|
283
287
|
std::unique_ptr<uint8_t[]> sampled_x_owner;
|
|
284
288
|
if (static_cast<size_t>(nx) >
|
|
285
289
|
static_cast<size_t>(k) * cp.max_points_per_centroid) {
|
|
@@ -298,7 +302,6 @@ std::unique_ptr<uint8_t[]> setup_train_state(
|
|
|
298
302
|
sampled_x_owner.reset(x_new);
|
|
299
303
|
x_bytes = x_new;
|
|
300
304
|
}
|
|
301
|
-
const float* x_sampled = reinterpret_cast<const float*>(x_bytes);
|
|
302
305
|
|
|
303
306
|
FAISS_THROW_IF_NOT_MSG(
|
|
304
307
|
nx <= static_cast<idx_t>(std::numeric_limits<int>::max()),
|
|
@@ -315,7 +318,28 @@ std::unique_ptr<uint8_t[]> setup_train_state(
|
|
|
315
318
|
}
|
|
316
319
|
|
|
317
320
|
state.X_tilde.resize(static_cast<size_t>(state.n) * d);
|
|
318
|
-
|
|
321
|
+
if (!fp16) {
|
|
322
|
+
state.R->apply_noalloc(
|
|
323
|
+
state.n,
|
|
324
|
+
reinterpret_cast<const float*>(x_bytes),
|
|
325
|
+
state.X_tilde.data());
|
|
326
|
+
} else {
|
|
327
|
+
const size_t block_size =
|
|
328
|
+
std::min(static_cast<size_t>(state.n), cp.decode_block_size);
|
|
329
|
+
std::vector<float> decoded(block_size * d);
|
|
330
|
+
const uint16_t* x16 = reinterpret_cast<const uint16_t*>(x_bytes);
|
|
331
|
+
for (size_t i0 = 0; i0 < static_cast<size_t>(state.n);
|
|
332
|
+
i0 += block_size) {
|
|
333
|
+
const size_t i1 =
|
|
334
|
+
std::min(static_cast<size_t>(state.n), i0 + block_size);
|
|
335
|
+
fp16_to_fp32((i1 - i0) * d, x16 + i0 * d, decoded.data());
|
|
336
|
+
state.R->apply_noalloc(
|
|
337
|
+
static_cast<idx_t>(i1 - i0),
|
|
338
|
+
decoded.data(),
|
|
339
|
+
state.X_tilde.data() + i0 * d);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
sampled_x_owner.reset();
|
|
319
343
|
|
|
320
344
|
// Forgy init: pick k random rows from the rotated pool as initial
|
|
321
345
|
// centroids. These remain in rotated space; un-rotation happens
|
|
@@ -351,8 +375,6 @@ std::unique_ptr<uint8_t[]> setup_train_state(
|
|
|
351
375
|
hassign.assign(k, 0.0f);
|
|
352
376
|
|
|
353
377
|
labels64.resize(state.n);
|
|
354
|
-
|
|
355
|
-
return sampled_x_owner;
|
|
356
378
|
}
|
|
357
379
|
|
|
358
380
|
/// Un-rotate centroids into output buffer. R orthogonal, so
|
|
@@ -411,15 +433,36 @@ SuperKMeans::SuperKMeans(int d, int k, const SuperKMeansParameters& cp_in)
|
|
|
411
433
|
}
|
|
412
434
|
|
|
413
435
|
void SuperKMeans::train(idx_t n, const float* x) {
|
|
436
|
+
train_ex(n, x, NumericType::Float32);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
void SuperKMeans::train_ex(idx_t n, const void* x, NumericType numeric_type) {
|
|
440
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
441
|
+
numeric_type == NumericType::Float32 ||
|
|
442
|
+
numeric_type == NumericType::Float16,
|
|
443
|
+
"SuperKMeans::train_ex: unsupported numeric type");
|
|
414
444
|
FAISS_THROW_IF_NOT_MSG(n > 0, "SuperKMeans: n must be positive");
|
|
415
445
|
FAISS_THROW_IF_MSG(x == nullptr, "SuperKMeans: x must not be null");
|
|
416
446
|
FAISS_THROW_IF_NOT_MSG(
|
|
417
447
|
n >= static_cast<idx_t>(k), "SuperKMeans: n must be >= k");
|
|
448
|
+
const bool fp16 = numeric_type == NumericType::Float16;
|
|
449
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
450
|
+
!fp16 || cp.decode_block_size > 0,
|
|
451
|
+
"SuperKMeans: decode_block_size must be positive");
|
|
418
452
|
if (cp.check_input_data_for_NaNs) {
|
|
419
|
-
|
|
453
|
+
const size_t num_values = static_cast<size_t>(n) * d;
|
|
454
|
+
if (fp16) {
|
|
420
455
|
FAISS_THROW_IF_NOT_MSG(
|
|
421
|
-
|
|
456
|
+
detail::fp16_all_finite(
|
|
457
|
+
num_values, static_cast<const uint16_t*>(x)),
|
|
422
458
|
"SuperKMeans: input contains NaN's or Inf's");
|
|
459
|
+
} else {
|
|
460
|
+
const float* x32 = static_cast<const float*>(x);
|
|
461
|
+
for (size_t i = 0; i < num_values; i++) {
|
|
462
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
463
|
+
std::isfinite(x32[i]),
|
|
464
|
+
"SuperKMeans: input contains NaN's or Inf's");
|
|
465
|
+
}
|
|
423
466
|
}
|
|
424
467
|
}
|
|
425
468
|
if (cp.verbose && n < static_cast<idx_t>(k) * cp.min_points_per_centroid) {
|
|
@@ -435,8 +478,7 @@ void SuperKMeans::train(idx_t n, const float* x) {
|
|
|
435
478
|
std::vector<int64_t> labels64;
|
|
436
479
|
SuperKMeansAssignScratch assign_scratch;
|
|
437
480
|
std::vector<float> hassign;
|
|
438
|
-
|
|
439
|
-
setup_train_state(state, labels64, hassign, cp, d, k, n, x);
|
|
481
|
+
setup_train_state(state, labels64, hassign, cp, d, k, n, x, numeric_type);
|
|
440
482
|
|
|
441
483
|
iteration_stats.clear();
|
|
442
484
|
iteration_stats.reserve(cp.niter);
|
|
@@ -625,7 +667,7 @@ void super_kmeans_assign_iteration(
|
|
|
625
667
|
[[maybe_unused]] const int omp_chunk_local = cp.omp_chunk;
|
|
626
668
|
int64_t tile_total = 0;
|
|
627
669
|
int64_t tile_pruned = 0;
|
|
628
|
-
#pragma omp parallel for schedule(
|
|
670
|
+
#pragma omp parallel for schedule(FAISS_OMP_DYNAMIC, omp_chunk_local) \
|
|
629
671
|
reduction(+ : tile_total) reduction(+ : tile_pruned)
|
|
630
672
|
for (int i = 0; i < bx; ++i) {
|
|
631
673
|
const float xnp_i = x_norms_partial[xi + i];
|
|
@@ -89,11 +89,16 @@ struct SuperKMeans {
|
|
|
89
89
|
|
|
90
90
|
SuperKMeans(int d, int k, const SuperKMeansParameters& cp = {});
|
|
91
91
|
|
|
92
|
-
/// Train on `n` row-major vectors of dimension `d`.
|
|
93
|
-
/// ClusteringParameters fields (niter, seed, verbose,
|
|
94
|
-
/// max_points_per_centroid, use_faster_subsampling,
|
|
95
|
-
/// check_input_data_for_NaNs).
|
|
92
|
+
/// Train on `n` row-major fp32 vectors of dimension `d`.
|
|
96
93
|
void train(idx_t n, const float* x);
|
|
94
|
+
|
|
95
|
+
/** Train on vectors of the given numeric type.
|
|
96
|
+
*
|
|
97
|
+
* Float32 is the same as train(). Float16 takes packed IEEE binary16
|
|
98
|
+
* vectors and widens bounded blocks while rotating them into the fp32
|
|
99
|
+
* training workspace. Centroids and all iteration state remain fp32.
|
|
100
|
+
*/
|
|
101
|
+
void train_ex(idx_t n, const void* x, NumericType numeric_type);
|
|
97
102
|
};
|
|
98
103
|
|
|
99
104
|
/// Reusable scratch for super_kmeans_assign_iteration; pass one instance across
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
#include <faiss/IndexPQ.h>
|
|
19
19
|
#include <faiss/impl/FaissAssert.h>
|
|
20
|
+
#include <faiss/impl/platform_macros.h>
|
|
20
21
|
#include <faiss/utils/distances.h>
|
|
21
22
|
#include <faiss/utils/random.h>
|
|
22
23
|
#include <faiss/utils/utils.h>
|
|
@@ -481,7 +482,7 @@ void HadamardRotation::apply_noalloc(idx_t n, const float* x, float* xt) const {
|
|
|
481
482
|
// Three rounds scale by p^(3/2). Normalize once at the end.
|
|
482
483
|
float total_scale = 1.0f / (p * std::sqrt(static_cast<float>(p)));
|
|
483
484
|
|
|
484
|
-
#pragma omp parallel for schedule(
|
|
485
|
+
#pragma omp parallel for schedule(FAISS_OMP_DYNAMIC)
|
|
485
486
|
for (idx_t i = 0; i < n; i++) {
|
|
486
487
|
const float* xi = x + i * d;
|
|
487
488
|
float* xo = xt + i * p;
|
|
@@ -526,7 +527,7 @@ void HadamardRotation::reverse_transform(idx_t n, const float* xt, float* x)
|
|
|
526
527
|
// total_scale = 1/(p*sqrt(p)), so the inverse applies the same factor.
|
|
527
528
|
const float inverse_scale = 1.0f / (p * std::sqrt(static_cast<float>(p)));
|
|
528
529
|
|
|
529
|
-
#pragma omp parallel for schedule(
|
|
530
|
+
#pragma omp parallel for schedule(FAISS_OMP_DYNAMIC)
|
|
530
531
|
for (idx_t i = 0; i < n; i++) {
|
|
531
532
|
const float* xi = xt + i * p;
|
|
532
533
|
float* xo = x + i * p;
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
#include <faiss/clone_index.h>
|
|
11
11
|
|
|
12
|
+
#include <memory>
|
|
13
|
+
|
|
12
14
|
#include <faiss/impl/FaissAssert.h>
|
|
13
15
|
|
|
14
16
|
#include <faiss/Index2Layer.h>
|
|
@@ -37,6 +39,7 @@
|
|
|
37
39
|
#include <faiss/IndexNSG.h>
|
|
38
40
|
#include <faiss/IndexPQ.h>
|
|
39
41
|
#include <faiss/IndexPQFastScan.h>
|
|
42
|
+
#include <faiss/IndexPiPNN.h>
|
|
40
43
|
#include <faiss/IndexPreTransform.h>
|
|
41
44
|
#include <faiss/IndexRaBitQ.h>
|
|
42
45
|
#include <faiss/IndexRefine.h>
|
|
@@ -170,6 +173,17 @@ IndexNSG* clone_IndexNSG(const IndexNSG* insg) {
|
|
|
170
173
|
}
|
|
171
174
|
}
|
|
172
175
|
|
|
176
|
+
static IndexPiPNN* clone_IndexPiPNN(const IndexPiPNN* ipipnn) {
|
|
177
|
+
TRYCLONE(IndexPiPNNFlat, ipipnn)
|
|
178
|
+
TRYCLONE(IndexPiPNNSQ, ipipnn) {
|
|
179
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
180
|
+
typeid(*ipipnn) == typeid(IndexPiPNN),
|
|
181
|
+
"clone not supported for this type of IndexPiPNN: %s",
|
|
182
|
+
typeid(*ipipnn).name());
|
|
183
|
+
return new IndexPiPNN(*ipipnn);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
173
187
|
IndexRowwiseMinMaxBase* clone_IndexRowwiseMinMax(
|
|
174
188
|
const IndexRowwiseMinMaxBase* irmmb) {
|
|
175
189
|
TRYCLONE(IndexRowwiseMinMaxFP16, irmmb)
|
|
@@ -356,6 +370,16 @@ Index* Cloner::clone_Index(const Index* index) {
|
|
|
356
370
|
res->own_fields = true;
|
|
357
371
|
res->storage = clone_Index(insg->storage);
|
|
358
372
|
return res;
|
|
373
|
+
} else if (
|
|
374
|
+
const IndexPiPNN* ipipnn = dynamic_cast<const IndexPiPNN*>(index)) {
|
|
375
|
+
// make sure we don't get a GPU index here
|
|
376
|
+
std::unique_ptr<Index> storage(
|
|
377
|
+
ipipnn->storage ? Cloner::clone_Index(ipipnn->storage)
|
|
378
|
+
: nullptr);
|
|
379
|
+
IndexPiPNN* res = clone_IndexPiPNN(ipipnn);
|
|
380
|
+
res->storage = storage.release();
|
|
381
|
+
res->own_fields = true;
|
|
382
|
+
return res;
|
|
359
383
|
} else if (
|
|
360
384
|
const IndexNNDescent* innd =
|
|
361
385
|
dynamic_cast<const IndexNNDescent*>(index)) {
|
|
@@ -0,0 +1,112 @@
|
|
|
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 <faiss/Index.h>
|
|
11
|
+
|
|
12
|
+
#include <memory>
|
|
13
|
+
|
|
14
|
+
namespace faiss {
|
|
15
|
+
namespace gpu {
|
|
16
|
+
class GpuResourcesProvider;
|
|
17
|
+
|
|
18
|
+
/** Caller-controlled dense vector storage for cuVS CAGRA.
|
|
19
|
+
*
|
|
20
|
+
* Dimensions and row strides are in elements, with contiguous columns. Binary
|
|
21
|
+
* vectors use UInt8, and their dimension is the number of bytes, not bits.
|
|
22
|
+
* Views never own or copy their allocation. An owning Dataset controls the
|
|
23
|
+
* allocation's lifetime; CAGRA always borrows it. Keep the backing allocation
|
|
24
|
+
* alive and unchanged until all indexes using it and queued GPU work finish.
|
|
25
|
+
* Moving an owning Dataset preserves its allocation and existing borrowed
|
|
26
|
+
* views.
|
|
27
|
+
*/
|
|
28
|
+
class Dataset {
|
|
29
|
+
public:
|
|
30
|
+
enum class Layout { Standard, Padded };
|
|
31
|
+
|
|
32
|
+
~Dataset();
|
|
33
|
+
Dataset(Dataset&&) noexcept;
|
|
34
|
+
Dataset& operator=(Dataset&&) noexcept;
|
|
35
|
+
Dataset(const Dataset&) = delete;
|
|
36
|
+
Dataset& operator=(const Dataset&) = delete;
|
|
37
|
+
|
|
38
|
+
/// Borrow host storage. rowStride must be at least dim.
|
|
39
|
+
static Dataset viewHost(
|
|
40
|
+
const void* data,
|
|
41
|
+
idx_t numRows,
|
|
42
|
+
int dim,
|
|
43
|
+
NumericType numericType,
|
|
44
|
+
idx_t rowStride);
|
|
45
|
+
|
|
46
|
+
/// Borrow storage accessible on device. A Standard view can also be
|
|
47
|
+
/// CAGRA-compatible when its physical stride and alignment satisfy padding.
|
|
48
|
+
/// When used by CAGRA, elements between dim and rowStride must be zero.
|
|
49
|
+
static Dataset viewDevice(
|
|
50
|
+
const void* data,
|
|
51
|
+
idx_t numRows,
|
|
52
|
+
int dim,
|
|
53
|
+
NumericType numericType,
|
|
54
|
+
idx_t rowStride,
|
|
55
|
+
int device);
|
|
56
|
+
|
|
57
|
+
/// Borrow CAGRA-compatible device storage without copying. The base address
|
|
58
|
+
/// must be 16-byte aligned and rowStride must equal dim rounded up to a
|
|
59
|
+
/// 16-byte row width. The caller must zero elements between dim and
|
|
60
|
+
/// rowStride, including for compatible Standard views used by CAGRA.
|
|
61
|
+
static Dataset viewDevicePadded(
|
|
62
|
+
const void* data,
|
|
63
|
+
idx_t numRows,
|
|
64
|
+
int dim,
|
|
65
|
+
NumericType numericType,
|
|
66
|
+
idx_t rowStride,
|
|
67
|
+
int device);
|
|
68
|
+
|
|
69
|
+
/// Create padded device storage using cuVS make_device_padded_dataset.
|
|
70
|
+
/// Device/managed input whose stride already matches the required padding
|
|
71
|
+
/// is rejected; use a view for that storage. Copies logical columns and
|
|
72
|
+
/// zeroes padding asynchronously on the resource's stream. Source data must
|
|
73
|
+
/// be ready on that stream and stay alive and unchanged until copying
|
|
74
|
+
/// finishes. Order subsequent use on that stream. Retains the resources
|
|
75
|
+
/// needed to release the allocation.
|
|
76
|
+
static Dataset makeDevicePadded(
|
|
77
|
+
GpuResourcesProvider* resources,
|
|
78
|
+
const Dataset& source,
|
|
79
|
+
int device);
|
|
80
|
+
|
|
81
|
+
const void* getData() const;
|
|
82
|
+
idx_t getNumRows() const;
|
|
83
|
+
int getDim() const;
|
|
84
|
+
idx_t getRowStride() const;
|
|
85
|
+
NumericType getNumericType() const;
|
|
86
|
+
int getDevice() const; // -1 for host storage
|
|
87
|
+
Layout getLayout() const;
|
|
88
|
+
bool isDevice() const;
|
|
89
|
+
bool ownsData() const;
|
|
90
|
+
|
|
91
|
+
/// Reports device residency, base alignment, and exact required row stride.
|
|
92
|
+
/// Does not inspect padding values; zero padding is a caller contract.
|
|
93
|
+
bool isCagraCompatible() const;
|
|
94
|
+
|
|
95
|
+
/// Create a non-owning view of the same storage by copying its metadata.
|
|
96
|
+
/// Does not retain ownership of the backing allocation.
|
|
97
|
+
Dataset view() const;
|
|
98
|
+
|
|
99
|
+
/// Copy logical columns into packed host storage. destination must have
|
|
100
|
+
/// numRows * dim * sizeof(element) bytes. Completes all device work using
|
|
101
|
+
/// the source device before copying and returns with the host data ready.
|
|
102
|
+
void copyToHost(void* destination) const;
|
|
103
|
+
|
|
104
|
+
private:
|
|
105
|
+
struct Impl;
|
|
106
|
+
explicit Dataset(std::unique_ptr<Impl> impl);
|
|
107
|
+
const Impl& getImpl() const;
|
|
108
|
+
std::unique_ptr<Impl> impl_;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
} // namespace gpu
|
|
112
|
+
} // namespace faiss
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
#include <faiss/IndexBinaryFlat.h>
|
|
16
16
|
#include <faiss/IndexFlat.h>
|
|
17
|
-
#if defined
|
|
17
|
+
#if defined USE_NVIDIA_CUVS
|
|
18
18
|
#include <faiss/IndexBinaryHNSW.h>
|
|
19
19
|
#include <faiss/IndexHNSW.h>
|
|
20
20
|
#endif
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
#include <faiss/MetaIndexes.h>
|
|
29
29
|
#include <faiss/gpu/GpuIndex.h>
|
|
30
30
|
#include <faiss/gpu/GpuIndexBinaryFlat.h>
|
|
31
|
-
#if defined
|
|
31
|
+
#if defined USE_NVIDIA_CUVS
|
|
32
32
|
#include <faiss/gpu/GpuIndexBinaryCagra.h>
|
|
33
33
|
#include <faiss/gpu/GpuIndexCagra.h>
|
|
34
34
|
#endif
|
|
@@ -92,7 +92,7 @@ Index* ToCPUCloner::clone_Index(const Index* index) {
|
|
|
92
92
|
// (inverse op of ToGpuClonerMultiple)
|
|
93
93
|
|
|
94
94
|
}
|
|
95
|
-
#if defined
|
|
95
|
+
#if defined USE_NVIDIA_CUVS
|
|
96
96
|
else if (auto icg = dynamic_cast<const GpuIndexCagra*>(index)) {
|
|
97
97
|
IndexHNSWCagra* res = new IndexHNSWCagra();
|
|
98
98
|
if (icg->get_numeric_type() != faiss::NumericType::Float32) {
|
|
@@ -171,6 +171,7 @@ Index* ToGpuCloner::clone_Index(const Index* index) {
|
|
|
171
171
|
config.flatConfig.useFloat16 = useFloat16CoarseQuantizer;
|
|
172
172
|
config.use_cuvs = use_cuvs;
|
|
173
173
|
config.allowCpuCoarseQuantizer = allowCpuCoarseQuantizer;
|
|
174
|
+
config.deterministic_tie_break = deterministic_tie_break;
|
|
174
175
|
|
|
175
176
|
GpuIndexIVFFlat* res = new GpuIndexIVFFlat(
|
|
176
177
|
provider, ifl->d, ifl->nlist, ifl->metric_type, config);
|
|
@@ -189,6 +190,7 @@ Index* ToGpuCloner::clone_Index(const Index* index) {
|
|
|
189
190
|
config.flatConfig.useFloat16 = useFloat16CoarseQuantizer;
|
|
190
191
|
config.use_cuvs = use_cuvs;
|
|
191
192
|
config.allowCpuCoarseQuantizer = allowCpuCoarseQuantizer;
|
|
193
|
+
config.deterministic_tie_break = deterministic_tie_break;
|
|
192
194
|
|
|
193
195
|
GpuIndexIVFScalarQuantizer* res = new GpuIndexIVFScalarQuantizer(
|
|
194
196
|
provider,
|
|
@@ -224,6 +226,7 @@ Index* ToGpuCloner::clone_Index(const Index* index) {
|
|
|
224
226
|
config.use_cuvs = use_cuvs;
|
|
225
227
|
config.interleavedLayout = use_cuvs;
|
|
226
228
|
config.allowCpuCoarseQuantizer = allowCpuCoarseQuantizer;
|
|
229
|
+
config.deterministic_tie_break = deterministic_tie_break;
|
|
227
230
|
|
|
228
231
|
GpuIndexIVFPQ* res = new GpuIndexIVFPQ(provider, ipq, config);
|
|
229
232
|
|
|
@@ -233,14 +236,14 @@ Index* ToGpuCloner::clone_Index(const Index* index) {
|
|
|
233
236
|
|
|
234
237
|
return res;
|
|
235
238
|
}
|
|
236
|
-
#if defined
|
|
239
|
+
#if defined USE_NVIDIA_CUVS
|
|
237
240
|
else if (auto icg = dynamic_cast<const faiss::IndexHNSWCagra*>(index)) {
|
|
238
241
|
GpuIndexCagraConfig config;
|
|
239
242
|
config.device = device;
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
res->
|
|
243
|
-
return res;
|
|
243
|
+
auto res = std::make_unique<GpuIndexCagra>(
|
|
244
|
+
provider, icg->d, icg->metric_type, config);
|
|
245
|
+
res->copyFrom(icg);
|
|
246
|
+
return res.release();
|
|
244
247
|
}
|
|
245
248
|
#endif
|
|
246
249
|
else {
|
|
@@ -533,7 +536,7 @@ faiss::IndexBinary* index_binary_gpu_to_cpu(
|
|
|
533
536
|
ii->copyTo(ret);
|
|
534
537
|
return ret;
|
|
535
538
|
}
|
|
536
|
-
#if defined
|
|
539
|
+
#if defined USE_NVIDIA_CUVS
|
|
537
540
|
else if (auto ii = dynamic_cast<const GpuIndexBinaryCagra*>(gpu_index)) {
|
|
538
541
|
IndexBinaryHNSWCagra* ret = new IndexBinaryHNSWCagra();
|
|
539
542
|
ii->copyTo(ret);
|
|
@@ -555,15 +558,15 @@ faiss::IndexBinary* index_binary_cpu_to_gpu(
|
|
|
555
558
|
config.device = device;
|
|
556
559
|
return new GpuIndexBinaryFlat(provider, ii, config);
|
|
557
560
|
}
|
|
558
|
-
#if defined
|
|
561
|
+
#if defined USE_NVIDIA_CUVS
|
|
559
562
|
else if (
|
|
560
563
|
auto ii = dynamic_cast<const faiss::IndexBinaryHNSWCagra*>(index)) {
|
|
561
564
|
GpuIndexCagraConfig config;
|
|
562
565
|
config.device = device;
|
|
563
|
-
|
|
564
|
-
|
|
566
|
+
auto res =
|
|
567
|
+
std::make_unique<GpuIndexBinaryCagra>(provider, ii->d, config);
|
|
565
568
|
res->copyFrom(ii);
|
|
566
|
-
return res;
|
|
569
|
+
return res.release();
|
|
567
570
|
}
|
|
568
571
|
#endif
|
|
569
572
|
else {
|
|
@@ -70,6 +70,8 @@ struct ToGpuClonerMultiple : faiss::Cloner, GpuMultipleClonerOptions {
|
|
|
70
70
|
faiss::Index* index_gpu_to_cpu(const faiss::Index* gpu_index);
|
|
71
71
|
|
|
72
72
|
/// converts any CPU index that can be converted to GPU
|
|
73
|
+
/// CAGRA clones contain only the graph. Call updateDataset with caller-owned,
|
|
74
|
+
/// compatible device storage before searching.
|
|
73
75
|
faiss::Index* index_cpu_to_gpu(
|
|
74
76
|
GpuResourcesProvider* provider,
|
|
75
77
|
int device,
|
|
@@ -105,6 +107,8 @@ faiss::IndexBinary* index_binary_gpu_to_cpu(
|
|
|
105
107
|
const faiss::IndexBinary* gpu_index);
|
|
106
108
|
|
|
107
109
|
/// converts any CPU index that can be converted to GPU
|
|
110
|
+
/// CAGRA clones contain only the graph. Call updateDataset with caller-owned,
|
|
111
|
+
/// compatible device storage before searching.
|
|
108
112
|
faiss::IndexBinary* index_binary_cpu_to_gpu(
|
|
109
113
|
GpuResourcesProvider* provider,
|
|
110
114
|
int device,
|
|
@@ -42,6 +42,9 @@ struct GpuClonerOptions {
|
|
|
42
42
|
/// Use the cuVS implementation. Opt-in: see GpuIndexConfig::use_cuvs.
|
|
43
43
|
bool use_cuvs = false;
|
|
44
44
|
|
|
45
|
+
/// IVF indexes only: see GpuIndexIVFConfig::deterministic_tie_break.
|
|
46
|
+
bool deterministic_tie_break = false;
|
|
47
|
+
|
|
45
48
|
/// This flag controls the CPU fallback logic for coarse quantizer
|
|
46
49
|
/// component of the index. When set to false (default), the cloner will
|
|
47
50
|
/// throw an exception for indices not implemented on GPU. When set to
|
|
@@ -213,6 +213,9 @@ class GpuIndex : public faiss::Index {
|
|
|
213
213
|
idx_t* labels,
|
|
214
214
|
const SearchParameters* params) const = 0;
|
|
215
215
|
|
|
216
|
+
/// Search with queries of the given numeric type; all data is guaranteed
|
|
217
|
+
/// to be resident on our device. The default handles Float32 and widens
|
|
218
|
+
/// Float16 queries to float32 on the device before calling searchImpl_
|
|
216
219
|
virtual void searchImpl_ex_(
|
|
217
220
|
idx_t n,
|
|
218
221
|
const void* x,
|
|
@@ -220,19 +223,7 @@ class GpuIndex : public faiss::Index {
|
|
|
220
223
|
int k,
|
|
221
224
|
float* distances,
|
|
222
225
|
idx_t* labels,
|
|
223
|
-
const SearchParameters* params) const
|
|
224
|
-
if (numeric_type == NumericType::Float32) {
|
|
225
|
-
searchImpl_(
|
|
226
|
-
n,
|
|
227
|
-
static_cast<const float*>(x),
|
|
228
|
-
k,
|
|
229
|
-
distances,
|
|
230
|
-
labels,
|
|
231
|
-
params);
|
|
232
|
-
} else {
|
|
233
|
-
FAISS_THROW_MSG("GpuIndex::searchImpl_: unsupported numeric type");
|
|
234
|
-
}
|
|
235
|
-
}
|
|
226
|
+
const SearchParameters* params) const;
|
|
236
227
|
|
|
237
228
|
private:
|
|
238
229
|
/// Calls addImpl_ for a single page of GPU-resident data
|