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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f7ff5a38fc140c730f7dfca4bbbfa2e2e4980fd63bf9f069ebbb9eb8deb4d50c
|
|
4
|
+
data.tar.gz: 919723a22c26f62267c9be7e34250ef7a30a5da682679634dd64471eef5187c4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 28e32877ea44804c5f73fcae9b8df462a024c56198156c0928a7ac2405d8cb4263e266bcc1fba2f88c41e3d62ba626fc55a4a228fe06e2d4e24421bb6e02b61b
|
|
7
|
+
data.tar.gz: 56cfa780d1d5361e3b43937c1b392a26528e4f3bd8166b0945c9cda63b32942e7001b7703e5705ba158a70ed92da69ef6983d1bbacd94362a9167403874aeb1e
|
data/CHANGELOG.md
CHANGED
data/ext/faiss/extconf.rb
CHANGED
|
@@ -33,7 +33,7 @@ ext = File.expand_path(".", __dir__)
|
|
|
33
33
|
vendor = File.expand_path("../../vendor/faiss", __dir__)
|
|
34
34
|
|
|
35
35
|
$srcs = Dir["{#{ext},#{vendor}/faiss,#{vendor}/faiss/{impl,invlists,utils}/**}/*.{cpp}"]
|
|
36
|
-
$srcs
|
|
36
|
+
$srcs.reject! { |v| v.match?(/avx2|avx512|neon|sve|rvv|simdlib_based|distances_aarch64/) }
|
|
37
37
|
$objs = $srcs.map { |v| v.sub(/cpp\z/, "o") }
|
|
38
38
|
abort "Faiss not found" unless find_header("faiss/Index.h", vendor)
|
|
39
39
|
$VPATH << vendor
|
data/lib/faiss/version.rb
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
#include <faiss/AutoTune.h>
|
|
15
15
|
|
|
16
16
|
#include <cinttypes>
|
|
17
|
+
#include <cmath>
|
|
17
18
|
|
|
18
19
|
#include <faiss/impl/FaissAssert.h>
|
|
19
20
|
#include <faiss/utils/random.h>
|
|
@@ -31,6 +32,11 @@
|
|
|
31
32
|
#include <faiss/IndexRefine.h>
|
|
32
33
|
#include <faiss/IndexShardsIVF.h>
|
|
33
34
|
|
|
35
|
+
#ifdef FAISS_ENABLE_SVS
|
|
36
|
+
#include <faiss/svs/IndexSVSVamana.h>
|
|
37
|
+
#include <faiss/svs/IndexSVSVamanaLeanVec.h>
|
|
38
|
+
#endif
|
|
39
|
+
|
|
34
40
|
namespace faiss {
|
|
35
41
|
|
|
36
42
|
AutoTuneCriterion::AutoTuneCriterion(idx_t nq_in, idx_t nnn_in)
|
|
@@ -484,6 +490,166 @@ void ParameterSpace::set_index_parameters(
|
|
|
484
490
|
});
|
|
485
491
|
}
|
|
486
492
|
|
|
493
|
+
#ifdef FAISS_ENABLE_SVS
|
|
494
|
+
|
|
495
|
+
namespace {
|
|
496
|
+
|
|
497
|
+
size_t svs_size_param(const std::string& name, double val) {
|
|
498
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
499
|
+
std::isfinite(val) && val >= 0,
|
|
500
|
+
"ParameterSpace::set_index_parameter: %s cannot be negative (%g)",
|
|
501
|
+
name.c_str(),
|
|
502
|
+
val);
|
|
503
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
504
|
+
val == std::floor(val),
|
|
505
|
+
"ParameterSpace::set_index_parameter: %s must be an integer (%g)",
|
|
506
|
+
name.c_str(),
|
|
507
|
+
val);
|
|
508
|
+
// The double -> size_t cast below is undefined behavior on overflow.
|
|
509
|
+
// 2^(8*sizeof(size_t)) is exact in double, so a value below it always
|
|
510
|
+
// fits.
|
|
511
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
512
|
+
val < std::ldexp(1.0, static_cast<int>(8 * sizeof(size_t))),
|
|
513
|
+
"ParameterSpace::set_index_parameter: %s is too large (%g)",
|
|
514
|
+
name.c_str(),
|
|
515
|
+
val);
|
|
516
|
+
return size_t(val);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/* Checks to make sure ix->impl is null. The SVS build parameters are consumed
|
|
520
|
+
when the backend index is created on the first add() (ix->impl != nullptr
|
|
521
|
+
afterwards), so setting them later would be silently ignored. For LeanVec,
|
|
522
|
+
train() only builds training_data (consuming leanvec_d); the remaining build
|
|
523
|
+
parameters are still consumed at the first add(), hence remain settable after
|
|
524
|
+
train() but before add(). */
|
|
525
|
+
void check_svs_not_built(const IndexSVSVamana* ix, const std::string& name) {
|
|
526
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
527
|
+
ix->impl == nullptr,
|
|
528
|
+
"ParameterSpace::set_index_parameter: %s is a build-time "
|
|
529
|
+
"parameter, it cannot be changed after the SVS index is built",
|
|
530
|
+
name.c_str());
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/* Sets a parameter of IndexSVSVamana or of its LVQ / LeanVec subclasses.
|
|
534
|
+
Returns false if the name is not an SVS Vamana parameter. */
|
|
535
|
+
bool set_svs_vamana_parameter(
|
|
536
|
+
IndexSVSVamana* ix,
|
|
537
|
+
const std::string& name,
|
|
538
|
+
double val) {
|
|
539
|
+
// Search parameters: re-read on every search(), hence tunable at any point
|
|
540
|
+
// in the index lifetime.
|
|
541
|
+
if (name == "search_window_size") {
|
|
542
|
+
ix->search_window_size = svs_size_param(name, val);
|
|
543
|
+
return true;
|
|
544
|
+
}
|
|
545
|
+
if (name == "search_buffer_capacity") {
|
|
546
|
+
ix->search_buffer_capacity = svs_size_param(name, val);
|
|
547
|
+
return true;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Graph build parameters.
|
|
551
|
+
if (name == "graph_max_degree") {
|
|
552
|
+
check_svs_not_built(ix, name);
|
|
553
|
+
ix->graph_max_degree = svs_size_param(name, val);
|
|
554
|
+
return true;
|
|
555
|
+
}
|
|
556
|
+
if (name == "prune_to") {
|
|
557
|
+
check_svs_not_built(ix, name);
|
|
558
|
+
ix->prune_to = svs_size_param(name, val);
|
|
559
|
+
return true;
|
|
560
|
+
}
|
|
561
|
+
if (name == "alpha") {
|
|
562
|
+
check_svs_not_built(ix, name);
|
|
563
|
+
ix->alpha = float(val);
|
|
564
|
+
return true;
|
|
565
|
+
}
|
|
566
|
+
if (name == "construction_window_size") {
|
|
567
|
+
check_svs_not_built(ix, name);
|
|
568
|
+
ix->construction_window_size = svs_size_param(name, val);
|
|
569
|
+
return true;
|
|
570
|
+
}
|
|
571
|
+
if (name == "max_candidate_pool_size") {
|
|
572
|
+
check_svs_not_built(ix, name);
|
|
573
|
+
ix->max_candidate_pool_size = svs_size_param(name, val);
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
576
|
+
if (name == "use_full_search_history") {
|
|
577
|
+
check_svs_not_built(ix, name);
|
|
578
|
+
ix->use_full_search_history = val != 0;
|
|
579
|
+
return true;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// Vector storage, which includes the LVQ and LeanVec compression levels.
|
|
583
|
+
if (name == "storage_kind") {
|
|
584
|
+
check_svs_not_built(ix, name);
|
|
585
|
+
size_t kind_idx = svs_size_param(name, val);
|
|
586
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
587
|
+
kind_idx < static_cast<size_t>(SVS_count),
|
|
588
|
+
"ParameterSpace::set_index_parameter: %g is not a valid "
|
|
589
|
+
"SVSStorageKind",
|
|
590
|
+
val);
|
|
591
|
+
auto kind = static_cast<SVSStorageKind>(kind_idx);
|
|
592
|
+
// Reject a kind that this build or machine does not support here
|
|
593
|
+
// rather than at build time, like the IndexSVSVamana constructor does.
|
|
594
|
+
// Both backends are accepted because storage_kind and is_static are
|
|
595
|
+
// build-time parameters that can be set in any order; the backend
|
|
596
|
+
// selected by is_static re-checks the kind at build time.
|
|
597
|
+
auto svs_kind = to_svs_storage_kind(kind);
|
|
598
|
+
auto status_static =
|
|
599
|
+
svs_runtime::VamanaIndex::check_storage_kind(svs_kind);
|
|
600
|
+
auto status_dynamic =
|
|
601
|
+
svs_runtime::DynamicVamanaIndex::check_storage_kind(svs_kind);
|
|
602
|
+
if (!status_static.ok() && !status_dynamic.ok()) {
|
|
603
|
+
FAISS_THROW_FMT(
|
|
604
|
+
"ParameterSpace::set_index_parameter: %s value %g is not "
|
|
605
|
+
"supported (static: %s; dynamic: %s)",
|
|
606
|
+
name.c_str(),
|
|
607
|
+
val,
|
|
608
|
+
status_static.message(),
|
|
609
|
+
status_dynamic.message());
|
|
610
|
+
}
|
|
611
|
+
ix->storage_kind = kind;
|
|
612
|
+
return true;
|
|
613
|
+
}
|
|
614
|
+
if (name == "is_static") {
|
|
615
|
+
check_svs_not_built(ix, name);
|
|
616
|
+
ix->is_static = val != 0;
|
|
617
|
+
return true;
|
|
618
|
+
}
|
|
619
|
+
if (name == "store_vectors") {
|
|
620
|
+
// Dropping the copy of the added vectors is always possible, but it
|
|
621
|
+
// cannot be undone: the copy left would not line up with the ids.
|
|
622
|
+
FAISS_THROW_IF_MSG(
|
|
623
|
+
val != 0 && !ix->stored_vectors_valid,
|
|
624
|
+
"ParameterSpace::set_index_parameter: store_vectors cannot be "
|
|
625
|
+
"re-enabled once the stored vectors have been dropped");
|
|
626
|
+
ix->store_vectors = val != 0;
|
|
627
|
+
return true;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// LeanVec only: dimensionality of the reduced (primary) vectors.
|
|
631
|
+
if (name == "leanvec_d") {
|
|
632
|
+
auto* lv = dynamic_cast<IndexSVSVamanaLeanVec*>(ix);
|
|
633
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
634
|
+
lv,
|
|
635
|
+
"ParameterSpace::set_index_parameter: leanvec_d only applies "
|
|
636
|
+
"to IndexSVSVamanaLeanVec");
|
|
637
|
+
check_svs_not_built(lv, name);
|
|
638
|
+
FAISS_THROW_IF_MSG(
|
|
639
|
+
lv->training_data,
|
|
640
|
+
"ParameterSpace::set_index_parameter: leanvec_d cannot be "
|
|
641
|
+
"changed after the LeanVec index has been trained");
|
|
642
|
+
lv->leanvec_d = svs_size_param(name, val);
|
|
643
|
+
return true;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
} // anonymous namespace
|
|
650
|
+
|
|
651
|
+
#endif // FAISS_ENABLE_SVS
|
|
652
|
+
|
|
487
653
|
// non-const version
|
|
488
654
|
// Do not use this macro if ix will be unused
|
|
489
655
|
#define DC(classname) classname* ix_ = dynamic_cast<classname*>(index)
|
|
@@ -613,6 +779,15 @@ void ParameterSpace::set_index_parameter(
|
|
|
613
779
|
}
|
|
614
780
|
}
|
|
615
781
|
|
|
782
|
+
#ifdef FAISS_ENABLE_SVS
|
|
783
|
+
// Covers IndexSVSVamanaLVQ and IndexSVSVamanaLeanVec as well
|
|
784
|
+
if (DC(IndexSVSVamana)) {
|
|
785
|
+
if (set_svs_vamana_parameter(ix_, name, val)) {
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
#endif
|
|
790
|
+
|
|
616
791
|
if (name.find("quantizer_") == 0) {
|
|
617
792
|
if (DC(IndexIVF)) {
|
|
618
793
|
std::string sub_name = name.substr(strlen("quantizer_"));
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
#include <faiss/VectorTransform.h>
|
|
12
12
|
#include <faiss/impl/AuxIndexStructures.h>
|
|
13
13
|
|
|
14
|
+
#include <algorithm>
|
|
14
15
|
#include <cinttypes>
|
|
15
16
|
#include <cmath>
|
|
16
17
|
#include <cstdio>
|
|
@@ -63,6 +64,47 @@ void Clustering::train_encoded(
|
|
|
63
64
|
const Index* codec,
|
|
64
65
|
Index& index,
|
|
65
66
|
const float* weights) {
|
|
67
|
+
train_impl(nx, x_in, codec, NumericType::Float32, index, weights);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
void Clustering::train_ex(
|
|
71
|
+
idx_t nx,
|
|
72
|
+
const void* x_in,
|
|
73
|
+
NumericType numeric_type,
|
|
74
|
+
Index& index,
|
|
75
|
+
const float* weights) {
|
|
76
|
+
if (numeric_type == NumericType::Float32) {
|
|
77
|
+
train(nx, static_cast<const float*>(x_in), index, weights);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
81
|
+
numeric_type == NumericType::Float16,
|
|
82
|
+
"Clustering::train_ex: unsupported numeric type");
|
|
83
|
+
train_impl(
|
|
84
|
+
nx,
|
|
85
|
+
static_cast<const uint8_t*>(x_in),
|
|
86
|
+
nullptr,
|
|
87
|
+
numeric_type,
|
|
88
|
+
index,
|
|
89
|
+
weights);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
void Clustering::train_impl(
|
|
93
|
+
idx_t nx,
|
|
94
|
+
const uint8_t* x_in,
|
|
95
|
+
const Index* codec,
|
|
96
|
+
NumericType numeric_type,
|
|
97
|
+
Index& index,
|
|
98
|
+
const float* weights) {
|
|
99
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
100
|
+
codec || numeric_type == NumericType::Float32 ||
|
|
101
|
+
numeric_type == NumericType::Float16,
|
|
102
|
+
"unsupported numeric type for clustering");
|
|
103
|
+
// packed IEEE binary16 rows, consumed without a codec
|
|
104
|
+
const bool fp16 = !codec && numeric_type == NumericType::Float16;
|
|
105
|
+
// rows that are not fp32 are widened by blocks for the assignment index
|
|
106
|
+
const bool encoded = codec || fp16;
|
|
107
|
+
|
|
66
108
|
FAISS_THROW_IF_NOT_FMT(
|
|
67
109
|
nx >= static_cast<idx_t>(k),
|
|
68
110
|
"Number of training points (%" PRId64
|
|
@@ -70,6 +112,7 @@ void Clustering::train_encoded(
|
|
|
70
112
|
"as large as number of clusters (%zd)",
|
|
71
113
|
nx,
|
|
72
114
|
k);
|
|
115
|
+
FAISS_THROW_IF_NOT_MSG(x_in, "training data must not be null");
|
|
73
116
|
|
|
74
117
|
FAISS_THROW_IF_NOT_FMT(
|
|
75
118
|
(!codec || static_cast<size_t>(codec->d) == d),
|
|
@@ -83,23 +126,46 @@ void Clustering::train_encoded(
|
|
|
83
126
|
int(index.d),
|
|
84
127
|
int(d));
|
|
85
128
|
|
|
129
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
130
|
+
!encoded || decode_block_size > 0,
|
|
131
|
+
"decode_block_size must be positive");
|
|
132
|
+
|
|
86
133
|
double t0 = getmillisecs();
|
|
87
134
|
|
|
88
135
|
if (!codec && check_input_data_for_NaNs) {
|
|
89
136
|
// Check for NaNs in input data. Normally it is the user's
|
|
90
|
-
// responsibility, but it may spare us some hard-to-debug
|
|
91
|
-
|
|
92
|
-
const float* x = reinterpret_cast<const float*>(x_in);
|
|
93
|
-
for (size_t i = 0; i < nx * d; i++) {
|
|
137
|
+
// responsibility, but it may spare us some hard-to-debug reports.
|
|
138
|
+
if (fp16) {
|
|
94
139
|
FAISS_THROW_IF_NOT_MSG(
|
|
95
|
-
|
|
140
|
+
detail::fp16_all_finite(
|
|
141
|
+
nx * d, reinterpret_cast<const uint16_t*>(x_in)),
|
|
142
|
+
"input contains NaN's or Inf's");
|
|
143
|
+
} else {
|
|
144
|
+
const float* x = reinterpret_cast<const float*>(x_in);
|
|
145
|
+
for (size_t i = 0; i < nx * d; i++) {
|
|
146
|
+
FAISS_THROW_IF_NOT_MSG(
|
|
147
|
+
std::isfinite(x[i]), "input contains NaN's or Inf's");
|
|
148
|
+
}
|
|
96
149
|
}
|
|
97
150
|
}
|
|
98
151
|
|
|
99
152
|
const uint8_t* x = x_in;
|
|
100
153
|
std::unique_ptr<uint8_t[]> del1;
|
|
101
154
|
std::unique_ptr<float[]> del3;
|
|
102
|
-
size_t line_size = codec ? codec->sa_code_size()
|
|
155
|
+
size_t line_size = codec ? codec->sa_code_size()
|
|
156
|
+
: fp16 ? sizeof(uint16_t) * d
|
|
157
|
+
: sizeof(float) * d;
|
|
158
|
+
|
|
159
|
+
// widen n consecutive training rows to fp32
|
|
160
|
+
auto decode_rows = [&](size_t n, const uint8_t* rows, float* out) {
|
|
161
|
+
if (codec) {
|
|
162
|
+
codec->sa_decode(n, rows, out);
|
|
163
|
+
} else if (fp16) {
|
|
164
|
+
fp16_to_fp32(n * d, reinterpret_cast<const uint16_t*>(rows), out);
|
|
165
|
+
} else {
|
|
166
|
+
memcpy(out, rows, n * line_size);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
103
169
|
|
|
104
170
|
if (static_cast<size_t>(nx) > k * max_points_per_centroid) {
|
|
105
171
|
uint8_t* x_new;
|
|
@@ -129,11 +195,7 @@ void Clustering::train_encoded(
|
|
|
129
195
|
nx);
|
|
130
196
|
}
|
|
131
197
|
centroids.resize(d * k);
|
|
132
|
-
|
|
133
|
-
memcpy(centroids.data(), x_in, sizeof(float) * d * k);
|
|
134
|
-
} else {
|
|
135
|
-
codec->sa_decode(nx, x_in, centroids.data());
|
|
136
|
-
}
|
|
198
|
+
decode_rows(k, x_in, centroids.data());
|
|
137
199
|
|
|
138
200
|
// one fake iteration...
|
|
139
201
|
ClusteringIterationStats stats = {0.0, 0.0, 0.0, 1.0, 0};
|
|
@@ -153,9 +215,8 @@ void Clustering::train_encoded(
|
|
|
153
215
|
k,
|
|
154
216
|
nredo,
|
|
155
217
|
niter);
|
|
156
|
-
if (
|
|
157
|
-
printf("Input data encoded in %zd bytes per vector\n",
|
|
158
|
-
codec->sa_code_size());
|
|
218
|
+
if (encoded) {
|
|
219
|
+
printf("Input data encoded in %zd bytes per vector\n", line_size);
|
|
159
220
|
}
|
|
160
221
|
}
|
|
161
222
|
|
|
@@ -191,8 +252,10 @@ void Clustering::train_encoded(
|
|
|
191
252
|
// initialize seed
|
|
192
253
|
const uint64_t actual_seed = detail::get_actual_rng_seed(seed);
|
|
193
254
|
|
|
194
|
-
// temporary buffer to decode vectors during the optimization
|
|
195
|
-
std::vector<float> decode_buffer(
|
|
255
|
+
// temporary buffer to decode codec-encoded vectors during the optimization
|
|
256
|
+
std::vector<float> decode_buffer(
|
|
257
|
+
codec ? d * std::min(static_cast<size_t>(nx), decode_block_size)
|
|
258
|
+
: 0);
|
|
196
259
|
|
|
197
260
|
for (int redo = 0; redo < nredo; redo++) {
|
|
198
261
|
if (verbose && nredo > 1) {
|
|
@@ -210,41 +273,44 @@ void Clustering::train_encoded(
|
|
|
210
273
|
std::vector<int> perm(nx);
|
|
211
274
|
rand_perm(perm.data(), nx, actual_seed + 1 + redo * 15486557L);
|
|
212
275
|
for (size_t i = 0; i < k_to_init; i++) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
} else {
|
|
218
|
-
codec->sa_decode(
|
|
219
|
-
1,
|
|
220
|
-
x + perm[n_input_centroids + i] * line_size,
|
|
221
|
-
centroids.data() + (n_input_centroids + i) * d);
|
|
222
|
-
}
|
|
276
|
+
decode_rows(
|
|
277
|
+
1,
|
|
278
|
+
x + perm[n_input_centroids + i] * line_size,
|
|
279
|
+
centroids.data() + (n_input_centroids + i) * d);
|
|
223
280
|
}
|
|
224
281
|
} else {
|
|
225
|
-
// For k-means++ and AFK-MC², we need all vectors decoded
|
|
226
|
-
const float* x_float = nullptr;
|
|
227
|
-
std::vector<float> x_decoded;
|
|
228
|
-
|
|
229
|
-
if (!codec) {
|
|
230
|
-
x_float = reinterpret_cast<const float*>(x);
|
|
231
|
-
} else {
|
|
232
|
-
// Decode all vectors for initialization
|
|
233
|
-
x_decoded.resize(nx * d);
|
|
234
|
-
codec->sa_decode(nx, x, x_decoded.data());
|
|
235
|
-
x_float = x_decoded.data();
|
|
236
|
-
}
|
|
237
|
-
|
|
238
282
|
ClusteringInitialization initializer(d, k_to_init);
|
|
239
283
|
initializer.method = init_method;
|
|
240
284
|
initializer.seed = actual_seed + 1 + redo * 15486557L;
|
|
241
285
|
initializer.afkmc2_chain_length = afkmc2_chain_length;
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
286
|
+
|
|
287
|
+
if (fp16) {
|
|
288
|
+
detail::init_centroids_fp16(
|
|
289
|
+
initializer,
|
|
290
|
+
nx,
|
|
291
|
+
reinterpret_cast<const uint16_t*>(x),
|
|
292
|
+
centroids.data() + n_input_centroids * d,
|
|
293
|
+
n_input_centroids,
|
|
294
|
+
n_input_centroids > 0 ? centroids.data() : nullptr);
|
|
295
|
+
} else {
|
|
296
|
+
const float* x_float = nullptr;
|
|
297
|
+
std::vector<float> x_decoded;
|
|
298
|
+
|
|
299
|
+
if (!encoded) {
|
|
300
|
+
x_float = reinterpret_cast<const float*>(x);
|
|
301
|
+
} else {
|
|
302
|
+
x_decoded.resize(nx * d);
|
|
303
|
+
decode_rows(nx, x, x_decoded.data());
|
|
304
|
+
x_float = x_decoded.data();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
initializer.init_centroids(
|
|
308
|
+
nx,
|
|
309
|
+
x_float,
|
|
310
|
+
centroids.data() + n_input_centroids * d,
|
|
311
|
+
n_input_centroids,
|
|
312
|
+
n_input_centroids > 0 ? centroids.data() : nullptr);
|
|
313
|
+
}
|
|
248
314
|
}
|
|
249
315
|
}
|
|
250
316
|
|
|
@@ -268,7 +334,7 @@ void Clustering::train_encoded(
|
|
|
268
334
|
for (int i = 0; i < niter; i++) {
|
|
269
335
|
double t0s = getmillisecs();
|
|
270
336
|
|
|
271
|
-
if (!
|
|
337
|
+
if (!encoded) {
|
|
272
338
|
index.search(
|
|
273
339
|
nx,
|
|
274
340
|
reinterpret_cast<const float*>(x),
|
|
@@ -277,15 +343,26 @@ void Clustering::train_encoded(
|
|
|
277
343
|
assign.get());
|
|
278
344
|
} else {
|
|
279
345
|
// search by blocks of decode_block_size vectors
|
|
280
|
-
size_t code_size = codec->sa_code_size();
|
|
281
346
|
for (size_t i0 = 0; i0 < static_cast<size_t>(nx);
|
|
282
347
|
i0 += decode_block_size) {
|
|
283
348
|
size_t i1 = i0 + decode_block_size;
|
|
284
349
|
if (i1 > static_cast<size_t>(nx)) {
|
|
285
350
|
i1 = nx;
|
|
286
351
|
}
|
|
287
|
-
|
|
288
|
-
|
|
352
|
+
if (fp16) {
|
|
353
|
+
// the index consumes fp16 queries itself (natively
|
|
354
|
+
// if it can, see Index::search_ex)
|
|
355
|
+
index.search_ex(
|
|
356
|
+
i1 - i0,
|
|
357
|
+
x + line_size * i0,
|
|
358
|
+
NumericType::Float16,
|
|
359
|
+
1,
|
|
360
|
+
dis.get() + i0,
|
|
361
|
+
assign.get() + i0);
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
decode_rows(
|
|
365
|
+
i1 - i0, x + line_size * i0, decode_buffer.data());
|
|
289
366
|
index.search(
|
|
290
367
|
i1 - i0,
|
|
291
368
|
decode_buffer.data(),
|
|
@@ -308,17 +385,30 @@ void Clustering::train_encoded(
|
|
|
308
385
|
std::vector<float> hassign(k);
|
|
309
386
|
|
|
310
387
|
size_t k_frozen = frozen_centroids ? n_input_centroids : 0;
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
388
|
+
if (fp16) {
|
|
389
|
+
detail::compute_centroids_fp16(
|
|
390
|
+
d,
|
|
391
|
+
k,
|
|
392
|
+
nx,
|
|
393
|
+
k_frozen,
|
|
394
|
+
reinterpret_cast<const uint16_t*>(x),
|
|
395
|
+
assign.get(),
|
|
396
|
+
weights,
|
|
397
|
+
hassign.data(),
|
|
398
|
+
centroids.data());
|
|
399
|
+
} else {
|
|
400
|
+
detail::compute_centroids(
|
|
401
|
+
d,
|
|
402
|
+
k,
|
|
403
|
+
nx,
|
|
404
|
+
k_frozen,
|
|
405
|
+
x,
|
|
406
|
+
codec,
|
|
407
|
+
assign.get(),
|
|
408
|
+
weights,
|
|
409
|
+
hassign.data(),
|
|
410
|
+
centroids.data());
|
|
411
|
+
}
|
|
322
412
|
|
|
323
413
|
int nsplit = detail::split_clusters(
|
|
324
414
|
d, k, nx, k_frozen, hassign.data(), centroids.data());
|
|
@@ -148,11 +148,40 @@ struct Clustering : ClusteringParameters {
|
|
|
148
148
|
Index& index,
|
|
149
149
|
const float* weights = nullptr);
|
|
150
150
|
|
|
151
|
+
/** run k-means on vectors of the given numeric type
|
|
152
|
+
*
|
|
153
|
+
* Float32 is the same as train(). Float16 takes packed IEEE binary16
|
|
154
|
+
* vectors (n * d uint16_t) and runs k-means natively on them: the NaN
|
|
155
|
+
* check, subsampling, initialization and centroid updates read the fp16
|
|
156
|
+
* rows directly, and the assignment step passes blocks of at most
|
|
157
|
+
* decode_block_size fp16 rows to index.search_ex(Float16). Indexes with a
|
|
158
|
+
* native fp16 search consume them directly; the Index::search_ex default
|
|
159
|
+
* widens them block by block. There is no fp32 copy of the training set,
|
|
160
|
+
* unless init_method needs one. Centroids are fp32.
|
|
161
|
+
*/
|
|
162
|
+
void train_ex(
|
|
163
|
+
idx_t n,
|
|
164
|
+
const void* x,
|
|
165
|
+
NumericType numeric_type,
|
|
166
|
+
Index& index,
|
|
167
|
+
const float* weights = nullptr);
|
|
168
|
+
|
|
151
169
|
/// Post-process the centroids after each centroid update.
|
|
152
170
|
/// includes optional L2 normalization and nearest integer rounding
|
|
153
171
|
void post_process_centroids();
|
|
154
172
|
|
|
155
173
|
virtual ~Clustering() {}
|
|
174
|
+
|
|
175
|
+
protected:
|
|
176
|
+
/// k-means on rows encoded by `codec` or, if codec is null, stored as
|
|
177
|
+
/// `numeric_type` (Float32 or Float16)
|
|
178
|
+
void train_impl(
|
|
179
|
+
idx_t nx,
|
|
180
|
+
const uint8_t* x_in,
|
|
181
|
+
const Index* codec,
|
|
182
|
+
NumericType numeric_type,
|
|
183
|
+
Index& index,
|
|
184
|
+
const float* weights);
|
|
156
185
|
};
|
|
157
186
|
|
|
158
187
|
/** Exact 1D clustering algorithm
|