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
|
@@ -7,6 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
+
#include <faiss/impl/scalar_quantizer/codecs.h>
|
|
11
|
+
#include <faiss/impl/scalar_quantizer/distance_computers.h>
|
|
12
|
+
#include <faiss/impl/scalar_quantizer/quantizers.h>
|
|
13
|
+
#include <faiss/impl/scalar_quantizer/similarities.h>
|
|
14
|
+
#include <faiss/impl/scalar_quantizer/sq8_coefficients.h>
|
|
15
|
+
#include <faiss/impl/simdlib/simdlib_avx512.h>
|
|
10
16
|
#include <cstring>
|
|
11
17
|
|
|
12
18
|
namespace faiss {
|
|
@@ -14,11 +20,6 @@ namespace faiss {
|
|
|
14
20
|
namespace scalar_quantizer {
|
|
15
21
|
|
|
16
22
|
using simd16float32 = faiss::simd16float32_tpl<SIMDLevel::AVX512>;
|
|
17
|
-
using simd512bit = faiss::simd512bit_tpl<SIMDLevel::AVX512>;
|
|
18
|
-
|
|
19
|
-
/**********************************************************
|
|
20
|
-
* TurboQuant bit-unpacking helpers
|
|
21
|
-
**********************************************************/
|
|
22
23
|
|
|
23
24
|
namespace {
|
|
24
25
|
|
|
@@ -100,7 +101,7 @@ FAISS_ALWAYS_INLINE __m512i unpack_16x4bit_to_u32(const uint8_t* code, int i) {
|
|
|
100
101
|
**********************************************************/
|
|
101
102
|
|
|
102
103
|
template <>
|
|
103
|
-
struct Codec8bit<
|
|
104
|
+
struct Codec8bit<THE_LEVEL_TO_DISPATCH> : Codec8bit<SIMDLevel::NONE> {
|
|
104
105
|
static FAISS_ALWAYS_INLINE simd16float32
|
|
105
106
|
decode_16_components(const uint8_t* code, size_t i) {
|
|
106
107
|
const __m128i c16 = _mm_loadu_si128((__m128i*)(code + i));
|
|
@@ -113,7 +114,7 @@ struct Codec8bit<SIMDLevel::AVX512> : Codec8bit<SIMDLevel::NONE> {
|
|
|
113
114
|
};
|
|
114
115
|
|
|
115
116
|
template <>
|
|
116
|
-
struct Codec4bit<
|
|
117
|
+
struct Codec4bit<THE_LEVEL_TO_DISPATCH> : Codec4bit<SIMDLevel::NONE> {
|
|
117
118
|
static FAISS_ALWAYS_INLINE simd16float32
|
|
118
119
|
decode_16_components(const uint8_t* code, size_t i) {
|
|
119
120
|
uint64_t c8 = *(uint64_t*)(code + (i >> 1));
|
|
@@ -135,7 +136,7 @@ struct Codec4bit<SIMDLevel::AVX512> : Codec4bit<SIMDLevel::NONE> {
|
|
|
135
136
|
};
|
|
136
137
|
|
|
137
138
|
template <>
|
|
138
|
-
struct Codec6bit<
|
|
139
|
+
struct Codec6bit<THE_LEVEL_TO_DISPATCH> : Codec6bit<SIMDLevel::NONE> {
|
|
139
140
|
static FAISS_ALWAYS_INLINE simd16float32
|
|
140
141
|
decode_16_components(const uint8_t* code, size_t i) {
|
|
141
142
|
// pure AVX512 implementation (not necessarily the fastest).
|
|
@@ -192,7 +193,7 @@ template <class Codec>
|
|
|
192
193
|
struct QuantizerTemplate<
|
|
193
194
|
Codec,
|
|
194
195
|
scalar_quantizer::QuantizerTemplateScaling::UNIFORM,
|
|
195
|
-
|
|
196
|
+
THE_LEVEL_TO_DISPATCH>
|
|
196
197
|
: QuantizerTemplate<
|
|
197
198
|
Codec,
|
|
198
199
|
scalar_quantizer::QuantizerTemplateScaling::UNIFORM,
|
|
@@ -211,13 +212,19 @@ struct QuantizerTemplate<
|
|
|
211
212
|
return simd16float32(_mm512_fmadd_ps(
|
|
212
213
|
xi, _mm512_set1_ps(this->vdiff), _mm512_set1_ps(this->vmin)));
|
|
213
214
|
}
|
|
215
|
+
|
|
216
|
+
/// Raw codec decode without denormalization
|
|
217
|
+
FAISS_ALWAYS_INLINE simd16float32
|
|
218
|
+
decode_16_raw(const uint8_t* code, int i) const {
|
|
219
|
+
return Codec::decode_16_components(code, i);
|
|
220
|
+
}
|
|
214
221
|
};
|
|
215
222
|
|
|
216
223
|
template <class Codec>
|
|
217
224
|
struct QuantizerTemplate<
|
|
218
225
|
Codec,
|
|
219
226
|
scalar_quantizer::QuantizerTemplateScaling::NON_UNIFORM,
|
|
220
|
-
|
|
227
|
+
THE_LEVEL_TO_DISPATCH>
|
|
221
228
|
: QuantizerTemplate<
|
|
222
229
|
Codec,
|
|
223
230
|
scalar_quantizer::QuantizerTemplateScaling::NON_UNIFORM,
|
|
@@ -244,36 +251,83 @@ struct QuantizerTemplate<
|
|
|
244
251
|
* Lloyd-Max scalar quantizer
|
|
245
252
|
**********************************************************/
|
|
246
253
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
254
|
+
// 1-bit Lloyd-Max AVX512: 16 comparisons → 2 bytes via mask compare.
|
|
255
|
+
// NLT_UQ is !(x < b), matching the scalar upper_bound tie-break.
|
|
256
|
+
template <>
|
|
257
|
+
struct QuantizerLloydMax<1, THE_LEVEL_TO_DISPATCH>
|
|
258
|
+
: QuantizerLloydMaxBase<1, THE_LEVEL_TO_DISPATCH> {
|
|
259
|
+
using Base = QuantizerLloydMaxBase<1, THE_LEVEL_TO_DISPATCH>;
|
|
260
|
+
|
|
261
|
+
QuantizerLloydMax(size_t d, const std::vector<float>& trained)
|
|
262
|
+
: Base(d, trained) {
|
|
263
|
+
assert(d % 16 == 0);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
FAISS_ALWAYS_INLINE simd16float32
|
|
267
|
+
reconstruct_16_components(const uint8_t* code, int i) const {
|
|
268
|
+
return simd16float32(_mm512_i32gather_ps(
|
|
269
|
+
unpack_16x1bit_to_u32(code, i),
|
|
270
|
+
this->centroids,
|
|
271
|
+
sizeof(float)));
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
void encode_vector(const float* x, uint8_t* code) const final {
|
|
275
|
+
__m512 boundary = _mm512_set1_ps(this->boundaries[0]);
|
|
276
|
+
for (size_t i = 0; i < this->d; i += 16) {
|
|
277
|
+
__m512 vals = _mm512_loadu_ps(x + i);
|
|
278
|
+
__mmask16 mask = _mm512_cmp_ps_mask(vals, boundary, _CMP_NLT_UQ);
|
|
279
|
+
uint16_t bits = _cvtmask16_u32(mask);
|
|
280
|
+
memcpy(code + i / 8, &bits, sizeof(uint16_t));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
void decode_vector(const uint8_t* code, float* x) const final {
|
|
285
|
+
for (size_t i = 0; i < this->d; i += 16) {
|
|
286
|
+
simd16float32 xi =
|
|
287
|
+
reconstruct_16_components(code, static_cast<int>(i));
|
|
288
|
+
_mm512_storeu_ps(x + i, xi.f);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
};
|
|
272
292
|
|
|
293
|
+
// 2-4 bit Lloyd-Max AVX512: decode via gather, encode stays scalar.
|
|
294
|
+
#define DEFINE_LLOYD_MAX_AVX512_MULTIBIT(NBITS, UNPACK_EXPR) \
|
|
295
|
+
template <> \
|
|
296
|
+
struct QuantizerLloydMax<NBITS, THE_LEVEL_TO_DISPATCH> \
|
|
297
|
+
: QuantizerLloydMaxBase<NBITS, THE_LEVEL_TO_DISPATCH> { \
|
|
298
|
+
using Base = QuantizerLloydMaxBase<NBITS, THE_LEVEL_TO_DISPATCH>; \
|
|
299
|
+
\
|
|
300
|
+
QuantizerLloydMax(size_t d, const std::vector<float>& trained) \
|
|
301
|
+
: Base(d, trained) { \
|
|
302
|
+
assert(d % 16 == 0); \
|
|
303
|
+
} \
|
|
304
|
+
\
|
|
305
|
+
FAISS_ALWAYS_INLINE simd16float32 \
|
|
306
|
+
reconstruct_16_components(const uint8_t* code, int i) const { \
|
|
307
|
+
return simd16float32(_mm512_i32gather_ps( \
|
|
308
|
+
(UNPACK_EXPR), this->centroids, sizeof(float))); \
|
|
309
|
+
} \
|
|
310
|
+
\
|
|
311
|
+
void decode_vector(const uint8_t* code, float* x) const final { \
|
|
312
|
+
for (size_t i = 0; i < this->d; i += 16) { \
|
|
313
|
+
simd16float32 xi = \
|
|
314
|
+
reconstruct_16_components(code, static_cast<int>(i)); \
|
|
315
|
+
_mm512_storeu_ps(x + i, xi.f); \
|
|
316
|
+
} \
|
|
317
|
+
} \
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
DEFINE_LLOYD_MAX_AVX512_MULTIBIT(2, unpack_16x2bit_to_u32(code, i));
|
|
321
|
+
DEFINE_LLOYD_MAX_AVX512_MULTIBIT(3, unpack_16x3bit_to_u32(code, i));
|
|
322
|
+
DEFINE_LLOYD_MAX_AVX512_MULTIBIT(4, unpack_16x4bit_to_u32(code, i));
|
|
323
|
+
|
|
324
|
+
#undef DEFINE_LLOYD_MAX_AVX512_MULTIBIT
|
|
325
|
+
|
|
326
|
+
// 8-bit Lloyd-Max AVX512
|
|
273
327
|
template <>
|
|
274
|
-
struct QuantizerLloydMax<8,
|
|
275
|
-
:
|
|
276
|
-
using Base =
|
|
328
|
+
struct QuantizerLloydMax<8, THE_LEVEL_TO_DISPATCH>
|
|
329
|
+
: QuantizerLloydMaxBase<8, THE_LEVEL_TO_DISPATCH> {
|
|
330
|
+
using Base = QuantizerLloydMaxBase<8, THE_LEVEL_TO_DISPATCH>;
|
|
277
331
|
|
|
278
332
|
QuantizerLloydMax(size_t d, const std::vector<float>& trained)
|
|
279
333
|
: Base(d, trained) {
|
|
@@ -288,6 +342,14 @@ struct QuantizerLloydMax<8, SIMDLevel::AVX512>
|
|
|
288
342
|
return simd16float32(
|
|
289
343
|
_mm512_i32gather_ps(indices, this->centroids, sizeof(float)));
|
|
290
344
|
}
|
|
345
|
+
|
|
346
|
+
void decode_vector(const uint8_t* code, float* x) const final {
|
|
347
|
+
for (size_t i = 0; i < this->d; i += 16) {
|
|
348
|
+
simd16float32 xi =
|
|
349
|
+
reconstruct_16_components(code, static_cast<int>(i));
|
|
350
|
+
_mm512_storeu_ps(x + i, xi.f);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
291
353
|
};
|
|
292
354
|
|
|
293
355
|
/**********************************************************
|
|
@@ -295,17 +357,25 @@ struct QuantizerLloydMax<8, SIMDLevel::AVX512>
|
|
|
295
357
|
**********************************************************/
|
|
296
358
|
|
|
297
359
|
template <>
|
|
298
|
-
struct QuantizerFP16<
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
assert(d % 16 == 0);
|
|
302
|
-
}
|
|
360
|
+
struct QuantizerFP16<THE_LEVEL_TO_DISPATCH>
|
|
361
|
+
: QuantizerFP16Base<THE_LEVEL_TO_DISPATCH> {
|
|
362
|
+
using QuantizerFP16Base<THE_LEVEL_TO_DISPATCH>::QuantizerFP16Base;
|
|
303
363
|
|
|
304
364
|
FAISS_ALWAYS_INLINE simd16float32
|
|
305
365
|
reconstruct_16_components(const uint8_t* code, int i) const {
|
|
306
366
|
__m256i codei = _mm256_loadu_si256((const __m256i*)(code + 2 * i));
|
|
307
367
|
return simd16float32(_mm512_cvtph_ps(codei));
|
|
308
368
|
}
|
|
369
|
+
|
|
370
|
+
/// Components i .. i + 15 selected by mask, the others 0. Reads no byte
|
|
371
|
+
/// past the selected components.
|
|
372
|
+
FAISS_ALWAYS_INLINE simd16float32 reconstruct_16_components_masked(
|
|
373
|
+
const uint8_t* code,
|
|
374
|
+
int i,
|
|
375
|
+
__mmask16 mask) const {
|
|
376
|
+
__m256i codei = _mm256_maskz_loadu_epi16(mask, code + 2 * i);
|
|
377
|
+
return simd16float32(_mm512_cvtph_ps(codei));
|
|
378
|
+
}
|
|
309
379
|
};
|
|
310
380
|
|
|
311
381
|
/**********************************************************
|
|
@@ -313,15 +383,26 @@ struct QuantizerFP16<SIMDLevel::AVX512> : QuantizerFP16<SIMDLevel::NONE> {
|
|
|
313
383
|
**********************************************************/
|
|
314
384
|
|
|
315
385
|
template <>
|
|
316
|
-
struct QuantizerBF16<
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
assert(d % 16 == 0);
|
|
320
|
-
}
|
|
386
|
+
struct QuantizerBF16<THE_LEVEL_TO_DISPATCH>
|
|
387
|
+
: QuantizerBF16Base<THE_LEVEL_TO_DISPATCH> {
|
|
388
|
+
using QuantizerBF16Base<THE_LEVEL_TO_DISPATCH>::QuantizerBF16Base;
|
|
321
389
|
|
|
322
390
|
FAISS_ALWAYS_INLINE simd16float32
|
|
323
391
|
reconstruct_16_components(const uint8_t* code, int i) const {
|
|
324
392
|
__m256i code_256i = _mm256_loadu_si256((const __m256i*)(code + 2 * i));
|
|
393
|
+
return widen(code_256i);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/// Components i .. i + 15 selected by mask, the others 0. Reads no byte
|
|
397
|
+
/// past the selected components.
|
|
398
|
+
FAISS_ALWAYS_INLINE simd16float32 reconstruct_16_components_masked(
|
|
399
|
+
const uint8_t* code,
|
|
400
|
+
int i,
|
|
401
|
+
__mmask16 mask) const {
|
|
402
|
+
return widen(_mm256_maskz_loadu_epi16(mask, code + 2 * i));
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
static FAISS_ALWAYS_INLINE simd16float32 widen(__m256i code_256i) {
|
|
325
406
|
__m512i code_512i = _mm512_cvtepu16_epi32(code_256i);
|
|
326
407
|
code_512i = _mm512_slli_epi32(code_512i, 16);
|
|
327
408
|
return simd16float32(_mm512_castsi512_ps(code_512i));
|
|
@@ -333,10 +414,10 @@ struct QuantizerBF16<SIMDLevel::AVX512> : QuantizerBF16<SIMDLevel::NONE> {
|
|
|
333
414
|
**********************************************************/
|
|
334
415
|
|
|
335
416
|
template <>
|
|
336
|
-
struct Quantizer8bitDirect<
|
|
337
|
-
:
|
|
417
|
+
struct Quantizer8bitDirect<THE_LEVEL_TO_DISPATCH>
|
|
418
|
+
: Quantizer8bitDirectBase<THE_LEVEL_TO_DISPATCH> {
|
|
338
419
|
Quantizer8bitDirect(size_t d, const std::vector<float>& trained)
|
|
339
|
-
:
|
|
420
|
+
: Quantizer8bitDirectBase<THE_LEVEL_TO_DISPATCH>(d, trained) {
|
|
340
421
|
assert(d % 16 == 0);
|
|
341
422
|
}
|
|
342
423
|
|
|
@@ -353,10 +434,10 @@ struct Quantizer8bitDirect<SIMDLevel::AVX512>
|
|
|
353
434
|
**********************************************************/
|
|
354
435
|
|
|
355
436
|
template <>
|
|
356
|
-
struct Quantizer8bitDirectSigned<
|
|
357
|
-
:
|
|
437
|
+
struct Quantizer8bitDirectSigned<THE_LEVEL_TO_DISPATCH>
|
|
438
|
+
: Quantizer8bitDirectSignedBase<THE_LEVEL_TO_DISPATCH> {
|
|
358
439
|
Quantizer8bitDirectSigned(size_t d, const std::vector<float>& trained)
|
|
359
|
-
:
|
|
440
|
+
: Quantizer8bitDirectSignedBase<THE_LEVEL_TO_DISPATCH>(d, trained) {
|
|
360
441
|
assert(d % 16 == 0);
|
|
361
442
|
}
|
|
362
443
|
|
|
@@ -375,9 +456,9 @@ struct Quantizer8bitDirectSigned<SIMDLevel::AVX512>
|
|
|
375
456
|
**********************************************************/
|
|
376
457
|
|
|
377
458
|
template <>
|
|
378
|
-
struct SimilarityL2<
|
|
459
|
+
struct SimilarityL2<THE_LEVEL_TO_DISPATCH> {
|
|
379
460
|
static constexpr int simdwidth = 16;
|
|
380
|
-
static constexpr SIMDLevel simd_level =
|
|
461
|
+
static constexpr SIMDLevel simd_level = THE_LEVEL_TO_DISPATCH;
|
|
381
462
|
static constexpr MetricType metric_type = METRIC_L2;
|
|
382
463
|
|
|
383
464
|
const float *y, *yi;
|
|
@@ -405,15 +486,38 @@ struct SimilarityL2<SIMDLevel::AVX512> {
|
|
|
405
486
|
accu16 = accu16 + tmp * tmp;
|
|
406
487
|
}
|
|
407
488
|
|
|
489
|
+
FAISS_ALWAYS_INLINE void fmadd_16_components_2(
|
|
490
|
+
simd16float32 x,
|
|
491
|
+
simd16float32 y_2) {
|
|
492
|
+
simd16float32 tmp = y_2 - x;
|
|
493
|
+
accu16 = fmadd(tmp, tmp, accu16);
|
|
494
|
+
}
|
|
495
|
+
|
|
408
496
|
FAISS_ALWAYS_INLINE float result_16() {
|
|
409
497
|
return horizontal_add(accu16);
|
|
410
498
|
}
|
|
499
|
+
|
|
500
|
+
static void adjust_query_for_raw_decode(
|
|
501
|
+
const float* x,
|
|
502
|
+
float* q_adj,
|
|
503
|
+
size_t d,
|
|
504
|
+
float vmin,
|
|
505
|
+
float vdiff,
|
|
506
|
+
float& scale_factor,
|
|
507
|
+
float& bias) {
|
|
508
|
+
float inv_vdiff = (vdiff != 0) ? 1.0f / vdiff : 0.0f;
|
|
509
|
+
for (size_t i = 0; i < d; i++) {
|
|
510
|
+
q_adj[i] = (x[i] - vmin) * inv_vdiff;
|
|
511
|
+
}
|
|
512
|
+
scale_factor = vdiff * vdiff;
|
|
513
|
+
bias = 0;
|
|
514
|
+
}
|
|
411
515
|
};
|
|
412
516
|
|
|
413
517
|
template <>
|
|
414
|
-
struct SimilarityIP<
|
|
518
|
+
struct SimilarityIP<THE_LEVEL_TO_DISPATCH> {
|
|
415
519
|
static constexpr int simdwidth = 16;
|
|
416
|
-
static constexpr SIMDLevel simd_level =
|
|
520
|
+
static constexpr SIMDLevel simd_level = THE_LEVEL_TO_DISPATCH;
|
|
417
521
|
static constexpr MetricType metric_type = METRIC_INNER_PRODUCT;
|
|
418
522
|
|
|
419
523
|
const float *y, *yi;
|
|
@@ -439,32 +543,144 @@ struct SimilarityIP<SIMDLevel::AVX512> {
|
|
|
439
543
|
accu16 = accu16 + x1 * x2;
|
|
440
544
|
}
|
|
441
545
|
|
|
546
|
+
FAISS_ALWAYS_INLINE void fmadd_16_components_2(
|
|
547
|
+
simd16float32 x1,
|
|
548
|
+
simd16float32 x2) {
|
|
549
|
+
accu16 = fmadd(x1, x2, accu16);
|
|
550
|
+
}
|
|
551
|
+
|
|
442
552
|
FAISS_ALWAYS_INLINE float result_16() {
|
|
443
553
|
return horizontal_add(accu16);
|
|
444
554
|
}
|
|
555
|
+
|
|
556
|
+
static void adjust_query_for_raw_decode(
|
|
557
|
+
const float* x,
|
|
558
|
+
float* q_adj,
|
|
559
|
+
size_t d,
|
|
560
|
+
float vmin,
|
|
561
|
+
float vdiff,
|
|
562
|
+
float& scale_factor,
|
|
563
|
+
float& bias) {
|
|
564
|
+
float sum_q = 0;
|
|
565
|
+
for (size_t i = 0; i < d; i++) {
|
|
566
|
+
q_adj[i] = x[i];
|
|
567
|
+
sum_q += x[i];
|
|
568
|
+
}
|
|
569
|
+
scale_factor = vdiff;
|
|
570
|
+
bias = vmin * sum_q;
|
|
571
|
+
}
|
|
445
572
|
};
|
|
446
573
|
|
|
447
574
|
/**********************************************************
|
|
448
575
|
* Distance Computers
|
|
449
576
|
**********************************************************/
|
|
450
577
|
|
|
451
|
-
|
|
452
|
-
|
|
578
|
+
namespace {
|
|
579
|
+
|
|
580
|
+
/// 16 lanes to 4: lanes j, j + 4, j + 8 and j + 12 summed into lane j.
|
|
581
|
+
FAISS_ALWAYS_INLINE __m128 reduce_16_to_4(__m512 a) {
|
|
582
|
+
const __m256 hi =
|
|
583
|
+
_mm256_castpd_ps(_mm512_extractf64x4_pd(_mm512_castps_pd(a), 1));
|
|
584
|
+
const __m256 s8 = _mm256_add_ps(_mm512_castps512_ps256(a), hi);
|
|
585
|
+
return _mm_add_ps(_mm256_castps256_ps128(s8), _mm256_extractf128_ps(s8, 1));
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
} // namespace
|
|
589
|
+
|
|
590
|
+
template <class Quantizer, class Similarity, bool four_acc>
|
|
591
|
+
struct DCTemplate<Quantizer, Similarity, THE_LEVEL_TO_DISPATCH, four_acc>
|
|
453
592
|
: SQDistanceComputer {
|
|
454
593
|
using Sim = Similarity;
|
|
455
594
|
|
|
456
595
|
Quantizer quant;
|
|
457
596
|
|
|
597
|
+
// Pre-adjusted query buffer for uniform quantizers
|
|
598
|
+
std::vector<float> q_adj;
|
|
599
|
+
float scale_factor = 0;
|
|
600
|
+
float bias = 0;
|
|
601
|
+
|
|
602
|
+
static constexpr bool has_decode_raw() {
|
|
603
|
+
return requires(const Quantizer& q, const uint8_t* c, int i) {
|
|
604
|
+
{ q.decode_16_raw(c, i) };
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
|
|
458
608
|
DCTemplate(size_t d, const std::vector<float>& trained)
|
|
459
|
-
: quant(d, trained) {
|
|
609
|
+
: quant(d, trained) {
|
|
610
|
+
if constexpr (has_decode_raw()) {
|
|
611
|
+
q_adj.resize(d);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/// The quantizer can decode a partial block, so d need not be a
|
|
616
|
+
/// multiple of 16.
|
|
617
|
+
static constexpr bool has_masked_tail() {
|
|
618
|
+
return requires(const Quantizer& q, const uint8_t* c) {
|
|
619
|
+
{ q.reconstruct_16_components_masked(c, 0, __mmask16(0)) };
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/// Adds the partial last block, from component i, of a d that is not a
|
|
624
|
+
/// multiple of 16.
|
|
625
|
+
FAISS_ALWAYS_INLINE void add_tail(
|
|
626
|
+
Similarity& sim,
|
|
627
|
+
const float* x,
|
|
628
|
+
const uint8_t* code,
|
|
629
|
+
size_t i) const {
|
|
630
|
+
if constexpr (has_masked_tail()) {
|
|
631
|
+
if (i < quant.d) {
|
|
632
|
+
const __mmask16 mask = __mmask16((1u << (quant.d - i)) - 1);
|
|
633
|
+
sim.fmadd_16_components_2(
|
|
634
|
+
quant.reconstruct_16_components_masked(
|
|
635
|
+
code, static_cast<int>(i), mask),
|
|
636
|
+
simd16float32(_mm512_maskz_loadu_ps(mask, x + i)));
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/// Similarity terms of one code with four accumulators.
|
|
642
|
+
FAISS_ALWAYS_INLINE __m512
|
|
643
|
+
accumulate_4(const float* x, const uint8_t* code) const {
|
|
644
|
+
struct Acc : Similarity {
|
|
645
|
+
Acc() : Similarity(nullptr) {}
|
|
646
|
+
};
|
|
647
|
+
Acc s[4];
|
|
648
|
+
for (int j = 0; j < 4; j++) {
|
|
649
|
+
s[j].begin_16();
|
|
650
|
+
}
|
|
651
|
+
const size_t d = quant.d;
|
|
652
|
+
size_t i = 0;
|
|
653
|
+
for (; i + 64 <= d; i += 64) {
|
|
654
|
+
for (int j = 0; j < 4; j++) {
|
|
655
|
+
s[j].fmadd_16_components_2(
|
|
656
|
+
quant.reconstruct_16_components(
|
|
657
|
+
code, static_cast<int>(i + 16 * j)),
|
|
658
|
+
simd16float32(x + i + 16 * j));
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
for (; i + 16 <= d; i += 16) {
|
|
662
|
+
s[0].fmadd_16_components_2(
|
|
663
|
+
quant.reconstruct_16_components(code, static_cast<int>(i)),
|
|
664
|
+
simd16float32(x + i));
|
|
665
|
+
}
|
|
666
|
+
add_tail(s[0], x, code, i);
|
|
667
|
+
return _mm512_add_ps(
|
|
668
|
+
_mm512_add_ps(s[0].accu16.f, s[1].accu16.f),
|
|
669
|
+
_mm512_add_ps(s[2].accu16.f, s[3].accu16.f));
|
|
670
|
+
}
|
|
460
671
|
|
|
461
672
|
float compute_distance(const float* x, const uint8_t* code) const {
|
|
673
|
+
if constexpr (four_acc) {
|
|
674
|
+
return reduce_4(reduce_16_to_4(accumulate_4(x, code)));
|
|
675
|
+
}
|
|
462
676
|
Similarity sim(x);
|
|
463
677
|
sim.begin_16();
|
|
464
|
-
|
|
678
|
+
const size_t d16 = quant.d & ~size_t(15);
|
|
679
|
+
for (size_t i = 0; i < d16; i += 16) {
|
|
465
680
|
simd16float32 xi = quant.reconstruct_16_components(code, i);
|
|
466
681
|
sim.add_16_components(xi);
|
|
467
682
|
}
|
|
683
|
+
add_tail(sim, x, code, d16);
|
|
468
684
|
return sim.result_16();
|
|
469
685
|
}
|
|
470
686
|
|
|
@@ -472,16 +688,46 @@ struct DCTemplate<Quantizer, Similarity, SIMDLevel::AVX512>
|
|
|
472
688
|
const {
|
|
473
689
|
Similarity sim(nullptr);
|
|
474
690
|
sim.begin_16();
|
|
475
|
-
|
|
691
|
+
const size_t d16 = quant.d & ~size_t(15);
|
|
692
|
+
for (size_t i = 0; i < d16; i += 16) {
|
|
476
693
|
simd16float32 x1 = quant.reconstruct_16_components(code1, i);
|
|
477
694
|
simd16float32 x2 = quant.reconstruct_16_components(code2, i);
|
|
478
695
|
sim.add_16_components_2(x1, x2);
|
|
479
696
|
}
|
|
697
|
+
if constexpr (has_masked_tail()) {
|
|
698
|
+
if (d16 < quant.d) {
|
|
699
|
+
const __mmask16 mask = __mmask16((1u << (quant.d - d16)) - 1);
|
|
700
|
+
const int i = static_cast<int>(d16);
|
|
701
|
+
sim.add_16_components_2(
|
|
702
|
+
quant.reconstruct_16_components_masked(code1, i, mask),
|
|
703
|
+
quant.reconstruct_16_components_masked(code2, i, mask));
|
|
704
|
+
}
|
|
705
|
+
}
|
|
480
706
|
return sim.result_16();
|
|
481
707
|
}
|
|
482
708
|
|
|
483
709
|
void set_query(const float* x) final {
|
|
484
710
|
q = x;
|
|
711
|
+
if constexpr (has_decode_raw()) {
|
|
712
|
+
Sim::adjust_query_for_raw_decode(
|
|
713
|
+
x,
|
|
714
|
+
q_adj.data(),
|
|
715
|
+
quant.d,
|
|
716
|
+
quant.vmin,
|
|
717
|
+
quant.vdiff,
|
|
718
|
+
scale_factor,
|
|
719
|
+
bias);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
float query_to_code_predecoded(const uint8_t* code) const {
|
|
724
|
+
Similarity sim(q_adj.data());
|
|
725
|
+
sim.begin_16();
|
|
726
|
+
for (size_t i = 0; i < quant.d; i += 16) {
|
|
727
|
+
simd16float32 xi = quant.decode_16_raw(code, i);
|
|
728
|
+
sim.add_16_components(xi);
|
|
729
|
+
}
|
|
730
|
+
return bias + scale_factor * sim.result_16();
|
|
485
731
|
}
|
|
486
732
|
|
|
487
733
|
float symmetric_dis(idx_t i, idx_t j) override {
|
|
@@ -490,64 +736,197 @@ struct DCTemplate<Quantizer, Similarity, SIMDLevel::AVX512>
|
|
|
490
736
|
}
|
|
491
737
|
|
|
492
738
|
float query_to_code(const uint8_t* code) const final {
|
|
493
|
-
|
|
739
|
+
if constexpr (has_decode_raw()) {
|
|
740
|
+
return query_to_code_predecoded(code);
|
|
741
|
+
} else {
|
|
742
|
+
return compute_distance(q, code);
|
|
743
|
+
}
|
|
494
744
|
}
|
|
495
|
-
};
|
|
496
745
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
746
|
+
void query_to_codes_batch_4(
|
|
747
|
+
const uint8_t* code_0,
|
|
748
|
+
const uint8_t* code_1,
|
|
749
|
+
const uint8_t* code_2,
|
|
750
|
+
const uint8_t* code_3,
|
|
751
|
+
float& dis0,
|
|
752
|
+
float& dis1,
|
|
753
|
+
float& dis2,
|
|
754
|
+
float& dis3) const final {
|
|
755
|
+
if constexpr (four_acc) {
|
|
756
|
+
alignas(16) float dis[4];
|
|
757
|
+
_mm_store_ps(
|
|
758
|
+
dis,
|
|
759
|
+
reduce_4x4(
|
|
760
|
+
reduce_16_to_4(accumulate_4(q, code_0)),
|
|
761
|
+
reduce_16_to_4(accumulate_4(q, code_1)),
|
|
762
|
+
reduce_16_to_4(accumulate_4(q, code_2)),
|
|
763
|
+
reduce_16_to_4(accumulate_4(q, code_3))));
|
|
764
|
+
dis0 = dis[0];
|
|
765
|
+
dis1 = dis[1];
|
|
766
|
+
dis2 = dis[2];
|
|
767
|
+
dis3 = dis[3];
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
Similarity sim0(q);
|
|
771
|
+
Similarity sim1(q);
|
|
772
|
+
Similarity sim2(q);
|
|
773
|
+
Similarity sim3(q);
|
|
774
|
+
|
|
775
|
+
sim0.begin_16();
|
|
776
|
+
sim1.begin_16();
|
|
777
|
+
sim2.begin_16();
|
|
778
|
+
sim3.begin_16();
|
|
779
|
+
|
|
780
|
+
const size_t d16 = quant.d & ~size_t(15);
|
|
781
|
+
for (size_t i = 0; i < d16; i += 16) {
|
|
782
|
+
simd16float32 xi0 = quant.reconstruct_16_components(code_0, i);
|
|
783
|
+
simd16float32 xi1 = quant.reconstruct_16_components(code_1, i);
|
|
784
|
+
simd16float32 xi2 = quant.reconstruct_16_components(code_2, i);
|
|
785
|
+
simd16float32 xi3 = quant.reconstruct_16_components(code_3, i);
|
|
786
|
+
sim0.add_16_components(xi0);
|
|
787
|
+
sim1.add_16_components(xi1);
|
|
788
|
+
sim2.add_16_components(xi2);
|
|
789
|
+
sim3.add_16_components(xi3);
|
|
790
|
+
}
|
|
791
|
+
add_tail(sim0, q, code_0, d16);
|
|
792
|
+
add_tail(sim1, q, code_1, d16);
|
|
793
|
+
add_tail(sim2, q, code_2, d16);
|
|
794
|
+
add_tail(sim3, q, code_3, d16);
|
|
501
795
|
|
|
502
|
-
|
|
503
|
-
|
|
796
|
+
dis0 = sim0.result_16();
|
|
797
|
+
dis1 = sim1.result_16();
|
|
798
|
+
dis2 = sim2.result_16();
|
|
799
|
+
dis3 = sim3.result_16();
|
|
800
|
+
}
|
|
801
|
+
};
|
|
504
802
|
|
|
505
|
-
|
|
803
|
+
// QT_8bit + IP: the precomputed form of the AVX2 specialization, 16 dims per
|
|
804
|
+
// convert and FMA.
|
|
805
|
+
template <bool four_acc>
|
|
806
|
+
struct DCTemplate<
|
|
807
|
+
QuantizerTemplate<
|
|
808
|
+
Codec8bit<THE_LEVEL_TO_DISPATCH>,
|
|
809
|
+
QuantizerTemplateScaling::NON_UNIFORM,
|
|
810
|
+
THE_LEVEL_TO_DISPATCH>,
|
|
811
|
+
SimilarityIP<THE_LEVEL_TO_DISPATCH>,
|
|
812
|
+
THE_LEVEL_TO_DISPATCH,
|
|
813
|
+
four_acc> : SQDistanceComputer {
|
|
814
|
+
using Quantizer = QuantizerTemplate<
|
|
815
|
+
Codec8bit<THE_LEVEL_TO_DISPATCH>,
|
|
816
|
+
QuantizerTemplateScaling::NON_UNIFORM,
|
|
817
|
+
THE_LEVEL_TO_DISPATCH>;
|
|
818
|
+
using Sim = SimilarityIP<THE_LEVEL_TO_DISPATCH>;
|
|
506
819
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
__m128i c1 = _mm_loadu_si128((__m128i*)(code1 + i));
|
|
515
|
-
__m128i c2 = _mm_loadu_si128((__m128i*)(code2 + i));
|
|
516
|
-
__m512i c1i = _mm512_cvtepu8_epi32(c1);
|
|
517
|
-
__m512i c2i = _mm512_cvtepu8_epi32(c2);
|
|
518
|
-
|
|
519
|
-
__m512i v;
|
|
520
|
-
if (Sim::metric_type == METRIC_INNER_PRODUCT) {
|
|
521
|
-
v = _mm512_mullo_epi32(c1i, c2i);
|
|
522
|
-
} else {
|
|
523
|
-
__m512i diff = _mm512_sub_epi32(c1i, c2i);
|
|
524
|
-
v = _mm512_mullo_epi32(diff, diff);
|
|
525
|
-
}
|
|
526
|
-
accu = _mm512_add_epi32(accu, v);
|
|
527
|
-
}
|
|
528
|
-
return _mm512_reduce_add_epi32(accu);
|
|
820
|
+
Quantizer quant;
|
|
821
|
+
std::vector<float> a, rmin, qa;
|
|
822
|
+
float bias = 0;
|
|
823
|
+
|
|
824
|
+
DCTemplate(size_t d, const std::vector<float>& trained)
|
|
825
|
+
: quant(d, trained), a(d), rmin(d), qa(d) {
|
|
826
|
+
sq8::make_coefficients(trained.data(), d, a.data(), rmin.data());
|
|
529
827
|
}
|
|
530
828
|
|
|
531
829
|
void set_query(const float* x) final {
|
|
532
|
-
|
|
533
|
-
|
|
830
|
+
q = x;
|
|
831
|
+
bias = 0;
|
|
832
|
+
for (size_t i = 0; i < quant.d; i++) {
|
|
833
|
+
qa[i] = x[i] * a[i];
|
|
834
|
+
bias += x[i] * rmin[i];
|
|
534
835
|
}
|
|
535
836
|
}
|
|
536
837
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
838
|
+
static FAISS_ALWAYS_INLINE __m512 codes_16(const uint8_t* code) {
|
|
839
|
+
return _mm512_cvtepi32_ps(
|
|
840
|
+
_mm512_cvtepu8_epi32(_mm_loadu_si128((const __m128i*)code)));
|
|
540
841
|
}
|
|
541
842
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
843
|
+
/// sum_i qa[i] * code[i] of N codes, in 4 lanes each. The N codes share
|
|
844
|
+
/// each qa load. With four_acc, dims i + 16 * j of each 64 go to
|
|
845
|
+
/// accumulator j of the code, so a code sums the same way for any N.
|
|
846
|
+
template <size_t N>
|
|
847
|
+
FAISS_ALWAYS_INLINE void accumulate(
|
|
848
|
+
const uint8_t* const* codes,
|
|
849
|
+
__m128* sums) const {
|
|
850
|
+
constexpr size_t n_acc = four_acc ? 4 : 1;
|
|
851
|
+
__m512 acc[N][n_acc];
|
|
852
|
+
for (size_t n = 0; n < N; n++) {
|
|
853
|
+
for (size_t j = 0; j < n_acc; j++) {
|
|
854
|
+
acc[n][j] = _mm512_setzero_ps();
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
const size_t d = quant.d;
|
|
858
|
+
size_t i = 0;
|
|
859
|
+
if constexpr (four_acc) {
|
|
860
|
+
for (; i + 64 <= d; i += 64) {
|
|
861
|
+
for (size_t j = 0; j < 4; j++) {
|
|
862
|
+
const __m512 qa16 = _mm512_loadu_ps(qa.data() + i + 16 * j);
|
|
863
|
+
for (size_t n = 0; n < N; n++) {
|
|
864
|
+
acc[n][j] = _mm512_fmadd_ps(
|
|
865
|
+
qa16,
|
|
866
|
+
codes_16(codes[n] + i + 16 * j),
|
|
867
|
+
acc[n][j]);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
for (; i < d; i += 16) {
|
|
873
|
+
const __m512 qa16 = _mm512_loadu_ps(qa.data() + i);
|
|
874
|
+
for (size_t n = 0; n < N; n++) {
|
|
875
|
+
acc[n][0] = _mm512_fmadd_ps(
|
|
876
|
+
qa16, codes_16(codes[n] + i), acc[n][0]);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
for (size_t n = 0; n < N; n++) {
|
|
880
|
+
__m512 sum = acc[n][0];
|
|
881
|
+
if constexpr (four_acc) {
|
|
882
|
+
sum = _mm512_add_ps(
|
|
883
|
+
_mm512_add_ps(acc[n][0], acc[n][1]),
|
|
884
|
+
_mm512_add_ps(acc[n][2], acc[n][3]));
|
|
885
|
+
}
|
|
886
|
+
sums[n] = reduce_16_to_4(sum);
|
|
887
|
+
}
|
|
545
888
|
}
|
|
546
889
|
|
|
547
890
|
float query_to_code(const uint8_t* code) const final {
|
|
548
|
-
|
|
891
|
+
__m128 sum;
|
|
892
|
+
accumulate<1>(&code, &sum);
|
|
893
|
+
return bias + reduce_4(sum);
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
void query_to_codes_batch_4(
|
|
897
|
+
const uint8_t* code_0,
|
|
898
|
+
const uint8_t* code_1,
|
|
899
|
+
const uint8_t* code_2,
|
|
900
|
+
const uint8_t* code_3,
|
|
901
|
+
float& dis0,
|
|
902
|
+
float& dis1,
|
|
903
|
+
float& dis2,
|
|
904
|
+
float& dis3) const final {
|
|
905
|
+
const uint8_t* codes[4] = {code_0, code_1, code_2, code_3};
|
|
906
|
+
__m128 sums[4];
|
|
907
|
+
accumulate<4>(codes, sums);
|
|
908
|
+
alignas(16) float dis[4];
|
|
909
|
+
_mm_store_ps(dis, reduce_4x4(sums[0], sums[1], sums[2], sums[3]));
|
|
910
|
+
dis0 = bias + dis[0];
|
|
911
|
+
dis1 = bias + dis[1];
|
|
912
|
+
dis2 = bias + dis[2];
|
|
913
|
+
dis3 = bias + dis[3];
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
float symmetric_dis(idx_t i, idx_t j) override {
|
|
917
|
+
const uint8_t* c1 = codes + i * code_size;
|
|
918
|
+
const uint8_t* c2 = codes + j * code_size;
|
|
919
|
+
Sim sim(nullptr);
|
|
920
|
+
sim.begin_16();
|
|
921
|
+
for (size_t k = 0; k < quant.d; k += 16) {
|
|
922
|
+
simd16float32 x1 = quant.reconstruct_16_components(c1, k);
|
|
923
|
+
simd16float32 x2 = quant.reconstruct_16_components(c2, k);
|
|
924
|
+
sim.add_16_components_2(x1, x2);
|
|
925
|
+
}
|
|
926
|
+
return sim.result_16();
|
|
549
927
|
}
|
|
550
928
|
};
|
|
551
929
|
|
|
552
930
|
} // namespace scalar_quantizer
|
|
931
|
+
|
|
553
932
|
} // namespace faiss
|