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
|
@@ -17,16 +17,20 @@
|
|
|
17
17
|
#include <cinttypes>
|
|
18
18
|
#include <cstdio>
|
|
19
19
|
#include <limits>
|
|
20
|
+
#include <optional>
|
|
20
21
|
|
|
22
|
+
#include <faiss/utils/random.h>
|
|
21
23
|
#include <faiss/utils/utils.h>
|
|
22
24
|
|
|
23
25
|
#include <faiss/IndexFlat.h>
|
|
26
|
+
#include <faiss/IndexHNSW.h>
|
|
24
27
|
#include <faiss/impl/AuxIndexStructures.h>
|
|
25
28
|
#include <faiss/impl/CodePacker.h>
|
|
26
29
|
#include <faiss/impl/FaissAssert.h>
|
|
27
30
|
#include <faiss/impl/IDSelector.h>
|
|
28
31
|
#include <faiss/impl/ResultHandler.h>
|
|
29
32
|
#include <faiss/impl/expanded_scanners.h>
|
|
33
|
+
#include <faiss/impl/platform_macros.h>
|
|
30
34
|
|
|
31
35
|
namespace faiss {
|
|
32
36
|
|
|
@@ -53,28 +57,89 @@ Level1Quantizer::~Level1Quantizer() {
|
|
|
53
57
|
}
|
|
54
58
|
}
|
|
55
59
|
|
|
56
|
-
|
|
60
|
+
namespace {
|
|
61
|
+
|
|
62
|
+
void add_hnsw_quantizer_links(
|
|
63
|
+
IndexHNSW& hnsw,
|
|
57
64
|
size_t n,
|
|
58
|
-
const
|
|
65
|
+
const uint8_t* x,
|
|
66
|
+
NumericType numeric_type,
|
|
67
|
+
const Index* codec,
|
|
68
|
+
bool verbose) {
|
|
69
|
+
const size_t samples = std::min(
|
|
70
|
+
n,
|
|
71
|
+
size_t(hnsw.level_0_link_samples_per_node) * size_t(hnsw.ntotal));
|
|
72
|
+
const HNSWLevel0LinkStats stats = codec
|
|
73
|
+
? hnsw.add_level_0_links_from_sample_encoded(samples, x, codec)
|
|
74
|
+
: hnsw.add_level_0_links_from_sample_ex(samples, x, numeric_type);
|
|
75
|
+
if (verbose) {
|
|
76
|
+
printf("HNSW quantizer level-0 links from %zd samples: %zd sinks found, "
|
|
77
|
+
"%zd remaining, %zd links added, %zd replaced\n",
|
|
78
|
+
samples,
|
|
79
|
+
stats.n_sinks_found,
|
|
80
|
+
stats.n_sinks_remaining,
|
|
81
|
+
stats.n_links_added,
|
|
82
|
+
stats.n_links_replaced);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Trains `q1` on rows encoded by `codec` or, if codec is null, stored as
|
|
87
|
+
* `numeric_type`. */
|
|
88
|
+
void train_q1_impl(
|
|
89
|
+
Level1Quantizer& q1,
|
|
90
|
+
size_t n,
|
|
91
|
+
const uint8_t* x,
|
|
92
|
+
NumericType numeric_type,
|
|
93
|
+
const Index* codec,
|
|
59
94
|
bool verbose,
|
|
60
95
|
MetricType metric_type) {
|
|
96
|
+
Index* quantizer = q1.quantizer;
|
|
97
|
+
const size_t nlist = q1.nlist;
|
|
98
|
+
const ClusteringParameters& cp = q1.cp;
|
|
99
|
+
Index* clustering_index = q1.clustering_index;
|
|
100
|
+
|
|
101
|
+
auto add_quantizer_links = [&]() {
|
|
102
|
+
auto* hnsw = dynamic_cast<IndexHNSW*>(quantizer);
|
|
103
|
+
if (hnsw && hnsw->level_0_link_samples_per_node > 0) {
|
|
104
|
+
add_hnsw_quantizer_links(*hnsw, n, x, numeric_type, codec, verbose);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// k-means on the training rows, with `assigner` as assignment index
|
|
109
|
+
auto train_clustering = [&](Clustering& clus, Index& assigner) {
|
|
110
|
+
if (codec) {
|
|
111
|
+
clus.train_encoded(n, x, codec, assigner);
|
|
112
|
+
} else {
|
|
113
|
+
clus.train_ex(n, x, numeric_type, assigner);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
61
117
|
FAISS_THROW_IF_NOT_MSG(quantizer, "IVF quantizer must not be null");
|
|
62
118
|
size_t d = quantizer->d;
|
|
119
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
120
|
+
!codec || static_cast<size_t>(codec->d) == d,
|
|
121
|
+
"Codec dimension %d not the same as quantizer dimension %d",
|
|
122
|
+
codec ? codec->d : 0,
|
|
123
|
+
int(d));
|
|
63
124
|
if (quantizer->is_trained &&
|
|
64
125
|
(static_cast<size_t>(quantizer->ntotal) == nlist)) {
|
|
65
126
|
if (verbose) {
|
|
66
127
|
printf("IVF quantizer does not need training.\n");
|
|
67
128
|
}
|
|
68
|
-
} else if (quantizer_trains_alone == 1) {
|
|
129
|
+
} else if (q1.quantizer_trains_alone == 1) {
|
|
130
|
+
FAISS_THROW_IF_MSG(
|
|
131
|
+
codec,
|
|
132
|
+
"encoded training is not supported when the IVF quantizer "
|
|
133
|
+
"trains alone");
|
|
69
134
|
if (verbose) {
|
|
70
135
|
printf("IVF quantizer trains alone...\n");
|
|
71
136
|
}
|
|
72
137
|
quantizer->verbose = verbose;
|
|
73
|
-
quantizer->
|
|
138
|
+
quantizer->train_ex(n, x, numeric_type);
|
|
74
139
|
FAISS_THROW_IF_NOT_MSG(
|
|
75
140
|
static_cast<size_t>(quantizer->ntotal) == nlist,
|
|
76
141
|
"nlist not consistent with quantizer size");
|
|
77
|
-
} else if (quantizer_trains_alone == 0) {
|
|
142
|
+
} else if (q1.quantizer_trains_alone == 0) {
|
|
78
143
|
if (verbose) {
|
|
79
144
|
printf("Training level-1 quantizer on %zd vectors in %zdD\n", n, d);
|
|
80
145
|
}
|
|
@@ -83,6 +148,16 @@ void Level1Quantizer::train_q1(
|
|
|
83
148
|
cp.use_super_kmeans && clustering_index,
|
|
84
149
|
"cp.use_super_kmeans is incompatible with a user-provided "
|
|
85
150
|
"clustering_index: SuperKMeans assigns with its own index");
|
|
151
|
+
FAISS_THROW_IF_MSG(
|
|
152
|
+
cp.use_super_kmeans && codec,
|
|
153
|
+
"SuperKMeans does not support encoded training data");
|
|
154
|
+
FAISS_THROW_IF_MSG(
|
|
155
|
+
cp.use_super_kmeans &&
|
|
156
|
+
!(metric_type == METRIC_L2 ||
|
|
157
|
+
(metric_type == METRIC_INNER_PRODUCT &&
|
|
158
|
+
cp.spherical)),
|
|
159
|
+
"SuperKMeans requires L2 or spherical inner-product "
|
|
160
|
+
"clustering");
|
|
86
161
|
|
|
87
162
|
quantizer->reset();
|
|
88
163
|
if (cp.use_super_kmeans) {
|
|
@@ -90,19 +165,20 @@ void Level1Quantizer::train_q1(
|
|
|
90
165
|
static_cast<ClusteringParameters&>(super_cp) = cp;
|
|
91
166
|
SuperKMeans clus(
|
|
92
167
|
static_cast<int>(d), static_cast<int>(nlist), super_cp);
|
|
93
|
-
clus.
|
|
168
|
+
clus.train_ex(n, x, numeric_type);
|
|
94
169
|
quantizer->add(nlist, clus.centroids.data());
|
|
95
170
|
} else {
|
|
96
171
|
Clustering clus(static_cast<int>(d), static_cast<int>(nlist), cp);
|
|
97
172
|
if (clustering_index) {
|
|
98
|
-
clus
|
|
173
|
+
train_clustering(clus, *clustering_index);
|
|
99
174
|
quantizer->add(nlist, clus.centroids.data());
|
|
100
175
|
} else {
|
|
101
|
-
clus
|
|
176
|
+
train_clustering(clus, *quantizer);
|
|
102
177
|
}
|
|
103
178
|
}
|
|
104
179
|
quantizer->is_trained = true;
|
|
105
|
-
|
|
180
|
+
add_quantizer_links();
|
|
181
|
+
} else if (q1.quantizer_trains_alone == 2) {
|
|
106
182
|
if (verbose) {
|
|
107
183
|
printf("Training L2 quantizer on %zd vectors in %zdD%s\n",
|
|
108
184
|
n,
|
|
@@ -118,9 +194,9 @@ void Level1Quantizer::train_q1(
|
|
|
118
194
|
Clustering clus(static_cast<int>(d), static_cast<int>(nlist), cp);
|
|
119
195
|
if (!clustering_index) {
|
|
120
196
|
IndexFlatL2 assigner(d);
|
|
121
|
-
clus
|
|
197
|
+
train_clustering(clus, assigner);
|
|
122
198
|
} else {
|
|
123
|
-
clus
|
|
199
|
+
train_clustering(clus, *clustering_index);
|
|
124
200
|
}
|
|
125
201
|
if (verbose) {
|
|
126
202
|
printf("Adding centroids to quantizer\n");
|
|
@@ -132,9 +208,46 @@ void Level1Quantizer::train_q1(
|
|
|
132
208
|
quantizer->train(nlist, clus.centroids.data());
|
|
133
209
|
}
|
|
134
210
|
quantizer->add(nlist, clus.centroids.data());
|
|
211
|
+
add_quantizer_links();
|
|
135
212
|
}
|
|
136
213
|
}
|
|
137
214
|
|
|
215
|
+
} // namespace
|
|
216
|
+
|
|
217
|
+
void Level1Quantizer::train_q1(
|
|
218
|
+
size_t n,
|
|
219
|
+
const float* x,
|
|
220
|
+
bool verbose,
|
|
221
|
+
MetricType metric_type) {
|
|
222
|
+
train_q1_ex(n, x, NumericType::Float32, verbose, metric_type);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
void Level1Quantizer::train_q1_ex(
|
|
226
|
+
size_t n,
|
|
227
|
+
const void* x,
|
|
228
|
+
NumericType numeric_type,
|
|
229
|
+
bool verbose,
|
|
230
|
+
MetricType metric_type) {
|
|
231
|
+
train_q1_impl(
|
|
232
|
+
*this,
|
|
233
|
+
n,
|
|
234
|
+
static_cast<const uint8_t*>(x),
|
|
235
|
+
numeric_type,
|
|
236
|
+
nullptr,
|
|
237
|
+
verbose,
|
|
238
|
+
metric_type);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
void Level1Quantizer::train_q1_encoded(
|
|
242
|
+
size_t n,
|
|
243
|
+
const uint8_t* x,
|
|
244
|
+
const Index* codec,
|
|
245
|
+
bool verbose,
|
|
246
|
+
MetricType metric_type) {
|
|
247
|
+
train_q1_impl(
|
|
248
|
+
*this, n, x, NumericType::Float32, codec, verbose, metric_type);
|
|
249
|
+
}
|
|
250
|
+
|
|
138
251
|
size_t Level1Quantizer::coarse_code_size() const {
|
|
139
252
|
size_t nl = nlist - 1;
|
|
140
253
|
size_t nbyte = 0;
|
|
@@ -437,19 +550,21 @@ void IndexIVF::search_preassigned(
|
|
|
437
550
|
const bool ensure_topk_full = params ? params->ensure_topk_full : false;
|
|
438
551
|
|
|
439
552
|
IDSelector* sel = params ? params->sel : nullptr;
|
|
553
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
554
|
+
!(sel && store_pairs),
|
|
555
|
+
"selector and store_pairs cannot be combined");
|
|
556
|
+
|
|
440
557
|
const IDSelectorRange* selr = dynamic_cast<const IDSelectorRange*>(sel);
|
|
441
558
|
if (selr) {
|
|
442
|
-
|
|
559
|
+
// The sorted-range shortcut bounds a section of an array-backed list,
|
|
560
|
+
// so an iterable list has to keep the selector and filter per entry.
|
|
561
|
+
if (selr->assume_sorted && !invlists->use_iterator) {
|
|
443
562
|
sel = nullptr; // use special IDSelectorRange processing
|
|
444
563
|
} else {
|
|
445
564
|
selr = nullptr; // use generic processing
|
|
446
565
|
}
|
|
447
566
|
}
|
|
448
567
|
|
|
449
|
-
FAISS_THROW_IF_NOT_MSG(
|
|
450
|
-
!(sel && store_pairs),
|
|
451
|
-
"selector and store_pairs cannot be combined");
|
|
452
|
-
|
|
453
568
|
FAISS_THROW_IF_NOT_MSG(
|
|
454
569
|
!invlists->use_iterator ||
|
|
455
570
|
(cur_max_codes == 0 && store_pairs == false),
|
|
@@ -568,10 +683,9 @@ void IndexIVF::search_preassigned(
|
|
|
568
683
|
return (size_t)0;
|
|
569
684
|
}
|
|
570
685
|
|
|
571
|
-
scanner->set_list(key, coarse_dis_i);
|
|
572
|
-
|
|
573
686
|
nlistv++;
|
|
574
687
|
if (invlists->use_iterator) {
|
|
688
|
+
scanner->set_list(key, coarse_dis_i);
|
|
575
689
|
size_t list_size = 0;
|
|
576
690
|
std::unique_ptr<InvertedListsIterator> it(
|
|
577
691
|
invlists->get_iterator(key, inverted_list_context));
|
|
@@ -586,31 +700,30 @@ void IndexIVF::search_preassigned(
|
|
|
586
700
|
list_size = static_cast<size_t>(list_size_max);
|
|
587
701
|
}
|
|
588
702
|
|
|
589
|
-
InvertedLists::
|
|
590
|
-
const uint8_t* codes = scodes.get();
|
|
591
|
-
|
|
592
|
-
std::unique_ptr<InvertedLists::ScopedIds> sids;
|
|
703
|
+
std::optional<InvertedLists::ScopedIds> sids;
|
|
593
704
|
const idx_t* ids = nullptr;
|
|
594
|
-
|
|
595
705
|
if (!store_pairs) {
|
|
596
|
-
sids
|
|
597
|
-
invlists, key);
|
|
706
|
+
sids.emplace(invlists, key);
|
|
598
707
|
ids = sids->get();
|
|
599
708
|
}
|
|
600
709
|
|
|
710
|
+
size_t jmin = 0;
|
|
601
711
|
if (selr) { // IDSelectorRange
|
|
602
712
|
// restrict search to a section of the inverted list
|
|
603
|
-
size_t
|
|
713
|
+
size_t jmax;
|
|
604
714
|
selr->find_sorted_ids_bounds(
|
|
605
715
|
list_size, ids, &jmin, &jmax);
|
|
606
716
|
list_size = jmax - jmin;
|
|
607
717
|
if (list_size == 0) {
|
|
608
718
|
return (size_t)0;
|
|
609
719
|
}
|
|
610
|
-
codes += jmin * code_size;
|
|
611
720
|
ids += jmin;
|
|
612
721
|
}
|
|
613
722
|
|
|
723
|
+
scanner->set_list(key, coarse_dis_i);
|
|
724
|
+
InvertedLists::ScopedCodes scodes(invlists, key);
|
|
725
|
+
const uint8_t* codes = scodes.get() + jmin * code_size;
|
|
726
|
+
|
|
614
727
|
size_t old_scan_cnt = 0;
|
|
615
728
|
size_t old_heap_updates = 0;
|
|
616
729
|
if (is_similarity_metric(metric_type)) {
|
|
@@ -692,7 +805,7 @@ void IndexIVF::search_preassigned(
|
|
|
692
805
|
scanner->set_query(x + i * d);
|
|
693
806
|
init_result(local_dis.data(), local_idx.data());
|
|
694
807
|
|
|
695
|
-
#pragma omp for schedule(
|
|
808
|
+
#pragma omp for schedule(FAISS_OMP_DYNAMIC)
|
|
696
809
|
for (idx_t ik = 0; ik < cur_nprobe; ik++) {
|
|
697
810
|
try {
|
|
698
811
|
ndis += scan_one_list(
|
|
@@ -734,7 +847,7 @@ void IndexIVF::search_preassigned(
|
|
|
734
847
|
init_result(distances + i * k, labels + i * k);
|
|
735
848
|
}
|
|
736
849
|
|
|
737
|
-
#pragma omp for schedule(
|
|
850
|
+
#pragma omp for schedule(FAISS_OMP_DYNAMIC)
|
|
738
851
|
for (int64_t ij = 0; ij < n * cur_nprobe; ij++) {
|
|
739
852
|
try {
|
|
740
853
|
size_t i = ij / cur_nprobe;
|
|
@@ -957,7 +1070,7 @@ void IndexIVF::range_search_preassigned(
|
|
|
957
1070
|
|
|
958
1071
|
RangeQueryResult& qres = pres.new_result(i);
|
|
959
1072
|
|
|
960
|
-
#pragma omp for schedule(
|
|
1073
|
+
#pragma omp for schedule(FAISS_OMP_DYNAMIC)
|
|
961
1074
|
for (int64_t ik = 0; ik < cur_nprobe; ik++) {
|
|
962
1075
|
try {
|
|
963
1076
|
scan_list_func(i, ik, qres);
|
|
@@ -969,7 +1082,7 @@ void IndexIVF::range_search_preassigned(
|
|
|
969
1082
|
} else if (parallel_mode == 2) {
|
|
970
1083
|
RangeQueryResult* qres = nullptr;
|
|
971
1084
|
|
|
972
|
-
#pragma omp for schedule(
|
|
1085
|
+
#pragma omp for schedule(FAISS_OMP_DYNAMIC)
|
|
973
1086
|
for (idx_t iik = 0; iik < nx * (idx_t)cur_nprobe; iik++) {
|
|
974
1087
|
try {
|
|
975
1088
|
idx_t i = iik / (idx_t)cur_nprobe;
|
|
@@ -1308,6 +1421,125 @@ void IndexIVF::update_vectors(int n, const idx_t* new_ids, const float* x) {
|
|
|
1308
1421
|
invlists, n, new_ids, assign.data(), flat_codes.data());
|
|
1309
1422
|
}
|
|
1310
1423
|
|
|
1424
|
+
namespace {
|
|
1425
|
+
|
|
1426
|
+
/** Trains the encoder of `ivf` on training rows that are not fp32.
|
|
1427
|
+
*
|
|
1428
|
+
* Only the train_encoder_num_vectors() rows sampled for the encoder are
|
|
1429
|
+
* widened to fp32. `decode_rows(n, rows, out)` widens n consecutive rows of
|
|
1430
|
+
* `row_size` bytes.
|
|
1431
|
+
*/
|
|
1432
|
+
template <class DecodeRows>
|
|
1433
|
+
void train_encoder_on_encoded_rows(
|
|
1434
|
+
IndexIVF& ivf,
|
|
1435
|
+
idx_t n,
|
|
1436
|
+
const uint8_t* x,
|
|
1437
|
+
size_t row_size,
|
|
1438
|
+
const DecodeRows& decode_rows) {
|
|
1439
|
+
const size_t d = ivf.d;
|
|
1440
|
+
idx_t max_nt = ivf.train_encoder_num_vectors();
|
|
1441
|
+
if (max_nt <= 0 || n <= max_nt) {
|
|
1442
|
+
max_nt = n;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
std::vector<float> decoded(static_cast<size_t>(max_nt) * d);
|
|
1446
|
+
if (max_nt == n) {
|
|
1447
|
+
decode_rows(n, x, decoded.data());
|
|
1448
|
+
} else {
|
|
1449
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
1450
|
+
n <= static_cast<idx_t>(std::numeric_limits<int>::max()),
|
|
1451
|
+
"Dataset too large (%" PRId64 ") for standard subsampling",
|
|
1452
|
+
n);
|
|
1453
|
+
if (ivf.verbose) {
|
|
1454
|
+
printf(" Input training set too big (max size is %" PRId64
|
|
1455
|
+
"), sampling %" PRId64 " / %" PRId64 " vectors\n",
|
|
1456
|
+
max_nt,
|
|
1457
|
+
max_nt,
|
|
1458
|
+
n);
|
|
1459
|
+
}
|
|
1460
|
+
std::vector<int> subset(static_cast<size_t>(n));
|
|
1461
|
+
rand_perm(subset.data(), n, 1234);
|
|
1462
|
+
for (idx_t i = 0; i < max_nt; ++i) {
|
|
1463
|
+
decode_rows(
|
|
1464
|
+
1,
|
|
1465
|
+
x + static_cast<size_t>(subset[i]) * row_size,
|
|
1466
|
+
decoded.data() + static_cast<size_t>(i) * d);
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
n = max_nt;
|
|
1470
|
+
|
|
1471
|
+
if (ivf.by_residual) {
|
|
1472
|
+
FAISS_THROW_IF_NOT_MSG(ivf.quantizer, "IVF quantizer must not be null");
|
|
1473
|
+
std::vector<idx_t> assign(n);
|
|
1474
|
+
ivf.quantizer->assign(n, decoded.data(), assign.data());
|
|
1475
|
+
|
|
1476
|
+
std::vector<float> residuals(static_cast<size_t>(n) * d);
|
|
1477
|
+
ivf.quantizer->compute_residual_n(
|
|
1478
|
+
n, decoded.data(), residuals.data(), assign.data());
|
|
1479
|
+
|
|
1480
|
+
ivf.train_encoder(n, residuals.data(), assign.data());
|
|
1481
|
+
} else {
|
|
1482
|
+
ivf.train_encoder(n, decoded.data(), nullptr);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
} // namespace
|
|
1487
|
+
|
|
1488
|
+
void IndexIVF::train_ex(idx_t n, const void* x, NumericType numeric_type) {
|
|
1489
|
+
if (numeric_type != NumericType::Float16) {
|
|
1490
|
+
Index::train_ex(n, x, numeric_type);
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
FAISS_THROW_IF_NOT_MSG(x, "training data must not be null");
|
|
1494
|
+
if (verbose) {
|
|
1495
|
+
printf("Training level-1 quantizer on fp16 data\n");
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
train_q1_ex(n, x, numeric_type, verbose, metric_type);
|
|
1499
|
+
|
|
1500
|
+
if (verbose) {
|
|
1501
|
+
printf("Training IVF residual\n");
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
const size_t dim = d;
|
|
1505
|
+
train_encoder_on_encoded_rows(
|
|
1506
|
+
*this,
|
|
1507
|
+
n,
|
|
1508
|
+
static_cast<const uint8_t*>(x),
|
|
1509
|
+
sizeof(uint16_t) * dim,
|
|
1510
|
+
[dim](idx_t ni, const uint8_t* rows, float* out) {
|
|
1511
|
+
fp16_to_fp32(
|
|
1512
|
+
ni * dim, reinterpret_cast<const uint16_t*>(rows), out);
|
|
1513
|
+
});
|
|
1514
|
+
|
|
1515
|
+
is_trained = true;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
void IndexIVF::train_encoded(idx_t n, const uint8_t* x, const Index* codec) {
|
|
1519
|
+
FAISS_THROW_IF_NOT_MSG(codec, "encoded training requires a codec");
|
|
1520
|
+
FAISS_THROW_IF_NOT_MSG(x, "encoded training data must not be null");
|
|
1521
|
+
if (verbose) {
|
|
1522
|
+
printf("Training level-1 quantizer\n");
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
train_q1_encoded(n, x, codec, verbose, metric_type);
|
|
1526
|
+
|
|
1527
|
+
if (verbose) {
|
|
1528
|
+
printf("Training IVF residual\n");
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
train_encoder_on_encoded_rows(
|
|
1532
|
+
*this,
|
|
1533
|
+
n,
|
|
1534
|
+
x,
|
|
1535
|
+
codec->sa_code_size(),
|
|
1536
|
+
[codec](idx_t ni, const uint8_t* rows, float* out) {
|
|
1537
|
+
codec->sa_decode(ni, rows, out);
|
|
1538
|
+
});
|
|
1539
|
+
|
|
1540
|
+
is_trained = true;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1311
1543
|
void IndexIVF::train(idx_t n, const float* x) {
|
|
1312
1544
|
if (verbose) {
|
|
1313
1545
|
printf("Training level-1 quantizer\n");
|
|
@@ -1462,6 +1694,15 @@ size_t InvertedListScanner::scan_codes(
|
|
|
1462
1694
|
return run_scan_codes(*this, list_size, codes, ids, handler);
|
|
1463
1695
|
}
|
|
1464
1696
|
|
|
1697
|
+
void InvertedListScanner::distances_to_codes(
|
|
1698
|
+
size_t n,
|
|
1699
|
+
const uint8_t* codes,
|
|
1700
|
+
float* distances) const {
|
|
1701
|
+
for (size_t j = 0; j < n; j++) {
|
|
1702
|
+
distances[j] = distance_to_code(codes + j * code_size);
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1465
1706
|
void InvertedListScanner::set_list(idx_t list_no_in, float /* coarse_dis */) {
|
|
1466
1707
|
this->list_no = list_no_in;
|
|
1467
1708
|
}
|
|
@@ -1498,6 +1739,9 @@ size_t InvertedListScanner::iterate_codes(
|
|
|
1498
1739
|
if (!keep_max) {
|
|
1499
1740
|
for (; it->is_available(); it->next()) {
|
|
1500
1741
|
auto id_and_codes = it->get_id_and_codes();
|
|
1742
|
+
if (sel && !sel->is_member(id_and_codes.first)) {
|
|
1743
|
+
continue;
|
|
1744
|
+
}
|
|
1501
1745
|
float dis = distance_to_code(id_and_codes.second);
|
|
1502
1746
|
if (has_cb) {
|
|
1503
1747
|
it->on_distance_computed(id_and_codes.first, dis);
|
|
@@ -1514,6 +1758,9 @@ size_t InvertedListScanner::iterate_codes(
|
|
|
1514
1758
|
} else {
|
|
1515
1759
|
for (; it->is_available(); it->next()) {
|
|
1516
1760
|
auto id_and_codes = it->get_id_and_codes();
|
|
1761
|
+
if (sel && !sel->is_member(id_and_codes.first)) {
|
|
1762
|
+
continue;
|
|
1763
|
+
}
|
|
1517
1764
|
float dis = distance_to_code(id_and_codes.second);
|
|
1518
1765
|
if (has_cb) {
|
|
1519
1766
|
it->on_distance_computed(id_and_codes.first, dis);
|
|
@@ -1561,6 +1808,9 @@ void InvertedListScanner::iterate_codes_range(
|
|
|
1561
1808
|
list_size = 0;
|
|
1562
1809
|
for (; it->is_available(); it->next()) {
|
|
1563
1810
|
auto id_and_codes = it->get_id_and_codes();
|
|
1811
|
+
if (sel && !sel->is_member(id_and_codes.first)) {
|
|
1812
|
+
continue;
|
|
1813
|
+
}
|
|
1564
1814
|
float dis = distance_to_code(id_and_codes.second);
|
|
1565
1815
|
bool keep = !keep_max
|
|
1566
1816
|
? dis < radius
|
|
@@ -46,13 +46,41 @@ struct Level1Quantizer {
|
|
|
46
46
|
/// to override index used during clustering
|
|
47
47
|
Index* clustering_index = nullptr;
|
|
48
48
|
|
|
49
|
-
/// Trains the quantizer
|
|
49
|
+
/// Trains the level-1 quantizer from fp32 vectors.
|
|
50
50
|
void train_q1(
|
|
51
51
|
size_t n,
|
|
52
52
|
const float* x,
|
|
53
53
|
bool verbose,
|
|
54
54
|
MetricType metric_type);
|
|
55
55
|
|
|
56
|
+
/** Trains the level-1 quantizer from Float32 or packed Float16 vectors.
|
|
57
|
+
*
|
|
58
|
+
* Float16 runs k-means natively on the fp16 rows (see
|
|
59
|
+
* Clustering::train_ex). With quantizer_trains_alone == 1 the data is
|
|
60
|
+
* passed on to quantizer->train_ex(). SuperKMeans supports raw Float32
|
|
61
|
+
* and Float16 input, but not vectors decoded through a codec.
|
|
62
|
+
*/
|
|
63
|
+
void train_q1_ex(
|
|
64
|
+
size_t n,
|
|
65
|
+
const void* x,
|
|
66
|
+
NumericType numeric_type,
|
|
67
|
+
bool verbose,
|
|
68
|
+
MetricType metric_type);
|
|
69
|
+
|
|
70
|
+
/** Trains the level-1 quantizer from vectors encoded by `codec`.
|
|
71
|
+
*
|
|
72
|
+
* The codec must remain alive for the duration of this call and decode
|
|
73
|
+
* each input row to `quantizer->d` floats. Encoded training is supported
|
|
74
|
+
* when clustering trains the quantizer (quantizer_trains_alone 0 or 2)
|
|
75
|
+
* without SuperKMeans.
|
|
76
|
+
*/
|
|
77
|
+
void train_q1_encoded(
|
|
78
|
+
size_t n,
|
|
79
|
+
const uint8_t* x,
|
|
80
|
+
const Index* codec,
|
|
81
|
+
bool verbose,
|
|
82
|
+
MetricType metric_type);
|
|
83
|
+
|
|
56
84
|
/// compute the number of bytes required to store list ids
|
|
57
85
|
size_t coarse_code_size() const;
|
|
58
86
|
void encode_listno(idx_t list_no, uint8_t* code) const;
|
|
@@ -236,6 +264,23 @@ struct IndexIVF : Index, IndexIVFInterface {
|
|
|
236
264
|
/// Trains the quantizer and calls train_encoder to train sub-quantizers
|
|
237
265
|
void train(idx_t n, const float* x) override;
|
|
238
266
|
|
|
267
|
+
/** Train from vectors decoded on demand by `codec`.
|
|
268
|
+
*
|
|
269
|
+
* Coarse quantizer training decodes in bounded batches. Subclasses with a
|
|
270
|
+
* trainable encoder decode at most train_encoder_num_vectors() rows into
|
|
271
|
+
* fp32; IndexIVFFlat overrides this method and needs no fp32 corpus buffer.
|
|
272
|
+
*/
|
|
273
|
+
virtual void train_encoded(idx_t n, const uint8_t* x, const Index* codec);
|
|
274
|
+
|
|
275
|
+
/** Supports Float32 and packed IEEE binary16 (Float16) inputs.
|
|
276
|
+
*
|
|
277
|
+
* Float16 trains natively without a codec: the coarse quantizer runs
|
|
278
|
+
* fp16 k-means (Clustering::train_ex) and only the
|
|
279
|
+
* train_encoder_num_vectors() rows sampled for the encoder are widened
|
|
280
|
+
* to fp32. IndexIVFFlat overrides this and widens no rows at all.
|
|
281
|
+
*/
|
|
282
|
+
void train_ex(idx_t n, const void* x, NumericType numeric_type) override;
|
|
283
|
+
|
|
239
284
|
/// Calls add_with_ids with NULL ids
|
|
240
285
|
void add(idx_t n, const float* x) override;
|
|
241
286
|
|
|
@@ -521,6 +566,13 @@ struct InvertedListScanner {
|
|
|
521
566
|
/// compute a single query-to-code distance
|
|
522
567
|
virtual float distance_to_code(const uint8_t* code) const = 0;
|
|
523
568
|
|
|
569
|
+
/** compute the distances to n consecutive codes of code_size bytes. A
|
|
570
|
+
* distance can differ in the last bits from distance_to_code. */
|
|
571
|
+
virtual void distances_to_codes(
|
|
572
|
+
size_t n,
|
|
573
|
+
const uint8_t* codes,
|
|
574
|
+
float* distances) const;
|
|
575
|
+
|
|
524
576
|
/** scan a set of codes, compute distances to current query, and
|
|
525
577
|
* update heap of results if necessary. Default implementation
|
|
526
578
|
* calls distance_to_code.
|