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,232 @@
|
|
|
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 <algorithm>
|
|
11
|
+
#include <cstring>
|
|
12
|
+
|
|
13
|
+
#include <faiss/impl/ScalarQuantizer.h>
|
|
14
|
+
#include <faiss/utils/hamming.h>
|
|
15
|
+
|
|
16
|
+
/** Helpers shared by IndexSQFastScan and IndexIVFSQFastScan.
|
|
17
|
+
*
|
|
18
|
+
* Both re-quantise a higher-precision scalar quantizer down to 4-bit nibbles
|
|
19
|
+
* for the SIMD scan and keep the original codes to rerank with, so the
|
|
20
|
+
* classification of quantizer types and the nibble packing have to agree
|
|
21
|
+
* between them.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
namespace faiss {
|
|
25
|
+
namespace sq_fastscan {
|
|
26
|
+
|
|
27
|
+
inline size_t roundup(size_t a, size_t b) {
|
|
28
|
+
return (a + b - 1) / b * b;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
inline bool is_native_4bit(ScalarQuantizer::QuantizerType qtype) {
|
|
32
|
+
return qtype == ScalarQuantizer::QT_4bit ||
|
|
33
|
+
qtype == ScalarQuantizer::QT_4bit_uniform;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
inline bool needs_rerank(ScalarQuantizer::QuantizerType qtype) {
|
|
37
|
+
return qtype == ScalarQuantizer::QT_6bit ||
|
|
38
|
+
qtype == ScalarQuantizer::QT_8bit ||
|
|
39
|
+
qtype == ScalarQuantizer::QT_8bit_uniform ||
|
|
40
|
+
qtype == ScalarQuantizer::QT_8bit_direct ||
|
|
41
|
+
qtype == ScalarQuantizer::QT_8bit_direct_signed;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
inline bool is_fallback(ScalarQuantizer::QuantizerType qtype) {
|
|
45
|
+
return !is_native_4bit(qtype) && !needs_rerank(qtype);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
inline bool is_uniform_range(ScalarQuantizer::QuantizerType qtype) {
|
|
49
|
+
return qtype == ScalarQuantizer::QT_8bit_uniform ||
|
|
50
|
+
qtype == ScalarQuantizer::QT_8bit_direct ||
|
|
51
|
+
qtype == ScalarQuantizer::QT_8bit_direct_signed;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
inline void get_uniform_range(
|
|
55
|
+
const ScalarQuantizer& sq,
|
|
56
|
+
float& vmin,
|
|
57
|
+
float& vdiff) {
|
|
58
|
+
if (sq.qtype == ScalarQuantizer::QT_8bit_direct) {
|
|
59
|
+
vmin = 0;
|
|
60
|
+
vdiff = 255;
|
|
61
|
+
} else if (sq.qtype == ScalarQuantizer::QT_8bit_direct_signed) {
|
|
62
|
+
vmin = -128;
|
|
63
|
+
vdiff = 255;
|
|
64
|
+
} else {
|
|
65
|
+
vmin = sq.trained[0];
|
|
66
|
+
vdiff = sq.trained[1];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/// Bits per dimension the quantizer stores.
|
|
71
|
+
inline int sq_bits(ScalarQuantizer::QuantizerType qtype) {
|
|
72
|
+
if (qtype == ScalarQuantizer::QT_6bit) {
|
|
73
|
+
return 6;
|
|
74
|
+
}
|
|
75
|
+
return is_native_4bit(qtype) ? 4 : 8;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/// Bits left over once the scan has taken its 4. Zero for a native 4-bit
|
|
79
|
+
/// code, which needs no rerank and therefore stores nothing extra.
|
|
80
|
+
inline int sq_rerank_bits(ScalarQuantizer::QuantizerType qtype) {
|
|
81
|
+
return sq_bits(qtype) - 4;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/// Bytes per vector needed to hold the leftover bits of every dimension.
|
|
85
|
+
inline size_t sq_rerank_size(int d, ScalarQuantizer::QuantizerType qtype) {
|
|
86
|
+
const int bits = sq_rerank_bits(qtype);
|
|
87
|
+
return bits > 0 ? (size_t(d) * bits + 7) / 8 : 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// The code for one value at the quantizer's own width.
|
|
91
|
+
inline int sq_code_of(float x, float vmin, float vdiff, int bits) {
|
|
92
|
+
const int maxv = (1 << bits) - 1;
|
|
93
|
+
const float f = (vdiff > 0) ? (x - vmin) / vdiff : 0.0f;
|
|
94
|
+
return std::min(maxv, std::max(0, int(f * float(maxv))));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/// Per-dimension range of the trained quantizer, resolved once for a batch.
|
|
98
|
+
struct SQRanges {
|
|
99
|
+
SQRanges(const ScalarQuantizer& sq, int d)
|
|
100
|
+
: uniform(is_uniform_range(sq.qtype) ||
|
|
101
|
+
sq.qtype == ScalarQuantizer::QT_4bit_uniform) {
|
|
102
|
+
if (uniform) {
|
|
103
|
+
get_uniform_range(sq, vmin_s, vdiff_s);
|
|
104
|
+
} else {
|
|
105
|
+
vmin_arr = sq.trained.data();
|
|
106
|
+
vdiff_arr = sq.trained.data() + d;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
float vmin(int m) const {
|
|
111
|
+
return uniform ? vmin_s : vmin_arr[m];
|
|
112
|
+
}
|
|
113
|
+
float vdiff(int m) const {
|
|
114
|
+
return uniform ? vdiff_s : vdiff_arr[m];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const bool uniform;
|
|
118
|
+
const float* vmin_arr = nullptr;
|
|
119
|
+
const float* vdiff_arr = nullptr;
|
|
120
|
+
float vmin_s = 0, vdiff_s = 0;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/** Split each code into the top 4 bits the SIMD kernel scans and the rest,
|
|
124
|
+
* which rerank keeps. `hi` is packed two dimensions per byte as
|
|
125
|
+
* pq4_pack_codes expects. `lo` is bit-packed at `bits - 4` per dimension.
|
|
126
|
+
* Total width is the quantizer's own, not that width plus 4.
|
|
127
|
+
*/
|
|
128
|
+
inline void float_to_split_codes(
|
|
129
|
+
const float* x,
|
|
130
|
+
uint8_t* hi,
|
|
131
|
+
uint8_t* lo,
|
|
132
|
+
idx_t n,
|
|
133
|
+
int d,
|
|
134
|
+
size_t M2,
|
|
135
|
+
const ScalarQuantizer& sq) {
|
|
136
|
+
const int bits = sq_bits(sq.qtype);
|
|
137
|
+
const int lo_bits = bits - 4;
|
|
138
|
+
const size_t hi_stride = M2 / 2;
|
|
139
|
+
const size_t lo_stride = sq_rerank_size(d, sq.qtype);
|
|
140
|
+
const SQRanges ranges(sq, d);
|
|
141
|
+
for (idx_t i = 0; i < n; i++) {
|
|
142
|
+
const float* xi = x + i * d;
|
|
143
|
+
uint8_t* hdst = hi + i * hi_stride;
|
|
144
|
+
memset(hdst, 0, hi_stride);
|
|
145
|
+
uint8_t* ldst = lo + i * lo_stride;
|
|
146
|
+
memset(ldst, 0, lo_stride);
|
|
147
|
+
BitstringWriter bsw(ldst, lo_stride);
|
|
148
|
+
for (int m = 0; m < d; m++) {
|
|
149
|
+
const int code =
|
|
150
|
+
sq_code_of(xi[m], ranges.vmin(m), ranges.vdiff(m), bits);
|
|
151
|
+
const int h = code >> lo_bits;
|
|
152
|
+
hdst[m / 2] |= (m & 1) ? uint8_t(h << 4) : uint8_t(h);
|
|
153
|
+
bsw.write(code & ((1 << lo_bits) - 1), lo_bits);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/// Rebuild the code values of one vector from its two halves.
|
|
159
|
+
inline void split_to_codes(
|
|
160
|
+
const uint8_t* hi,
|
|
161
|
+
const uint8_t* lo,
|
|
162
|
+
int d,
|
|
163
|
+
ScalarQuantizer::QuantizerType qtype,
|
|
164
|
+
int* codes_out) {
|
|
165
|
+
const int lo_bits = sq_rerank_bits(qtype);
|
|
166
|
+
BitstringReader bsr(lo, sq_rerank_size(d, qtype));
|
|
167
|
+
for (int m = 0; m < d; m++) {
|
|
168
|
+
const int h = (m & 1) ? (hi[m / 2] >> 4) : (hi[m / 2] & 0xF);
|
|
169
|
+
codes_out[m] = (h << lo_bits) | int(bsr.read(lo_bits));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
inline void float_to_4bit_nibbles(
|
|
174
|
+
const float* x,
|
|
175
|
+
uint8_t* nibbles,
|
|
176
|
+
idx_t n,
|
|
177
|
+
int d,
|
|
178
|
+
int M2,
|
|
179
|
+
const ScalarQuantizer& sq) {
|
|
180
|
+
const bool is_uniform = is_uniform_range(sq.qtype) ||
|
|
181
|
+
sq.qtype == ScalarQuantizer::QT_4bit_uniform;
|
|
182
|
+
const float* vmin_arr = nullptr;
|
|
183
|
+
const float* vdiff_arr = nullptr;
|
|
184
|
+
float vmin_s = 0, inv_vdiff_s = 0;
|
|
185
|
+
|
|
186
|
+
if (is_uniform) {
|
|
187
|
+
float vdiff;
|
|
188
|
+
get_uniform_range(sq, vmin_s, vdiff);
|
|
189
|
+
inv_vdiff_s = (vdiff > 0) ? (1.0f / vdiff) : 0;
|
|
190
|
+
} else {
|
|
191
|
+
vmin_arr = sq.trained.data();
|
|
192
|
+
vdiff_arr = sq.trained.data() + d;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const int half = M2 / 2;
|
|
196
|
+
for (idx_t i = 0; i < n; i++) {
|
|
197
|
+
const float* xi = x + i * d;
|
|
198
|
+
uint8_t* dst = nibbles + i * half;
|
|
199
|
+
memset(dst, 0, half);
|
|
200
|
+
for (int m = 0; m + 1 < d; m += 2) {
|
|
201
|
+
float f0, f1;
|
|
202
|
+
if (is_uniform) {
|
|
203
|
+
f0 = (xi[m] - vmin_s) * inv_vdiff_s;
|
|
204
|
+
f1 = (xi[m + 1] - vmin_s) * inv_vdiff_s;
|
|
205
|
+
} else {
|
|
206
|
+
f0 = (vdiff_arr[m] > 0) ? (xi[m] - vmin_arr[m]) / vdiff_arr[m]
|
|
207
|
+
: 0;
|
|
208
|
+
f1 = (vdiff_arr[m + 1] > 0)
|
|
209
|
+
? (xi[m + 1] - vmin_arr[m + 1]) / vdiff_arr[m + 1]
|
|
210
|
+
: 0;
|
|
211
|
+
}
|
|
212
|
+
uint8_t lo = (uint8_t)std::min(15, std::max(0, (int)(f0 * 15.0f)));
|
|
213
|
+
uint8_t hi = (uint8_t)std::min(15, std::max(0, (int)(f1 * 15.0f)));
|
|
214
|
+
dst[m / 2] = lo | (hi << 4);
|
|
215
|
+
}
|
|
216
|
+
if (d & 1) {
|
|
217
|
+
float f;
|
|
218
|
+
if (is_uniform) {
|
|
219
|
+
f = (xi[d - 1] - vmin_s) * inv_vdiff_s;
|
|
220
|
+
} else {
|
|
221
|
+
f = (vdiff_arr[d - 1] > 0)
|
|
222
|
+
? (xi[d - 1] - vmin_arr[d - 1]) / vdiff_arr[d - 1]
|
|
223
|
+
: 0;
|
|
224
|
+
}
|
|
225
|
+
dst[(d - 1) / 2] =
|
|
226
|
+
(uint8_t)std::min(15, std::max(0, (int)(f * 15.0f)));
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
} // namespace sq_fastscan
|
|
232
|
+
} // namespace faiss
|
|
@@ -35,17 +35,20 @@
|
|
|
35
35
|
#include <faiss/IndexIVFPQR.h>
|
|
36
36
|
#include <faiss/IndexIVFRaBitQ.h>
|
|
37
37
|
#include <faiss/IndexIVFRaBitQFastScan.h>
|
|
38
|
+
#include <faiss/IndexIVFSQFastScan.h>
|
|
38
39
|
#include <faiss/IndexIVFSpectralHash.h>
|
|
39
40
|
#include <faiss/IndexLSH.h>
|
|
40
41
|
#include <faiss/IndexLattice.h>
|
|
41
42
|
#include <faiss/IndexNSG.h>
|
|
42
43
|
#include <faiss/IndexPQ.h>
|
|
43
44
|
#include <faiss/IndexPQFastScan.h>
|
|
45
|
+
#include <faiss/IndexPiPNN.h>
|
|
44
46
|
#include <faiss/IndexPreTransform.h>
|
|
45
47
|
#include <faiss/IndexRaBitQ.h>
|
|
46
48
|
#include <faiss/IndexRaBitQFastScan.h>
|
|
47
49
|
#include <faiss/IndexRefine.h>
|
|
48
50
|
#include <faiss/IndexRowwiseMinMax.h>
|
|
51
|
+
#include <faiss/IndexSQFastScan.h>
|
|
49
52
|
#include <faiss/IndexScalarQuantizer.h>
|
|
50
53
|
#include <faiss/VectorTransform.h>
|
|
51
54
|
|
|
@@ -177,6 +180,11 @@ std::map<std::string, ScalarQuantizer::QuantizerType> sq_types = {
|
|
|
177
180
|
};
|
|
178
181
|
const std::string sq_pattern =
|
|
179
182
|
"(SQ0|SQ4|SQ8|SQ6|SQfp16|SQbf16|SQ8_direct_signed|SQ8_direct|SQtqmse1|SQtqmse2|SQtqmse3|SQtqmse4|SQtqmse8|SQtq2|SQtq3|SQtq4|SQtq5)";
|
|
183
|
+
const std::string sq_fs_pattern =
|
|
184
|
+
"(SQ4|SQ6|SQ8|SQ8_direct_signed|SQ8_direct)fs(_[0-9]+)?";
|
|
185
|
+
// All SQ types with "fs" suffix for IndexIVFSQFastScan, optional _bbs
|
|
186
|
+
const std::string ivf_sq_fs_pattern =
|
|
187
|
+
"(SQ0|SQ4|SQ8|SQ6|SQfp16|SQbf16|SQ8_direct_signed|SQ8_direct|SQtqmse1|SQtqmse2|SQtqmse3|SQtqmse4|SQtqmse8|SQtq2|SQtq3|SQtq4|SQtq5)fs(_[0-9]+)?";
|
|
180
188
|
|
|
181
189
|
std::map<std::string, AdditiveQuantizer::Search_type_t> aq_search_type = {
|
|
182
190
|
{"_Nfloat", AdditiveQuantizer::ST_norm_float},
|
|
@@ -310,6 +318,11 @@ Index* parse_coarse_quantizer(
|
|
|
310
318
|
int R = std::stoi(sm[2]);
|
|
311
319
|
return new IndexNSGFlat(d, R, mt);
|
|
312
320
|
}
|
|
321
|
+
if (match("IVF([0-9]+[kM]?)_PiPNN([0-9]*)")) {
|
|
322
|
+
nlist = parse_nlist(sm[1].str());
|
|
323
|
+
int R = mres_to_int(sm[2], 64);
|
|
324
|
+
return new IndexPiPNNFlat(d, R, mt);
|
|
325
|
+
}
|
|
313
326
|
#ifdef FAISS_ENABLE_SVS
|
|
314
327
|
if (match("IVF([0-9]+[kM]?)_SVSVamana([0-9]*)(_.+)?")) {
|
|
315
328
|
nlist = parse_nlist(sm[1].str());
|
|
@@ -389,6 +402,17 @@ IndexIVF* parse_IndexIVF(
|
|
|
389
402
|
return new IndexIVFFlatPanorama(
|
|
390
403
|
get_q(), d, nlist, nlevels, mt, own_il, bs);
|
|
391
404
|
}
|
|
405
|
+
if (match(ivf_sq_fs_pattern)) {
|
|
406
|
+
int bbs = mres_to_int(sm[2], 32, 1);
|
|
407
|
+
return new IndexIVFSQFastScan(
|
|
408
|
+
get_q(),
|
|
409
|
+
d,
|
|
410
|
+
nlist,
|
|
411
|
+
sq_types[sm[1].str()],
|
|
412
|
+
mt,
|
|
413
|
+
bbs,
|
|
414
|
+
/*by_residual=*/true);
|
|
415
|
+
}
|
|
392
416
|
if (match(sq_pattern)) {
|
|
393
417
|
return new IndexIVFScalarQuantizer(
|
|
394
418
|
get_q(),
|
|
@@ -637,6 +661,30 @@ IndexNSG* parse_IndexNSG(
|
|
|
637
661
|
return nullptr;
|
|
638
662
|
}
|
|
639
663
|
|
|
664
|
+
/***************************************************************
|
|
665
|
+
* Parse IndexPiPNN
|
|
666
|
+
*/
|
|
667
|
+
|
|
668
|
+
IndexPiPNN* parse_IndexPiPNN(
|
|
669
|
+
const std::string& code_string,
|
|
670
|
+
int d,
|
|
671
|
+
MetricType mt,
|
|
672
|
+
int pipnn_R) {
|
|
673
|
+
std::smatch sm;
|
|
674
|
+
auto match = [&sm, &code_string](const std::string& pattern) {
|
|
675
|
+
return re_match(code_string, pattern, sm);
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
if (match("Flat|")) {
|
|
679
|
+
return new IndexPiPNNFlat(d, pipnn_R, mt);
|
|
680
|
+
}
|
|
681
|
+
if (match(sq_pattern)) {
|
|
682
|
+
return new IndexPiPNNSQ(d, sq_types[sm[1].str()], pipnn_R, mt);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
return nullptr;
|
|
686
|
+
}
|
|
687
|
+
|
|
640
688
|
#ifdef FAISS_ENABLE_SVS
|
|
641
689
|
/***************************************************************
|
|
642
690
|
* Parse IndexSVS
|
|
@@ -831,6 +879,12 @@ Index* parse_other_indexes(
|
|
|
831
879
|
return new IndexLattice(d, M, nbit, r2);
|
|
832
880
|
}
|
|
833
881
|
|
|
882
|
+
// IndexSQFastScan (must be checked before IndexScalarQuantizer)
|
|
883
|
+
if (match(sq_fs_pattern)) {
|
|
884
|
+
int bbs = mres_to_int(sm[2], 32, 1);
|
|
885
|
+
return new IndexSQFastScan(d, sq_types[sm[1].str()], metric, bbs);
|
|
886
|
+
}
|
|
887
|
+
|
|
834
888
|
// IndexScalarQuantizer
|
|
835
889
|
if (match(sq_pattern)) {
|
|
836
890
|
return new IndexScalarQuantizer(d, sq_types[description], metric);
|
|
@@ -1156,6 +1210,28 @@ std::unique_ptr<Index> index_factory_sub(
|
|
|
1156
1210
|
return std::unique_ptr<Index>(index);
|
|
1157
1211
|
}
|
|
1158
1212
|
|
|
1213
|
+
// PiPNN variants (separator "," or "_", as for HNSW and NSG)
|
|
1214
|
+
if (re_match(description, "PiPNN([0-9]*)([,_].*)?", sm)) {
|
|
1215
|
+
int pipnn_R = mres_to_int(sm[1], 64);
|
|
1216
|
+
// We also accept empty code string (synonym of Flat)
|
|
1217
|
+
std::string code_string =
|
|
1218
|
+
sm[2].length() > 0 ? sm[2].str().substr(1) : "";
|
|
1219
|
+
if (verbose) {
|
|
1220
|
+
printf("parsing PiPNN string %s code_string=%s pipnn_R=%d\n",
|
|
1221
|
+
description.c_str(),
|
|
1222
|
+
code_string.c_str(),
|
|
1223
|
+
pipnn_R);
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
IndexPiPNN* index = parse_IndexPiPNN(code_string, d, metric, pipnn_R);
|
|
1227
|
+
FAISS_THROW_IF_NOT_FMT(
|
|
1228
|
+
index,
|
|
1229
|
+
"could not parse PiPNN code description %s in %s",
|
|
1230
|
+
code_string.c_str(),
|
|
1231
|
+
description.c_str());
|
|
1232
|
+
return std::unique_ptr<Index>(index);
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1159
1235
|
// IndexRowwiseMinMax, fp32 version
|
|
1160
1236
|
if (description.compare(0, 7, "MinMax,") == 0) {
|
|
1161
1237
|
size_t comma = description.find(',');
|
|
@@ -127,7 +127,9 @@ size_t InvertedLists::copy_subset_to(
|
|
|
127
127
|
} else if (subset_type == SUBSET_TYPE_ID_MOD) {
|
|
128
128
|
for (size_t i = 0; i < n; i++) {
|
|
129
129
|
idx_t id = ids_in[i];
|
|
130
|
-
|
|
130
|
+
// C++ gives a negative remainder, so a plain `id % a1` never
|
|
131
|
+
// matches for a negative id. Fold it into [0, a1) instead.
|
|
132
|
+
if (((id % a1) + a1) % a1 == a2) {
|
|
131
133
|
oivf.add_entry(
|
|
132
134
|
list_no,
|
|
133
135
|
get_single_id(list_no, i),
|
|
@@ -90,8 +90,9 @@ inline svs_runtime::StorageKind to_svs_storage_kind(SVSStorageKind kind) {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
struct IndexSVSVamana : Index {
|
|
93
|
-
|
|
94
|
-
size_t
|
|
93
|
+
// Same defaults as IndexSVSVamana(d, /*degree=*/64).
|
|
94
|
+
size_t graph_max_degree = 64;
|
|
95
|
+
size_t prune_to = 60;
|
|
95
96
|
float alpha = 1.2;
|
|
96
97
|
size_t search_window_size = 10;
|
|
97
98
|
size_t search_buffer_capacity = 10;
|
|
@@ -117,6 +117,8 @@ template <class T, int A = 32>
|
|
|
117
117
|
struct AlignedTable {
|
|
118
118
|
AlignedTableTightAlloc<T, A> tab;
|
|
119
119
|
size_t numel = 0;
|
|
120
|
+
// If true, resize() reallocates only when n is larger than the capacity.
|
|
121
|
+
bool keep_capacity = false;
|
|
120
122
|
|
|
121
123
|
static size_t round_capacity(size_t n) {
|
|
122
124
|
if (n == 0) {
|
|
@@ -141,7 +143,10 @@ struct AlignedTable {
|
|
|
141
143
|
}
|
|
142
144
|
|
|
143
145
|
void resize(size_t n) {
|
|
144
|
-
|
|
146
|
+
const size_t capacity = round_capacity(n);
|
|
147
|
+
if (!keep_capacity || capacity > tab.numel) {
|
|
148
|
+
tab.resize(capacity);
|
|
149
|
+
}
|
|
145
150
|
numel = n;
|
|
146
151
|
}
|
|
147
152
|
|
|
@@ -194,10 +194,11 @@ void merge_knn_results(
|
|
|
194
194
|
const idx_t* I_in = all_labels + i * k;
|
|
195
195
|
int heap_size = 0;
|
|
196
196
|
|
|
197
|
-
// push the first element of each shard (if not -1)
|
|
197
|
+
// push the first element of each shard (if not -1). A caller id
|
|
198
|
+
// may be negative, so only -1 marks a missing result.
|
|
198
199
|
for (long s = 0; s < static_cast<long>(nshard); s++) {
|
|
199
200
|
pointer[s] = 0;
|
|
200
|
-
if (I_in[stride * s]
|
|
201
|
+
if (I_in[stride * s] != -1) {
|
|
201
202
|
heap_push<C>(
|
|
202
203
|
++heap_size,
|
|
203
204
|
heap_vals,
|
|
@@ -221,7 +222,7 @@ void merge_knn_results(
|
|
|
221
222
|
// pop from shard, advance pointer for this shard
|
|
222
223
|
heap_pop<C>(heap_size--, heap_vals, shard_ids);
|
|
223
224
|
p++;
|
|
224
|
-
if (static_cast<size_t>(p) < k && I_in[stride * s + p]
|
|
225
|
+
if (static_cast<size_t>(p) < k && I_in[stride * s + p] != -1) {
|
|
225
226
|
heap_push<C>(
|
|
226
227
|
++heap_size,
|
|
227
228
|
heap_vals,
|
|
@@ -21,19 +21,30 @@ using simd8uint32 = simd8uint32_tpl<SINGLE_SIMD_LEVEL_256>;
|
|
|
21
21
|
using simd16uint16 = simd16uint16_tpl<SINGLE_SIMD_LEVEL_256>;
|
|
22
22
|
|
|
23
23
|
// HeapWithBucketsForHamming32 uses simd8uint32 under the
|
|
24
|
-
// hood.
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
// hood. SL is the SIMD level of the file that uses it, so each level compiles
|
|
25
|
+
// its own copy under its own name.
|
|
26
|
+
|
|
27
|
+
template <
|
|
28
|
+
typename C,
|
|
29
|
+
uint32_t NBUCKETS,
|
|
30
|
+
uint32_t N,
|
|
31
|
+
typename HammingComputerT,
|
|
32
|
+
SIMDLevel SL>
|
|
27
33
|
struct HeapWithBucketsForHamming32 {
|
|
28
34
|
// this case was not implemented yet.
|
|
29
35
|
};
|
|
30
36
|
|
|
31
|
-
template <
|
|
37
|
+
template <
|
|
38
|
+
uint32_t NBUCKETS,
|
|
39
|
+
uint32_t N,
|
|
40
|
+
typename HammingComputerT,
|
|
41
|
+
SIMDLevel SL>
|
|
32
42
|
struct HeapWithBucketsForHamming32<
|
|
33
43
|
CMax<int, int64_t>,
|
|
34
44
|
NBUCKETS,
|
|
35
45
|
N,
|
|
36
|
-
HammingComputerT
|
|
46
|
+
HammingComputerT,
|
|
47
|
+
SL> {
|
|
37
48
|
static constexpr uint32_t NBUCKETS_8 = NBUCKETS / 8;
|
|
38
49
|
static_assert(
|
|
39
50
|
(NBUCKETS) > 0 && ((NBUCKETS % 8) == 0),
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
#include <immintrin.h>
|
|
15
15
|
#endif
|
|
16
16
|
|
|
17
|
+
#if defined(__riscv_vector)
|
|
18
|
+
#include <riscv_vector.h>
|
|
19
|
+
#endif
|
|
20
|
+
|
|
17
21
|
namespace faiss {
|
|
18
22
|
|
|
19
23
|
namespace {
|
|
@@ -38,6 +42,8 @@ inline float decode_bf16(const uint16_t v) {
|
|
|
38
42
|
return fp.as_f32;
|
|
39
43
|
}
|
|
40
44
|
|
|
45
|
+
namespace {
|
|
46
|
+
|
|
41
47
|
inline void encode_bf16_simd(const float* src, uint16_t* dst, size_t n) {
|
|
42
48
|
size_t i = 0;
|
|
43
49
|
#ifdef __AVX512BF16__
|
|
@@ -61,10 +67,40 @@ inline void decode_bf16_simd(const uint16_t* src, float* dst, size_t n) {
|
|
|
61
67
|
w = _mm512_slli_epi32(w, 16);
|
|
62
68
|
_mm512_storeu_ps(dst + i, _mm512_castsi512_ps(w));
|
|
63
69
|
}
|
|
70
|
+
#elif defined(__riscv_vector)
|
|
71
|
+
if (n == 1) {
|
|
72
|
+
dst[0] = decode_bf16(src[0]);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (n < 16) {
|
|
76
|
+
for (; i < n; ++i) {
|
|
77
|
+
dst[i] = decode_bf16(src[i]);
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const size_t vlmax = __riscv_vsetvlmax_e16m1();
|
|
82
|
+
for (; i + vlmax <= n; i += vlmax) {
|
|
83
|
+
vuint16m1_t v = __riscv_vle16_v_u16m1(src + i, vlmax);
|
|
84
|
+
vuint32m2_t w = __riscv_vzext_vf2_u32m2(v, vlmax);
|
|
85
|
+
w = __riscv_vsll_vx_u32m2(w, 16, vlmax);
|
|
86
|
+
__riscv_vse32_v_f32m2(
|
|
87
|
+
dst + i, __riscv_vreinterpret_v_u32m2_f32m2(w), vlmax);
|
|
88
|
+
}
|
|
89
|
+
if (i < n) {
|
|
90
|
+
const size_t vl = __riscv_vsetvl_e16m1(n - i);
|
|
91
|
+
vuint16m1_t v = __riscv_vle16_v_u16m1(src + i, vl);
|
|
92
|
+
vuint32m2_t w = __riscv_vzext_vf2_u32m2(v, vl);
|
|
93
|
+
w = __riscv_vsll_vx_u32m2(w, 16, vl);
|
|
94
|
+
__riscv_vse32_v_f32m2(
|
|
95
|
+
dst + i, __riscv_vreinterpret_v_u32m2_f32m2(w), vl);
|
|
96
|
+
i += vl;
|
|
97
|
+
}
|
|
64
98
|
#endif
|
|
65
99
|
for (; i < n; i++) {
|
|
66
100
|
dst[i] = decode_bf16(src[i]);
|
|
67
101
|
}
|
|
68
102
|
}
|
|
69
103
|
|
|
104
|
+
} // namespace
|
|
105
|
+
|
|
70
106
|
} // namespace faiss
|