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
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
#include <faiss/impl/scalar_quantizer/similarities.h>
|
|
16
16
|
#include <faiss/utils/distances.h>
|
|
17
17
|
#include <faiss/utils/rabitq_simd.h>
|
|
18
|
+
#include <faiss/utils/simd_impl/masked_sum.h>
|
|
18
19
|
#include <limits>
|
|
19
20
|
|
|
20
21
|
#ifndef THE_LEVEL_TO_DISPATCH
|
|
@@ -36,35 +37,6 @@ template <SIMDLevel SL0>
|
|
|
36
37
|
inline constexpr SIMDLevel rabitq_popcount_level =
|
|
37
38
|
SL0 == SIMDLevel::AVX512_SPR ? SIMDLevel::AVX512_VPOPCNT : SL0;
|
|
38
39
|
|
|
39
|
-
/*******************************************************************
|
|
40
|
-
* TurboQuant SIMD kernel: masked_sum
|
|
41
|
-
* Compute sum of arr[j] where bit j of the bitmask is set.
|
|
42
|
-
* NONE specialization is inline; AVX2/AVX512/NEON specializations
|
|
43
|
-
* live in sq-avx2.cpp / sq-avx512.cpp / sq-neon.cpp.
|
|
44
|
-
*******************************************************************/
|
|
45
|
-
|
|
46
|
-
template <SIMDLevel SL0>
|
|
47
|
-
float turboq_masked_sum(const float* arr, const uint8_t* bits, size_t d);
|
|
48
|
-
|
|
49
|
-
template <>
|
|
50
|
-
inline float turboq_masked_sum<SIMDLevel::NONE>(
|
|
51
|
-
const float* arr,
|
|
52
|
-
const uint8_t* bits,
|
|
53
|
-
size_t d) {
|
|
54
|
-
float result = 0;
|
|
55
|
-
for (size_t byte_idx = 0; byte_idx < (d + 7) / 8; byte_idx++) {
|
|
56
|
-
uint8_t b = bits[byte_idx];
|
|
57
|
-
size_t base = byte_idx * 8;
|
|
58
|
-
size_t end = std::min(base + 8, d);
|
|
59
|
-
for (size_t j = base; j < end; j++) {
|
|
60
|
-
if (b & (1 << (j - base))) {
|
|
61
|
-
result += arr[j];
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return result;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
40
|
/*******************************************************************
|
|
69
41
|
* Full TurboQuant DC — lives here because it needs both
|
|
70
42
|
* quantizers.h (QuantizerTurboQuantFull, SQTurboQFactors) and
|
|
@@ -73,8 +45,10 @@ inline float turboq_masked_sum<SIMDLevel::NONE>(
|
|
|
73
45
|
*******************************************************************/
|
|
74
46
|
template <int NBits, class Similarity, SIMDLevel SL2>
|
|
75
47
|
struct DCTurboQuantFull : ScalarQuantizer::TurboQuantRefine::DistanceComputer {
|
|
48
|
+
// The AVX-512 levels share the AVX512 masked_sum specialization.
|
|
49
|
+
static constexpr SIMDLevel SUM_LEVEL = simd512_level_selector<SL2>::value;
|
|
76
50
|
using Sim = Similarity;
|
|
77
|
-
QuantizerTurboQuantFull<NBits,
|
|
51
|
+
QuantizerTurboQuantFull<NBits, SL2> quant;
|
|
78
52
|
std::vector<float> query;
|
|
79
53
|
std::vector<float> query_proj;
|
|
80
54
|
float q_norm_sq = 0;
|
|
@@ -277,19 +251,19 @@ struct DCTurboQuantFull : ScalarQuantizer::TurboQuantRefine::DistanceComputer {
|
|
|
277
251
|
mse_popcnt_scale * static_cast<float>(pop);
|
|
278
252
|
} else {
|
|
279
253
|
// Float path: masked accumulation
|
|
280
|
-
float pos_sum =
|
|
254
|
+
float pos_sum = masked_sum<SUM_LEVEL>(query.data(), code, d);
|
|
281
255
|
mse_dot = scaled_c0 * total_q_sum + delta_centroid * pos_sum;
|
|
282
256
|
}
|
|
283
257
|
} else if constexpr (NBits == 3) {
|
|
284
258
|
// 2-bit MSE: decompose into 3 masked sums over bit-planes.
|
|
285
259
|
size_t pb = quant.mse_plane_bytes;
|
|
286
|
-
float s0 =
|
|
287
|
-
float s1 =
|
|
260
|
+
float s0 = masked_sum<SUM_LEVEL>(query.data(), code, d);
|
|
261
|
+
float s1 = masked_sum<SUM_LEVEL>(query.data(), code + pb, d);
|
|
288
262
|
for (size_t i = 0; i < pb; i++) {
|
|
289
263
|
scratch_and[i] = code[i] & code[pb + i];
|
|
290
264
|
}
|
|
291
265
|
float s01 =
|
|
292
|
-
|
|
266
|
+
masked_sum<SUM_LEVEL>(query.data(), scratch_and.data(), d);
|
|
293
267
|
mse_dot = mse_multi_base + mse_coeff_s0 * s0 + mse_coeff_s1 * s1 +
|
|
294
268
|
mse_coeff_s01 * s01;
|
|
295
269
|
} else {
|
|
@@ -336,7 +310,7 @@ struct DCTurboQuantFull : ScalarQuantizer::TurboQuantRefine::DistanceComputer {
|
|
|
336
310
|
qjl_dot = qjl_coeff * gamma * (2.0f * pos_sum - total_qproj_sum);
|
|
337
311
|
} else {
|
|
338
312
|
float pos_sum =
|
|
339
|
-
|
|
313
|
+
masked_sum<SUM_LEVEL>(query_proj.data(), qjl_code, d);
|
|
340
314
|
qjl_dot = qjl_coeff * gamma * (2.0f * pos_sum - total_qproj_sum);
|
|
341
315
|
}
|
|
342
316
|
|
|
@@ -373,6 +347,50 @@ constexpr bool is_dimension_compatible(size_t d) {
|
|
|
373
347
|
}
|
|
374
348
|
}
|
|
375
349
|
|
|
350
|
+
// Distance computers and scanners. At AVX512 the 16-bit float codecs decode
|
|
351
|
+
// a partial last block, so they take any d.
|
|
352
|
+
template <SIMDLevel SL2>
|
|
353
|
+
constexpr bool is_dimension_compatible(
|
|
354
|
+
size_t d,
|
|
355
|
+
ScalarQuantizer::QuantizerType qtype) {
|
|
356
|
+
return (SL2 == SIMDLevel::AVX512 &&
|
|
357
|
+
(qtype == ScalarQuantizer::QT_fp16 ||
|
|
358
|
+
qtype == ScalarQuantizer::QT_bf16)) ||
|
|
359
|
+
is_dimension_compatible<SL2>(d);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/// Calls f with the DCTemplate type for (Quantizer, Sim, SL2) and d. The
|
|
363
|
+
/// 16-bit float quantizers and the QT_8bit inner product use it. Four
|
|
364
|
+
/// accumulators per code hide the FMA latency at a large d. At a small d their
|
|
365
|
+
/// reduction costs more than it saves. At AVX512 they are faster only on AMD
|
|
366
|
+
/// (SIMDConfig::sq_avx512_4_accumulators).
|
|
367
|
+
template <class Quantizer, class Sim, SIMDLevel SL2, class F>
|
|
368
|
+
auto with_dc_template(size_t d, F f) {
|
|
369
|
+
if constexpr (SL2 == SIMDLevel::AVX2 || SL2 == SIMDLevel::AVX512) {
|
|
370
|
+
if (d >= 384 &&
|
|
371
|
+
(SL2 == SIMDLevel::AVX2 || SIMDConfig::sq_avx512_4_accumulators)) {
|
|
372
|
+
return f.template
|
|
373
|
+
operator()<DCTemplate<Quantizer, Sim, SL2, true>>();
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return f.template operator()<DCTemplate<Quantizer, Sim, SL2>>();
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/// with_dc_template for QT_8bit. Only its inner product has a four-accumulator
|
|
380
|
+
/// loop.
|
|
381
|
+
template <class Sim, SIMDLevel SL2, class F>
|
|
382
|
+
auto with_8bit_dc_template(size_t d, F f) {
|
|
383
|
+
using Quantizer = QuantizerTemplate<
|
|
384
|
+
Codec8bit<SL2>,
|
|
385
|
+
QuantizerTemplateScaling::NON_UNIFORM,
|
|
386
|
+
SL2>;
|
|
387
|
+
if constexpr (Sim::metric_type == METRIC_INNER_PRODUCT) {
|
|
388
|
+
return with_dc_template<Quantizer, Sim, SL2>(d, f);
|
|
389
|
+
} else {
|
|
390
|
+
return f.template operator()<DCTemplate<Quantizer, Sim, SL2>>();
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
376
394
|
/*******************************************************************
|
|
377
395
|
* sq_select_quantizer: the big switch returning SQuantizer*
|
|
378
396
|
*******************************************************************/
|
|
@@ -487,10 +505,13 @@ SQDistanceComputer* select_distance_computer_body(
|
|
|
487
505
|
const std::vector<float>& trained) {
|
|
488
506
|
// Return nullptr for incompatible dimensions in SIMD cases
|
|
489
507
|
if constexpr (SL2 != SIMDLevel::NONE) {
|
|
490
|
-
if (!is_dimension_compatible<SL2>(d)) {
|
|
508
|
+
if (!is_dimension_compatible<SL2>(d, qtype)) {
|
|
491
509
|
return nullptr;
|
|
492
510
|
}
|
|
493
511
|
}
|
|
512
|
+
auto new_dc = [&]<class DC>() -> SQDistanceComputer* {
|
|
513
|
+
return new DC(d, trained);
|
|
514
|
+
};
|
|
494
515
|
switch (qtype) {
|
|
495
516
|
case ScalarQuantizer::QT_8bit_uniform:
|
|
496
517
|
return new DCTemplate<
|
|
@@ -511,13 +532,7 @@ SQDistanceComputer* select_distance_computer_body(
|
|
|
511
532
|
SL2>(d, trained);
|
|
512
533
|
|
|
513
534
|
case ScalarQuantizer::QT_8bit:
|
|
514
|
-
return
|
|
515
|
-
QuantizerTemplate<
|
|
516
|
-
Codec8bit<SL2>,
|
|
517
|
-
QuantizerTemplateScaling::NON_UNIFORM,
|
|
518
|
-
SL2>,
|
|
519
|
-
Sim,
|
|
520
|
-
SL2>(d, trained);
|
|
535
|
+
return with_8bit_dc_template<Sim, SL2>(d, new_dc);
|
|
521
536
|
|
|
522
537
|
case ScalarQuantizer::QT_6bit:
|
|
523
538
|
return new DCTemplate<
|
|
@@ -538,10 +553,10 @@ SQDistanceComputer* select_distance_computer_body(
|
|
|
538
553
|
SL2>(d, trained);
|
|
539
554
|
|
|
540
555
|
case ScalarQuantizer::QT_fp16:
|
|
541
|
-
return
|
|
556
|
+
return with_dc_template<QuantizerFP16<SL2>, Sim, SL2>(d, new_dc);
|
|
542
557
|
|
|
543
558
|
case ScalarQuantizer::QT_bf16:
|
|
544
|
-
return
|
|
559
|
+
return with_dc_template<QuantizerBF16<SL2>, Sim, SL2>(d, new_dc);
|
|
545
560
|
|
|
546
561
|
case ScalarQuantizer::QT_8bit_direct:
|
|
547
562
|
if constexpr (is_avx512_family<SL2>) {
|
|
@@ -705,7 +720,7 @@ InvertedListScanner* sq_select_InvertedListScanner<THE_LEVEL_TO_DISPATCH>(
|
|
|
705
720
|
[&]<SIMDLevel SL2, class Similarity>() -> InvertedListScanner* {
|
|
706
721
|
// Return nullptr for incompatible dimensions in SIMD cases
|
|
707
722
|
if constexpr (SL2 != SIMDLevel::NONE) {
|
|
708
|
-
if (!is_dimension_compatible<SL2>(d)) {
|
|
723
|
+
if (!is_dimension_compatible<SL2>(d, qtype)) {
|
|
709
724
|
return nullptr;
|
|
710
725
|
}
|
|
711
726
|
}
|
|
@@ -727,13 +742,7 @@ InvertedListScanner* sq_select_InvertedListScanner<THE_LEVEL_TO_DISPATCH>(
|
|
|
727
742
|
Similarity,
|
|
728
743
|
SL2>>();
|
|
729
744
|
case ScalarQuantizer::QT_8bit:
|
|
730
|
-
return
|
|
731
|
-
QuantizerTemplate<
|
|
732
|
-
Codec8bit<SL2>,
|
|
733
|
-
QuantizerTemplateScaling::NON_UNIFORM,
|
|
734
|
-
SL2>,
|
|
735
|
-
Similarity,
|
|
736
|
-
SL2>>();
|
|
745
|
+
return with_8bit_dc_template<Similarity, SL2>(d, scan);
|
|
737
746
|
case ScalarQuantizer::QT_4bit:
|
|
738
747
|
return scan.template operator()<DCTemplate<
|
|
739
748
|
QuantizerTemplate<
|
|
@@ -751,11 +760,11 @@ InvertedListScanner* sq_select_InvertedListScanner<THE_LEVEL_TO_DISPATCH>(
|
|
|
751
760
|
Similarity,
|
|
752
761
|
SL2>>();
|
|
753
762
|
case ScalarQuantizer::QT_fp16:
|
|
754
|
-
return
|
|
755
|
-
|
|
763
|
+
return with_dc_template<QuantizerFP16<SL2>, Similarity, SL2>(
|
|
764
|
+
d, scan);
|
|
756
765
|
case ScalarQuantizer::QT_bf16:
|
|
757
|
-
return
|
|
758
|
-
|
|
766
|
+
return with_dc_template<QuantizerBF16<SL2>, Similarity, SL2>(
|
|
767
|
+
d, scan);
|
|
759
768
|
case ScalarQuantizer::QT_8bit_direct:
|
|
760
769
|
if constexpr (is_avx512_family<SL2>) {
|
|
761
770
|
if (d % 32 == 0) {
|
|
@@ -5,11 +5,8 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
#ifdef COMPILE_SIMD_ARM_NEON
|
|
9
|
-
|
|
10
8
|
#include <faiss/impl/simdlib/simdlib_neon.h>
|
|
11
9
|
|
|
12
|
-
#include <algorithm>
|
|
13
10
|
#include <cstring>
|
|
14
11
|
|
|
15
12
|
#include <faiss/impl/scalar_quantizer/codecs.h>
|
|
@@ -17,6 +14,7 @@
|
|
|
17
14
|
#include <faiss/impl/scalar_quantizer/quantizers.h>
|
|
18
15
|
#include <faiss/impl/scalar_quantizer/scanners.h>
|
|
19
16
|
#include <faiss/impl/scalar_quantizer/similarities.h>
|
|
17
|
+
#include <faiss/impl/scalar_quantizer/sq8_coefficients.h>
|
|
20
18
|
|
|
21
19
|
namespace faiss {
|
|
22
20
|
|
|
@@ -105,14 +103,15 @@ template <>
|
|
|
105
103
|
struct Codec8bit<SIMDLevel::ARM_NEON> : Codec8bit<SIMDLevel::NONE> {
|
|
106
104
|
static FAISS_ALWAYS_INLINE simd8float32
|
|
107
105
|
decode_8_components(const uint8_t* code, size_t i) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
106
|
+
const uint16x8_t c16 = vmovl_u8(vld1_u8(code + i));
|
|
107
|
+
const float32x4_t lo = vcvtq_f32_u32(vmovl_u16(vget_low_u16(c16)));
|
|
108
|
+
const float32x4_t hi = vcvtq_f32_u32(vmovl_u16(vget_high_u16(c16)));
|
|
109
|
+
const float32x4_t one_255 = vdupq_n_f32(1.f / 255.f);
|
|
110
|
+
const float32x4_t half_one_255 = vdupq_n_f32(0.5f / 255.f);
|
|
111
|
+
return simd8float32(
|
|
112
|
+
float32x4x2_t{
|
|
113
|
+
vfmaq_f32(half_one_255, lo, one_255),
|
|
114
|
+
vfmaq_f32(half_one_255, hi, one_255)});
|
|
116
115
|
}
|
|
117
116
|
};
|
|
118
117
|
|
|
@@ -618,6 +617,97 @@ struct DCTemplate<Quantizer, Similarity, SIMDLevel::ARM_NEON>
|
|
|
618
617
|
}
|
|
619
618
|
};
|
|
620
619
|
|
|
620
|
+
// QT_8bit + L2. With a, rmin from sq8_coefficients.h and e = q - rmin, each
|
|
621
|
+
// term is (e_i - a_i * c_i)^2: one fmls and one fmla per 4 dims, instead of
|
|
622
|
+
// separate codec, vmin/vdiff, sub, mul and add steps.
|
|
623
|
+
template <>
|
|
624
|
+
struct DCTemplate<
|
|
625
|
+
QuantizerTemplate<
|
|
626
|
+
Codec8bit<SIMDLevel::ARM_NEON>,
|
|
627
|
+
QuantizerTemplateScaling::NON_UNIFORM,
|
|
628
|
+
SIMDLevel::ARM_NEON>,
|
|
629
|
+
SimilarityL2<SIMDLevel::ARM_NEON>,
|
|
630
|
+
SIMDLevel::ARM_NEON> : SQDistanceComputer {
|
|
631
|
+
using Sim = SimilarityL2<SIMDLevel::ARM_NEON>;
|
|
632
|
+
|
|
633
|
+
size_t d;
|
|
634
|
+
std::vector<float> a, rmin, e;
|
|
635
|
+
|
|
636
|
+
DCTemplate(size_t d_in, const std::vector<float>& trained)
|
|
637
|
+
: d(d_in), a(d_in), rmin(d_in), e(d_in) {
|
|
638
|
+
assert(d % 8 == 0);
|
|
639
|
+
sq8::make_coefficients(trained.data(), d, a.data(), rmin.data());
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
void set_query(const float* x) final {
|
|
643
|
+
q = x;
|
|
644
|
+
for (size_t i = 0; i < d; i++) {
|
|
645
|
+
e[i] = x[i] - rmin[i];
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// Each code has its own accumulators, so the batched results equal the
|
|
650
|
+
// single-code ones bit for bit.
|
|
651
|
+
template <size_t N>
|
|
652
|
+
FAISS_ALWAYS_INLINE void l2(
|
|
653
|
+
const uint8_t* const (&codes)[N],
|
|
654
|
+
float (&dis)[N]) const {
|
|
655
|
+
float32x4_t acc[N][2] = {};
|
|
656
|
+
for (size_t i = 0; i < d; i += 8) {
|
|
657
|
+
const float32x4_t a0 = vld1q_f32(a.data() + i);
|
|
658
|
+
const float32x4_t a1 = vld1q_f32(a.data() + i + 4);
|
|
659
|
+
const float32x4_t e0 = vld1q_f32(e.data() + i);
|
|
660
|
+
const float32x4_t e1 = vld1q_f32(e.data() + i + 4);
|
|
661
|
+
for (size_t n = 0; n < N; n++) {
|
|
662
|
+
const uint16x8_t c16 = vmovl_u8(vld1_u8(codes[n] + i));
|
|
663
|
+
const float32x4_t t0 = vfmsq_f32(
|
|
664
|
+
e0, a0, vcvtq_f32_u32(vmovl_u16(vget_low_u16(c16))));
|
|
665
|
+
const float32x4_t t1 =
|
|
666
|
+
vfmsq_f32(e1, a1, vcvtq_f32_u32(vmovl_high_u16(c16)));
|
|
667
|
+
acc[n][0] = vfmaq_f32(acc[n][0], t0, t0);
|
|
668
|
+
acc[n][1] = vfmaq_f32(acc[n][1], t1, t1);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
for (size_t n = 0; n < N; n++) {
|
|
672
|
+
dis[n] = vaddvq_f32(vaddq_f32(acc[n][0], acc[n][1]));
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
float query_to_code(const uint8_t* code) const final {
|
|
677
|
+
float dis[1];
|
|
678
|
+
l2<1>({code}, dis);
|
|
679
|
+
return dis[0];
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
void query_to_codes_batch_4(
|
|
683
|
+
const uint8_t* code_0,
|
|
684
|
+
const uint8_t* code_1,
|
|
685
|
+
const uint8_t* code_2,
|
|
686
|
+
const uint8_t* code_3,
|
|
687
|
+
float& dis0,
|
|
688
|
+
float& dis1,
|
|
689
|
+
float& dis2,
|
|
690
|
+
float& dis3) const final {
|
|
691
|
+
float dis[4];
|
|
692
|
+
l2<4>({code_0, code_1, code_2, code_3}, dis);
|
|
693
|
+
dis0 = dis[0];
|
|
694
|
+
dis1 = dis[1];
|
|
695
|
+
dis2 = dis[2];
|
|
696
|
+
dis3 = dis[3];
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
float symmetric_dis(idx_t i, idx_t j) override {
|
|
700
|
+
const uint8_t* c1 = codes + i * code_size;
|
|
701
|
+
const uint8_t* c2 = codes + j * code_size;
|
|
702
|
+
float accu = 0;
|
|
703
|
+
for (size_t k = 0; k < d; k++) {
|
|
704
|
+
const float diff = a[k] * float(int(c1[k]) - int(c2[k]));
|
|
705
|
+
accu += diff * diff;
|
|
706
|
+
}
|
|
707
|
+
return accu;
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
|
|
621
711
|
// Byte-domain kernels for QT_8bit_direct{,_signed}. The dispatch only
|
|
622
712
|
// selects them when d % 16 == 0, so no loop needs a tail.
|
|
623
713
|
|
|
@@ -762,93 +852,8 @@ struct DistanceComputerByteSigned<Similarity, SIMDLevel::ARM_NEON>
|
|
|
762
852
|
}
|
|
763
853
|
};
|
|
764
854
|
|
|
765
|
-
/**********************************************************
|
|
766
|
-
* TurboQuant masked_sum NEON specialization (scalar fallback)
|
|
767
|
-
**********************************************************/
|
|
768
|
-
|
|
769
|
-
template <SIMDLevel SL0>
|
|
770
|
-
float turboq_masked_sum(const float* arr, const uint8_t* bits, size_t d);
|
|
771
|
-
|
|
772
|
-
template <>
|
|
773
|
-
float turboq_masked_sum<SIMDLevel::ARM_NEON>(
|
|
774
|
-
const float* arr,
|
|
775
|
-
const uint8_t* bits,
|
|
776
|
-
size_t d) {
|
|
777
|
-
float result = 0;
|
|
778
|
-
for (size_t byte_idx = 0; byte_idx < (d + 7) / 8; byte_idx++) {
|
|
779
|
-
uint8_t b = bits[byte_idx];
|
|
780
|
-
size_t base = byte_idx * 8;
|
|
781
|
-
size_t end = std::min(base + 8, d);
|
|
782
|
-
for (size_t j = base; j < end; j++) {
|
|
783
|
-
if (b & (1 << (j - base))) {
|
|
784
|
-
result += arr[j];
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
return result;
|
|
789
|
-
}
|
|
790
|
-
|
|
791
855
|
} // namespace scalar_quantizer
|
|
792
856
|
} // namespace faiss
|
|
793
857
|
|
|
794
858
|
#define THE_LEVEL_TO_DISPATCH SIMDLevel::ARM_NEON
|
|
795
859
|
#include <faiss/impl/scalar_quantizer/sq-dispatch.h>
|
|
796
|
-
|
|
797
|
-
#ifdef COMPILE_SIMD_ARM_SVE
|
|
798
|
-
|
|
799
|
-
// ARM_SVE: SVE is a superset of NEON. Forward to the NEON implementation
|
|
800
|
-
// until a dedicated SVE specialization is written.
|
|
801
|
-
|
|
802
|
-
namespace faiss {
|
|
803
|
-
namespace scalar_quantizer {
|
|
804
|
-
|
|
805
|
-
// NOLINTNEXTLINE(facebook-hte-MisplacedTemplateSpecialization)
|
|
806
|
-
template <>
|
|
807
|
-
ScalarQuantizer::SQuantizer* sq_select_quantizer<SIMDLevel::ARM_SVE>(
|
|
808
|
-
QuantizerType qtype,
|
|
809
|
-
size_t d,
|
|
810
|
-
const std::vector<float>& trained) {
|
|
811
|
-
return sq_select_quantizer<SIMDLevel::ARM_NEON>(qtype, d, trained);
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
// NOLINTNEXTLINE(facebook-hte-MisplacedTemplateSpecialization)
|
|
815
|
-
template <>
|
|
816
|
-
SQDistanceComputer* sq_select_distance_computer<SIMDLevel::ARM_SVE>(
|
|
817
|
-
MetricType metric,
|
|
818
|
-
ScalarQuantizer::QuantizerType qtype,
|
|
819
|
-
size_t d,
|
|
820
|
-
const std::vector<float>& trained) {
|
|
821
|
-
return sq_select_distance_computer<SIMDLevel::ARM_NEON>(
|
|
822
|
-
metric, qtype, d, trained);
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
// NOLINTNEXTLINE(facebook-hte-MisplacedTemplateSpecialization)
|
|
826
|
-
template <>
|
|
827
|
-
InvertedListScanner* sq_select_InvertedListScanner<SIMDLevel::ARM_SVE>(
|
|
828
|
-
QuantizerType qtype,
|
|
829
|
-
MetricType mt,
|
|
830
|
-
size_t d,
|
|
831
|
-
size_t code_size,
|
|
832
|
-
const std::vector<float>& trained,
|
|
833
|
-
const Index* quantizer,
|
|
834
|
-
bool store_pairs,
|
|
835
|
-
const IDSelector* sel,
|
|
836
|
-
bool by_residual) {
|
|
837
|
-
return sq_select_InvertedListScanner<SIMDLevel::ARM_NEON>(
|
|
838
|
-
qtype,
|
|
839
|
-
mt,
|
|
840
|
-
d,
|
|
841
|
-
code_size,
|
|
842
|
-
trained,
|
|
843
|
-
quantizer,
|
|
844
|
-
store_pairs,
|
|
845
|
-
sel,
|
|
846
|
-
by_residual);
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
} // namespace scalar_quantizer
|
|
850
|
-
} // namespace faiss
|
|
851
|
-
|
|
852
|
-
#endif // COMPILE_SIMD_ARM_SVE
|
|
853
|
-
|
|
854
|
-
#endif // COMPILE_SIMD_ARM_NEON
|