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
|
@@ -5,12 +5,8 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
#ifdef COMPILE_SIMD_AVX2
|
|
9
|
-
|
|
10
8
|
#define THE_SIMD_LEVEL SIMDLevel::AVX2
|
|
11
9
|
// NOLINTBEGIN(facebook-hte-InlineHeader,facebook-unused-include-check)
|
|
12
10
|
#include <faiss/utils/hamming_distance/hamming_computer-avx2.h>
|
|
13
11
|
#include <faiss/utils/hamming_distance/hamming_impl.h>
|
|
14
12
|
// NOLINTEND(facebook-hte-InlineHeader,facebook-unused-include-check)
|
|
15
|
-
|
|
16
|
-
#endif // COMPILE_SIMD_AVX2
|
|
@@ -5,11 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
#ifdef COMPILE_SIMD_AVX512
|
|
9
|
-
|
|
10
8
|
#define THE_SIMD_LEVEL SIMDLevel::AVX512
|
|
11
9
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
12
10
|
#include <faiss/utils/hamming_distance/hamming_computer-avx512.h>
|
|
13
11
|
#include <faiss/utils/hamming_distance/hamming_impl.h>
|
|
14
|
-
|
|
15
|
-
#endif // COMPILE_SIMD_AVX512
|
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
#ifdef COMPILE_SIMD_AVX512_VPOPCNT
|
|
9
|
-
|
|
10
8
|
#define THE_SIMD_LEVEL SIMDLevel::AVX512_VPOPCNT
|
|
11
9
|
#include <faiss/utils/hamming_distance/hamming_computer-avx512_vpopcnt.h>
|
|
12
10
|
#include <faiss/utils/hamming_distance/hamming_impl.h>
|
|
@@ -20,5 +18,3 @@
|
|
|
20
18
|
// Fails the build if the batch path stops being selected for this computer.
|
|
21
19
|
static_assert(faiss::has_hamming_batch<
|
|
22
20
|
faiss::HammingComputer20_tpl<faiss::SIMDLevel::AVX512_VPOPCNT>>);
|
|
23
|
-
|
|
24
|
-
#endif // COMPILE_SIMD_AVX512_VPOPCNT
|
|
@@ -103,12 +103,40 @@ struct HammingComputerDefault_tpl<SIMDLevel::AVX512> {
|
|
|
103
103
|
remainder8 = code_size % 8;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
/// No VPOPCNTDQ at this level: count the bits of each nibble with a
|
|
107
|
+
/// 16-entry table (vpshufb), then sum the bytes per 64-bit lane (vpsadbw).
|
|
108
|
+
/// The partial last block is a masked load, so no byte past the code is
|
|
109
|
+
/// read.
|
|
106
110
|
int hamming(const uint8_t* b8) const {
|
|
107
|
-
const
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
111
|
+
const int code_size = quotient8 * 8 + remainder8;
|
|
112
|
+
const __m512i lut = _mm512_broadcast_i32x4(
|
|
113
|
+
_mm_setr_epi8(0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4));
|
|
114
|
+
const __m512i low4 = _mm512_set1_epi8(0x0f);
|
|
115
|
+
const auto count = [&](__m512i x) {
|
|
116
|
+
const __m512i lo = _mm512_and_si512(x, low4);
|
|
117
|
+
const __m512i hi = _mm512_and_si512(_mm512_srli_epi16(x, 4), low4);
|
|
118
|
+
const __m512i c = _mm512_add_epi8(
|
|
119
|
+
_mm512_shuffle_epi8(lut, lo), _mm512_shuffle_epi8(lut, hi));
|
|
120
|
+
return _mm512_sad_epu8(c, _mm512_setzero_si512());
|
|
121
|
+
};
|
|
122
|
+
__m512i accu = _mm512_setzero_si512();
|
|
123
|
+
int i = 0;
|
|
124
|
+
for (; i + 64 <= code_size; i += 64) {
|
|
125
|
+
accu = _mm512_add_epi64(
|
|
126
|
+
accu,
|
|
127
|
+
count(_mm512_xor_si512(
|
|
128
|
+
_mm512_loadu_si512(a8 + i),
|
|
129
|
+
_mm512_loadu_si512(b8 + i))));
|
|
130
|
+
}
|
|
131
|
+
if (i < code_size) {
|
|
132
|
+
const __mmask64 mask = _bzhi_u64(~uint64_t(0), code_size - i);
|
|
133
|
+
accu = _mm512_add_epi64(
|
|
134
|
+
accu,
|
|
135
|
+
count(_mm512_xor_si512(
|
|
136
|
+
_mm512_maskz_loadu_epi8(mask, a8 + i),
|
|
137
|
+
_mm512_maskz_loadu_epi8(mask, b8 + i))));
|
|
138
|
+
}
|
|
139
|
+
return static_cast<int>(_mm512_reduce_add_epi64(accu));
|
|
112
140
|
}
|
|
113
141
|
|
|
114
142
|
inline int get_code_size() const {
|
|
@@ -186,40 +186,25 @@ struct HammingComputerDefault_tpl<SIMDLevel::AVX512_VPOPCNT> {
|
|
|
186
186
|
remainder8 = code_size % 8;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
/// One vector accumulator, reduced once. The partial last block is a
|
|
190
|
+
/// masked load, so no byte past the code is read.
|
|
189
191
|
int hamming(const uint8_t* b8) const {
|
|
190
|
-
int
|
|
191
|
-
|
|
192
|
-
const uint64_t* a64 = reinterpret_cast<const uint64_t*>(a8);
|
|
193
|
-
const uint64_t* b64 = reinterpret_cast<const uint64_t*>(b8);
|
|
194
|
-
|
|
192
|
+
const int code_size = quotient8 * 8 + remainder8;
|
|
193
|
+
__m512i accu = _mm512_setzero_si512();
|
|
195
194
|
int i = 0;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
_mm512_loadu_si512(&b64[i * 8]));
|
|
201
|
-
__m512i vpcnt = _mm512_popcnt_epi64(vxor);
|
|
202
|
-
accu += _mm512_reduce_add_epi32(vpcnt);
|
|
195
|
+
for (; i + 64 <= code_size; i += 64) {
|
|
196
|
+
const __m512i vxor = _mm512_xor_si512(
|
|
197
|
+
_mm512_loadu_si512(a8 + i), _mm512_loadu_si512(b8 + i));
|
|
198
|
+
accu = _mm512_add_epi64(accu, _mm512_popcnt_epi64(vxor));
|
|
203
199
|
}
|
|
204
|
-
i
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
_mm256_loadu_si256((const __m256i*)&b64[i]));
|
|
211
|
-
__m256i vpcnt = _mm256_popcnt_epi64(vxor);
|
|
212
|
-
__m128i lo = _mm256_castsi256_si128(vpcnt);
|
|
213
|
-
__m128i hi = _mm256_extracti128_si256(vpcnt, 1);
|
|
214
|
-
__m128i sum = _mm_add_epi64(lo, hi);
|
|
215
|
-
accu += static_cast<int>(
|
|
216
|
-
_mm_extract_epi64(sum, 0) + _mm_extract_epi64(sum, 1));
|
|
217
|
-
i += 4;
|
|
200
|
+
if (i < code_size) {
|
|
201
|
+
const __mmask64 mask = _bzhi_u64(~uint64_t(0), code_size - i);
|
|
202
|
+
const __m512i vxor = _mm512_xor_si512(
|
|
203
|
+
_mm512_maskz_loadu_epi8(mask, a8 + i),
|
|
204
|
+
_mm512_maskz_loadu_epi8(mask, b8 + i));
|
|
205
|
+
accu = _mm512_add_epi64(accu, _mm512_popcnt_epi64(vxor));
|
|
218
206
|
}
|
|
219
|
-
|
|
220
|
-
accu += hamming_popcount_tail(
|
|
221
|
-
a64, b64, i, quotient8, a8, b8, remainder8);
|
|
222
|
-
return accu;
|
|
207
|
+
return static_cast<int>(_mm512_reduce_add_epi64(accu));
|
|
223
208
|
}
|
|
224
209
|
|
|
225
210
|
inline int get_code_size() const {
|
|
@@ -16,8 +16,6 @@
|
|
|
16
16
|
// hamming_computer-generic.h. SIMDLevel::ARM_NEON specializations for the
|
|
17
17
|
// ISA-varying HammingComputer and GenHammingComputer structs live in this file.
|
|
18
18
|
|
|
19
|
-
#ifdef __aarch64__
|
|
20
|
-
|
|
21
19
|
#include <arm_neon.h>
|
|
22
20
|
|
|
23
21
|
#include <cassert>
|
|
@@ -318,5 +316,3 @@ struct GenHammingComputerM8_tpl<SIMDLevel::ARM_NEON> {
|
|
|
318
316
|
} // namespace faiss
|
|
319
317
|
|
|
320
318
|
#endif
|
|
321
|
-
|
|
322
|
-
#endif
|
|
@@ -5,11 +5,7 @@
|
|
|
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
|
#define THE_SIMD_LEVEL SIMDLevel::ARM_NEON
|
|
11
9
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
12
10
|
#include <faiss/utils/hamming_distance/hamming_computer-neon.h>
|
|
13
11
|
#include <faiss/utils/hamming_distance/hamming_impl.h>
|
|
14
|
-
|
|
15
|
-
#endif // COMPILE_SIMD_ARM_NEON
|
|
@@ -5,11 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
#ifdef COMPILE_SIMD_RISCV_RVV
|
|
9
|
-
|
|
10
8
|
#define THE_SIMD_LEVEL SIMDLevel::RISCV_RVV
|
|
11
9
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
12
10
|
#include <faiss/utils/hamming_distance/hamming_computer-rvv.h>
|
|
13
11
|
#include <faiss/utils/hamming_distance/hamming_impl.h>
|
|
14
|
-
|
|
15
|
-
#endif // COMPILE_SIMD_RISCV_RVV
|
|
@@ -53,10 +53,14 @@ namespace pq_code_distance {
|
|
|
53
53
|
*********************************************************************/
|
|
54
54
|
|
|
55
55
|
/// Scalar PQ code distance implementation.
|
|
56
|
-
/// Templated only on decoder type, independent of SIMD level.
|
|
57
56
|
/// Used directly by non-PQDecoder8 decoders (PQDecoder16,
|
|
58
57
|
/// PQDecoderGeneric) and as fallback for PQDecoder8 at NONE/NEON.
|
|
59
|
-
|
|
58
|
+
// SL keeps each SIMD-level TU's instantiation a distinct symbol. Without it
|
|
59
|
+
// the linker merges them and may keep one compiled with -mavx512*, which
|
|
60
|
+
// then runs on the AVX2 path and raises SIGILL on CPUs without AVX512.
|
|
61
|
+
// The default keeps callers outside faiss that name only the decoder (e.g.
|
|
62
|
+
// unicorn/features/encoders/PQFSTable.h) compiling; faiss passes SL itself.
|
|
63
|
+
template <typename PQDecoderT, SIMDLevel SL = SIMDLevel::NONE>
|
|
60
64
|
struct PQCodeDistanceScalar {
|
|
61
65
|
using PQDecoder = PQDecoderT;
|
|
62
66
|
|
|
@@ -160,7 +164,7 @@ struct PQCodeDistance {
|
|
|
160
164
|
if constexpr (std::is_same_v<PQDecoderT, PQDecoder8>) {
|
|
161
165
|
return pq_code_distance_single_impl<SL>(M, nbits, sim_table, code);
|
|
162
166
|
} else {
|
|
163
|
-
return PQCodeDistanceScalar<PQDecoderT>::distance_single_code(
|
|
167
|
+
return PQCodeDistanceScalar<PQDecoderT, SL>::distance_single_code(
|
|
164
168
|
M, nbits, sim_table, code);
|
|
165
169
|
}
|
|
166
170
|
}
|
|
@@ -191,7 +195,7 @@ struct PQCodeDistance {
|
|
|
191
195
|
result2,
|
|
192
196
|
result3);
|
|
193
197
|
} else {
|
|
194
|
-
PQCodeDistanceScalar<PQDecoderT>::distance_four_codes(
|
|
198
|
+
PQCodeDistanceScalar<PQDecoderT, SL>::distance_four_codes(
|
|
195
199
|
M,
|
|
196
200
|
nbits,
|
|
197
201
|
sim_table,
|
|
@@ -25,34 +25,9 @@ inline void prefetch_L3(const void* address) {
|
|
|
25
25
|
_mm_prefetch((const char*)address, _MM_HINT_T2);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
#elif defined(__aarch64__)
|
|
29
|
-
|
|
30
|
-
// ARM64
|
|
31
|
-
|
|
32
|
-
#ifdef _MSC_VER
|
|
33
|
-
|
|
34
|
-
// todo: arm on MSVC
|
|
35
|
-
inline void prefetch_L1(const void* address) {}
|
|
36
|
-
inline void prefetch_L2(const void* address) {}
|
|
37
|
-
inline void prefetch_L3(const void* address) {}
|
|
38
|
-
|
|
39
|
-
#else
|
|
40
|
-
// arm on non-MSVC
|
|
41
|
-
|
|
42
|
-
inline void prefetch_L1(const void* address) {
|
|
43
|
-
__builtin_prefetch(address, 0, 3);
|
|
44
|
-
}
|
|
45
|
-
inline void prefetch_L2(const void* address) {
|
|
46
|
-
__builtin_prefetch(address, 0, 2);
|
|
47
|
-
}
|
|
48
|
-
inline void prefetch_L3(const void* address) {
|
|
49
|
-
__builtin_prefetch(address, 0, 1);
|
|
50
|
-
}
|
|
51
|
-
#endif
|
|
52
|
-
|
|
53
28
|
#else
|
|
54
29
|
|
|
55
|
-
//
|
|
30
|
+
// other platforms, including ARM64
|
|
56
31
|
|
|
57
32
|
#ifdef _MSC_VER
|
|
58
33
|
|
|
@@ -60,6 +60,19 @@ void round_tab(const float* tab, size_t n, float a, float bi, T* tab_out) {
|
|
|
60
60
|
|
|
61
61
|
} // anonymous namespace
|
|
62
62
|
|
|
63
|
+
float fastscan_lut_scale(
|
|
64
|
+
float max_column_span,
|
|
65
|
+
float max_sum_span,
|
|
66
|
+
size_t n_rounded_terms) {
|
|
67
|
+
const float headroom = 0.5f * float(n_rounded_terms);
|
|
68
|
+
const float sum_budget = 65535.0f - headroom;
|
|
69
|
+
const float a = std::min(
|
|
70
|
+
max_column_span > 0 ? 255.0f / max_column_span : HUGE_VALF,
|
|
71
|
+
(max_sum_span > 0 && sum_budget > 0) ? sum_budget / max_sum_span
|
|
72
|
+
: HUGE_VALF);
|
|
73
|
+
return std::isfinite(a) ? a : 0.0f;
|
|
74
|
+
}
|
|
75
|
+
|
|
63
76
|
void round_uint8_per_column(
|
|
64
77
|
float* tab,
|
|
65
78
|
size_t n,
|
|
@@ -67,6 +80,7 @@ void round_uint8_per_column(
|
|
|
67
80
|
float* a_out,
|
|
68
81
|
float* b_out) {
|
|
69
82
|
float max_span = 0;
|
|
83
|
+
float total_span = 0;
|
|
70
84
|
std::vector<float> mins(n);
|
|
71
85
|
for (size_t i = 0; i < n; i++) {
|
|
72
86
|
mins[i] = tab_min(tab + i * d, d);
|
|
@@ -74,8 +88,9 @@ void round_uint8_per_column(
|
|
|
74
88
|
if (span > max_span) {
|
|
75
89
|
max_span = span;
|
|
76
90
|
}
|
|
91
|
+
total_span += span;
|
|
77
92
|
}
|
|
78
|
-
float a = max_span
|
|
93
|
+
float a = fastscan_lut_scale(max_span, total_span, n);
|
|
79
94
|
float b = 0;
|
|
80
95
|
for (size_t i = 0; i < n; i++) {
|
|
81
96
|
b += mins[i];
|
|
@@ -97,6 +112,7 @@ void round_uint8_per_column_multi(
|
|
|
97
112
|
float* a_out,
|
|
98
113
|
float* b_out) {
|
|
99
114
|
float max_span = 0;
|
|
115
|
+
float total_span = 0;
|
|
100
116
|
std::vector<float> mins(n);
|
|
101
117
|
for (size_t i = 0; i < n; i++) {
|
|
102
118
|
float min_i = HUGE_VAL;
|
|
@@ -110,8 +126,9 @@ void round_uint8_per_column_multi(
|
|
|
110
126
|
if (span > max_span) {
|
|
111
127
|
max_span = span;
|
|
112
128
|
}
|
|
129
|
+
total_span += span;
|
|
113
130
|
}
|
|
114
|
-
float a = max_span
|
|
131
|
+
float a = fastscan_lut_scale(max_span, total_span, n);
|
|
115
132
|
float b = 0;
|
|
116
133
|
for (size_t i = 0; i < n; i++) {
|
|
117
134
|
b += mins[i];
|
|
@@ -155,12 +172,7 @@ void quantize_LUT_and_bias(
|
|
|
155
172
|
max_span_dis += span;
|
|
156
173
|
b += mins[i];
|
|
157
174
|
}
|
|
158
|
-
a =
|
|
159
|
-
max_span_LUT > 0 ? 255.0f / max_span_LUT : HUGE_VALF,
|
|
160
|
-
max_span_dis > 0 ? 65535.0f / max_span_dis : HUGE_VALF);
|
|
161
|
-
if (!std::isfinite(a)) {
|
|
162
|
-
a = 0.0f;
|
|
163
|
-
}
|
|
175
|
+
a = fastscan_lut_scale(max_span_LUT, max_span_dis, M);
|
|
164
176
|
|
|
165
177
|
for (size_t i = 0; i < M; i++) {
|
|
166
178
|
round_tab(LUT + i * ksub, ksub, a, mins[i], LUTq + i * ksub);
|
|
@@ -180,12 +192,7 @@ void quantize_LUT_and_bias(
|
|
|
180
192
|
max_span_dis += span;
|
|
181
193
|
b += mins[i];
|
|
182
194
|
}
|
|
183
|
-
a =
|
|
184
|
-
max_span_LUT > 0 ? 255.0f / max_span_LUT : HUGE_VALF,
|
|
185
|
-
max_span_dis > 0 ? 65535.0f / max_span_dis : HUGE_VALF);
|
|
186
|
-
if (!std::isfinite(a)) {
|
|
187
|
-
a = 0.0f;
|
|
188
|
-
}
|
|
195
|
+
a = fastscan_lut_scale(max_span_LUT, max_span_dis, M);
|
|
189
196
|
b += bias_min;
|
|
190
197
|
|
|
191
198
|
for (size_t i = 0; i < M; i++) {
|
|
@@ -219,12 +226,7 @@ void quantize_LUT_and_bias(
|
|
|
219
226
|
b = std::min(b, b2j);
|
|
220
227
|
}
|
|
221
228
|
|
|
222
|
-
a =
|
|
223
|
-
max_span_LUT > 0 ? 255.0f / max_span_LUT : HUGE_VALF,
|
|
224
|
-
max_span_dis > 0 ? 65535.0f / max_span_dis : HUGE_VALF);
|
|
225
|
-
if (!std::isfinite(a)) {
|
|
226
|
-
a = 0.0f;
|
|
227
|
-
}
|
|
229
|
+
a = fastscan_lut_scale(max_span_LUT, max_span_dis, M);
|
|
228
230
|
|
|
229
231
|
ij = 0;
|
|
230
232
|
size_t ij_2 = 0;
|
|
@@ -266,13 +268,15 @@ void quantize_LUT_and_bias(
|
|
|
266
268
|
}
|
|
267
269
|
|
|
268
270
|
float max_span = -HUGE_VAL;
|
|
271
|
+
float total_span = 0;
|
|
269
272
|
b = 0;
|
|
270
273
|
for (size_t i = 0; i < M; i++) {
|
|
271
274
|
float span = maxs[i] - mins[i];
|
|
272
275
|
max_span = std::max(max_span, span);
|
|
276
|
+
total_span += span;
|
|
273
277
|
b += mins[i];
|
|
274
278
|
}
|
|
275
|
-
a = max_span
|
|
279
|
+
a = fastscan_lut_scale(max_span, total_span, M);
|
|
276
280
|
ij = 0;
|
|
277
281
|
size_t ij_2 = 0;
|
|
278
282
|
for (size_t j = 0; j < nprobe; j++) {
|
|
@@ -321,12 +325,7 @@ void aq_quantize_LUT_and_bias(
|
|
|
321
325
|
max_span_dis += (i >= M - M_norm ? span * norm_scale : span);
|
|
322
326
|
b += mins[i];
|
|
323
327
|
}
|
|
324
|
-
a =
|
|
325
|
-
max_span_LUT > 0 ? 255.0f / max_span_LUT : HUGE_VALF,
|
|
326
|
-
max_span_dis > 0 ? 65535.0f / max_span_dis : HUGE_VALF);
|
|
327
|
-
if (!std::isfinite(a)) {
|
|
328
|
-
a = 0.0f;
|
|
329
|
-
}
|
|
328
|
+
a = fastscan_lut_scale(max_span_LUT, max_span_dis, M);
|
|
330
329
|
b += bias_min;
|
|
331
330
|
|
|
332
331
|
for (size_t i = 0; i < M; i++) {
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
+
#include <cstddef>
|
|
11
|
+
|
|
10
12
|
#include <cstdint>
|
|
11
13
|
#include <cstdio>
|
|
12
14
|
|
|
@@ -25,6 +27,15 @@ namespace faiss {
|
|
|
25
27
|
|
|
26
28
|
namespace quantize_lut {
|
|
27
29
|
|
|
30
|
+
/** Scale for a fast scan LUT, bounding both the uint8 entry and the uint16
|
|
31
|
+
* sum the kernel accumulates. `n_rounded_terms` is how many rounded values
|
|
32
|
+
* land in one accumulator: the columns, plus one for a rounded bias term.
|
|
33
|
+
*/
|
|
34
|
+
float fastscan_lut_scale(
|
|
35
|
+
float max_column_span,
|
|
36
|
+
float max_sum_span,
|
|
37
|
+
size_t n_rounded_terms);
|
|
38
|
+
|
|
28
39
|
/* affine quantizer, a and b are the affine coefficients, marginalize over d
|
|
29
40
|
*
|
|
30
41
|
* @param tab input/output, size (n, d)
|
|
@@ -53,6 +53,28 @@ BitwiseAndDotProductResult bitwise_and_dot_product_with_popcount(
|
|
|
53
53
|
size_t size,
|
|
54
54
|
size_t qb);
|
|
55
55
|
|
|
56
|
+
/// Four independent AND-dot-product/popcount pairs for a four-plane query.
|
|
57
|
+
/// Query contains 4 * size bytes; each data pointer contains `size` bytes.
|
|
58
|
+
/// Byte-aligned buffers and arbitrary byte counts are supported.
|
|
59
|
+
template <SIMDLevel SL = SINGLE_SIMD_LEVEL>
|
|
60
|
+
inline void bitwise_q4_batch_4(
|
|
61
|
+
const uint8_t* query,
|
|
62
|
+
const uint8_t* const* data,
|
|
63
|
+
size_t size,
|
|
64
|
+
BitwiseAndDotProductResult* results) {
|
|
65
|
+
for (size_t i = 0; i < 4; ++i) {
|
|
66
|
+
results[i] = bitwise_and_dot_product_with_popcount<SL>(
|
|
67
|
+
query, data[i], size, 4);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
template <>
|
|
72
|
+
void bitwise_q4_batch_4<SIMDLevel::AVX512_VPOPCNT>(
|
|
73
|
+
const uint8_t* query,
|
|
74
|
+
const uint8_t* const* data,
|
|
75
|
+
size_t size,
|
|
76
|
+
BitwiseAndDotProductResult* results);
|
|
77
|
+
|
|
56
78
|
/**
|
|
57
79
|
* Compute dot product between query and binary data using popcount on XOR.
|
|
58
80
|
*
|
|
@@ -140,9 +162,11 @@ inline uint64_t bitwise_and_dot_product<SIMDLevel::NONE>(
|
|
|
140
162
|
uint64_t sum = 0;
|
|
141
163
|
size_t offset = 0;
|
|
142
164
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
143
|
-
|
|
165
|
+
uint64_t yv;
|
|
166
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
144
167
|
for (int j = 0; j < qb; j++) {
|
|
145
|
-
|
|
168
|
+
uint64_t qv;
|
|
169
|
+
std::memcpy(&qv, query + j * size + offset, sizeof(qv));
|
|
146
170
|
sum += popcount64(qv & yv) << j;
|
|
147
171
|
}
|
|
148
172
|
}
|
|
@@ -167,10 +191,12 @@ inline BitwiseAndDotProductResult bitwise_and_dot_product_with_popcount<
|
|
|
167
191
|
uint64_t popcount_sum = 0;
|
|
168
192
|
size_t offset = 0;
|
|
169
193
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
170
|
-
|
|
194
|
+
uint64_t yv;
|
|
195
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
171
196
|
popcount_sum += popcount64(yv);
|
|
172
197
|
for (int j = 0; j < qb; j++) {
|
|
173
|
-
|
|
198
|
+
uint64_t qv;
|
|
199
|
+
std::memcpy(&qv, query + j * size + offset, sizeof(qv));
|
|
174
200
|
dot_product += popcount64(qv & yv) << j;
|
|
175
201
|
}
|
|
176
202
|
}
|
|
@@ -194,9 +220,11 @@ inline uint64_t bitwise_xor_dot_product<SIMDLevel::NONE>(
|
|
|
194
220
|
uint64_t sum = 0;
|
|
195
221
|
size_t offset = 0;
|
|
196
222
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
197
|
-
|
|
223
|
+
uint64_t yv;
|
|
224
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
198
225
|
for (int j = 0; j < qb; j++) {
|
|
199
|
-
|
|
226
|
+
uint64_t qv;
|
|
227
|
+
std::memcpy(&qv, query + j * size + offset, sizeof(qv));
|
|
200
228
|
sum += popcount64(qv ^ yv) << j;
|
|
201
229
|
}
|
|
202
230
|
}
|
|
@@ -215,7 +243,8 @@ inline uint64_t popcount<SIMDLevel::NONE>(const uint8_t* data, size_t size) {
|
|
|
215
243
|
uint64_t sum = 0;
|
|
216
244
|
size_t offset = 0;
|
|
217
245
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
218
|
-
|
|
246
|
+
uint64_t yv;
|
|
247
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
219
248
|
sum += popcount64(yv);
|
|
220
249
|
}
|
|
221
250
|
for (; offset < size; ++offset) {
|
|
@@ -332,16 +361,12 @@ inline void quantize_query_values<SIMDLevel::NONE>(
|
|
|
332
361
|
/*********************************************************
|
|
333
362
|
* Multi-bit RaBitQ inner product kernels.
|
|
334
363
|
*
|
|
335
|
-
*
|
|
364
|
+
* Score = sum_i rotated_q[i] * ((sign_i << ex_bits) + ex_i + cb)
|
|
336
365
|
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
* ex_bits >= 2: Bit-plane decomposition (BMI2 required) — PEXT extracts
|
|
342
|
-
* each bit plane in one instruction, then the same
|
|
343
|
-
* bit→mask→float kernel computes each plane's dot product.
|
|
344
|
-
* Fallback: Scalar extraction via 64-bit window read + shift + mask.
|
|
366
|
+
* ex_bits == 1: bits map straight to floats. No extraction.
|
|
367
|
+
* ex_bits 2..7: BMI2 PEXT extracts each bit plane.
|
|
368
|
+
* ex_bits == 8: whole bytes. No extraction and no BMI2.
|
|
369
|
+
* Fallback: scalar math reads one code at a time.
|
|
345
370
|
*********************************************************/
|
|
346
371
|
namespace faiss::rabitq::multibit {
|
|
347
372
|
|
|
@@ -357,6 +382,16 @@ inline float ip_scalar(
|
|
|
357
382
|
size_t ex_bits,
|
|
358
383
|
float cb) {
|
|
359
384
|
float result = 0.0f;
|
|
385
|
+
if (ex_bits == 8) {
|
|
386
|
+
// RBQ9 is byte-aligned, including the last dimension. Do not require
|
|
387
|
+
// trailing factor bytes for the scalar reference or SIMD tail.
|
|
388
|
+
for (size_t i = start; i < d; ++i) {
|
|
389
|
+
const int sb = (sign_bits[i / 8] >> (i % 8)) & 1;
|
|
390
|
+
result += rotated_q[i] *
|
|
391
|
+
(static_cast<float>((sb << 8) + ex_code[i]) + cb);
|
|
392
|
+
}
|
|
393
|
+
return result;
|
|
394
|
+
}
|
|
360
395
|
const int sign_shift = static_cast<int>(ex_bits);
|
|
361
396
|
const uint64_t code_mask = (1ULL << ex_bits) - 1;
|
|
362
397
|
for (size_t i = start; i < d; i++) {
|
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
#include <faiss/utils/distances.h>
|
|
9
|
-
|
|
10
|
-
#ifdef __aarch64__
|
|
9
|
+
#include <faiss/utils/simd_impl/masked_sum.h>
|
|
11
10
|
|
|
12
11
|
#include <arm_neon.h>
|
|
13
12
|
#include <limits>
|
|
@@ -41,6 +40,14 @@ void fvec_madd<SIMDLevel::ARM_NEON>(
|
|
|
41
40
|
c[i] = a[i] + bf * b[i];
|
|
42
41
|
}
|
|
43
42
|
|
|
43
|
+
template <>
|
|
44
|
+
float fvec_masked_sum<SIMDLevel::ARM_NEON>(
|
|
45
|
+
const float* x,
|
|
46
|
+
const uint8_t* bits,
|
|
47
|
+
size_t d) {
|
|
48
|
+
return masked_sum<SIMDLevel::ARM_NEON>(x, bits, d);
|
|
49
|
+
}
|
|
50
|
+
|
|
44
51
|
template <>
|
|
45
52
|
void fvec_L2sqr_ny_transposed<SIMDLevel::ARM_NEON>(
|
|
46
53
|
float* dis,
|
|
@@ -150,5 +157,3 @@ int fvec_madd_and_argmin<SIMDLevel::ARM_NEON>(
|
|
|
150
157
|
}
|
|
151
158
|
|
|
152
159
|
} // namespace faiss
|
|
153
|
-
|
|
154
|
-
#endif // __aarch64__
|
|
@@ -758,9 +758,11 @@ size_t fvec_L2sqr_ny_nearest_y_transposed<SIMDLevel::ARM_SVE>(
|
|
|
758
758
|
return current_min_idx;
|
|
759
759
|
}
|
|
760
760
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
761
|
+
namespace {
|
|
762
|
+
|
|
763
|
+
template <class QueryTiles>
|
|
764
|
+
void exhaustive_L2sqr_blas_cmax_sve(
|
|
765
|
+
QueryTiles& queries,
|
|
764
766
|
const float* y,
|
|
765
767
|
size_t d,
|
|
766
768
|
size_t nx,
|
|
@@ -779,7 +781,7 @@ void exhaustive_L2sqr_blas_cmax<SIMDLevel::ARM_SVE>(
|
|
|
779
781
|
std::unique_ptr<float[]> x_norms(new float[nx]);
|
|
780
782
|
std::unique_ptr<float[]> del2;
|
|
781
783
|
|
|
782
|
-
|
|
784
|
+
queries.prepare_norms(nx, x_norms.get());
|
|
783
785
|
|
|
784
786
|
const size_t lanes = svcntw();
|
|
785
787
|
|
|
@@ -795,6 +797,8 @@ void exhaustive_L2sqr_blas_cmax<SIMDLevel::ARM_SVE>(
|
|
|
795
797
|
if (i1 > nx)
|
|
796
798
|
i1 = nx;
|
|
797
799
|
|
|
800
|
+
const float* xt = queries.tile(i0, i1, x_norms.get());
|
|
801
|
+
|
|
798
802
|
res.begin_multiple(i0, i1);
|
|
799
803
|
|
|
800
804
|
for (size_t j0 = 0; j0 < ny; j0 += bs_y) {
|
|
@@ -813,7 +817,7 @@ void exhaustive_L2sqr_blas_cmax<SIMDLevel::ARM_SVE>(
|
|
|
813
817
|
&one,
|
|
814
818
|
y + j0 * d,
|
|
815
819
|
&di,
|
|
816
|
-
|
|
820
|
+
xt,
|
|
817
821
|
&di,
|
|
818
822
|
&zero,
|
|
819
823
|
ip_block.get(),
|
|
@@ -938,4 +942,32 @@ void exhaustive_L2sqr_blas_cmax<SIMDLevel::ARM_SVE>(
|
|
|
938
942
|
}
|
|
939
943
|
}
|
|
940
944
|
|
|
945
|
+
} // namespace
|
|
946
|
+
|
|
947
|
+
template <>
|
|
948
|
+
void exhaustive_L2sqr_blas_cmax<SIMDLevel::ARM_SVE>(
|
|
949
|
+
const float* x,
|
|
950
|
+
const float* y,
|
|
951
|
+
size_t d,
|
|
952
|
+
size_t nx,
|
|
953
|
+
size_t ny,
|
|
954
|
+
Top1BlockResultHandler<CMax<float, int64_t>>& res,
|
|
955
|
+
const float* y_norms) {
|
|
956
|
+
Fp32QueryTiles queries{x, d};
|
|
957
|
+
exhaustive_L2sqr_blas_cmax_sve(queries, y, d, nx, ny, res, y_norms);
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
template <>
|
|
961
|
+
void exhaustive_L2sqr_blas_cmax_fp16<SIMDLevel::ARM_SVE>(
|
|
962
|
+
const uint16_t* x,
|
|
963
|
+
const float* y,
|
|
964
|
+
size_t d,
|
|
965
|
+
size_t nx,
|
|
966
|
+
size_t ny,
|
|
967
|
+
Top1BlockResultHandler<CMax<float, int64_t>>& res,
|
|
968
|
+
const float* y_norms) {
|
|
969
|
+
Fp16QueryTiles queries(x, d, nx);
|
|
970
|
+
exhaustive_L2sqr_blas_cmax_sve(queries, y, d, nx, ny, res, y_norms);
|
|
971
|
+
}
|
|
972
|
+
|
|
941
973
|
} // namespace faiss
|