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,8 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
#ifdef COMPILE_SIMD_AVX512
|
|
9
|
-
|
|
10
8
|
#include <faiss/utils/rabitq_simd.h>
|
|
11
9
|
#include <immintrin.h>
|
|
12
10
|
#include <limits>
|
|
@@ -378,9 +376,11 @@ uint64_t bitwise_and_dot_product<SIMDLevel::AVX512>(
|
|
|
378
376
|
}
|
|
379
377
|
sum += reduce_add_128(sum_128);
|
|
380
378
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
381
|
-
|
|
379
|
+
uint64_t yv;
|
|
380
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
382
381
|
for (int j = 0; j < qb; j++) {
|
|
383
|
-
|
|
382
|
+
uint64_t qv;
|
|
383
|
+
std::memcpy(&qv, query + j * size + offset, sizeof(qv));
|
|
384
384
|
sum += popcount64(qv & yv) << j;
|
|
385
385
|
}
|
|
386
386
|
}
|
|
@@ -457,10 +457,12 @@ BitwiseAndDotProductResult bitwise_and_dot_product_with_popcount<
|
|
|
457
457
|
dot_product += reduce_add_128(dot_128);
|
|
458
458
|
popcount_sum += reduce_add_128(pop_128);
|
|
459
459
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
460
|
-
|
|
460
|
+
uint64_t yv;
|
|
461
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
461
462
|
popcount_sum += popcount64(yv);
|
|
462
463
|
for (int j = 0; j < qb; j++) {
|
|
463
|
-
|
|
464
|
+
uint64_t qv;
|
|
465
|
+
std::memcpy(&qv, query + j * size + offset, sizeof(qv));
|
|
464
466
|
dot_product += popcount64(qv & yv) << j;
|
|
465
467
|
}
|
|
466
468
|
}
|
|
@@ -527,9 +529,11 @@ uint64_t bitwise_xor_dot_product<SIMDLevel::AVX512>(
|
|
|
527
529
|
}
|
|
528
530
|
sum += reduce_add_128(sum_128);
|
|
529
531
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
530
|
-
|
|
532
|
+
uint64_t yv;
|
|
533
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
531
534
|
for (int j = 0; j < qb; j++) {
|
|
532
|
-
|
|
535
|
+
uint64_t qv;
|
|
536
|
+
std::memcpy(&qv, query + j * size + offset, sizeof(qv));
|
|
533
537
|
sum += popcount64(qv ^ yv) << j;
|
|
534
538
|
}
|
|
535
539
|
}
|
|
@@ -572,7 +576,8 @@ uint64_t popcount<SIMDLevel::AVX512>(const uint8_t* data, size_t size) {
|
|
|
572
576
|
}
|
|
573
577
|
sum += reduce_add_128(sum_128);
|
|
574
578
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
575
|
-
|
|
579
|
+
uint64_t yv;
|
|
580
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
576
581
|
sum += popcount64(yv);
|
|
577
582
|
}
|
|
578
583
|
for (; offset < size; ++offset) {
|
|
@@ -654,13 +659,9 @@ inline float ip_1exbit_avx512(
|
|
|
654
659
|
return result;
|
|
655
660
|
}
|
|
656
661
|
|
|
657
|
-
//
|
|
658
|
-
//
|
|
659
|
-
|
|
660
|
-
// Bitplane kernel for ex_bits >= 2, 16 dims per iteration. A bitplane is
|
|
661
|
-
// already a bitmask, so it goes into a mask register and one masked add
|
|
662
|
-
// applies its weight. Reads of ex_code run a few bytes past the ex-code
|
|
663
|
-
// section into the record's own trailing factors, so they stay in bounds.
|
|
662
|
+
// Bit-plane kernel for ex_bits >= 2. It scores 16 dims per pass.
|
|
663
|
+
// Each plane acts as a mask for one weighted add. Reads can run
|
|
664
|
+
// past the codes into the row tail, which stays in bounds.
|
|
664
665
|
inline float ip_bitplane_avx512(
|
|
665
666
|
const uint8_t* __restrict sign_bits,
|
|
666
667
|
const uint8_t* __restrict ex_code,
|
|
@@ -737,7 +738,6 @@ inline float ip_bitplane_avx512(
|
|
|
737
738
|
result += ip_scalar(sign_bits, ex_code, rotated_q, i, d, ex_bits, cb);
|
|
738
739
|
return result;
|
|
739
740
|
}
|
|
740
|
-
#endif // __BMI2__
|
|
741
741
|
|
|
742
742
|
} // namespace
|
|
743
743
|
|
|
@@ -749,19 +749,36 @@ float compute_inner_product<SIMDLevel::AVX512>(
|
|
|
749
749
|
size_t d,
|
|
750
750
|
size_t ex_bits,
|
|
751
751
|
float cb) {
|
|
752
|
+
if (ex_bits == 8) {
|
|
753
|
+
// RBQ9 has one byte per extra code: no bit-plane extraction or BMI2.
|
|
754
|
+
__m512 acc = _mm512_setzero_ps();
|
|
755
|
+
const __m512 weight = _mm512_set1_ps(256.f);
|
|
756
|
+
const __m512 offset = _mm512_set1_ps(cb);
|
|
757
|
+
size_t i = 0;
|
|
758
|
+
for (; i + 16 <= d; i += 16) {
|
|
759
|
+
uint16_t signs;
|
|
760
|
+
memcpy(&signs, sign_bits + i / 8, sizeof(signs));
|
|
761
|
+
const __m128i bytes = _mm_loadu_si128(
|
|
762
|
+
reinterpret_cast<const __m128i*>(ex_code + i));
|
|
763
|
+
__m512 recon = _mm512_cvtepi32_ps(_mm512_cvtepu8_epi32(bytes));
|
|
764
|
+
recon = _mm512_mask_add_ps(recon, signs, recon, weight);
|
|
765
|
+
acc = _mm512_fmadd_ps(
|
|
766
|
+
_mm512_loadu_ps(rotated_q + i),
|
|
767
|
+
_mm512_add_ps(recon, offset),
|
|
768
|
+
acc);
|
|
769
|
+
}
|
|
770
|
+
return _mm512_reduce_add_ps(acc) +
|
|
771
|
+
ip_scalar(sign_bits, ex_code, rotated_q, i, d, ex_bits, cb);
|
|
772
|
+
}
|
|
752
773
|
if (ex_bits == 1) {
|
|
753
774
|
return ip_1exbit_avx512(sign_bits, ex_code, rotated_q, d, cb);
|
|
754
775
|
}
|
|
755
776
|
|
|
756
|
-
#ifdef __BMI2__
|
|
757
777
|
if (ex_bits <= 7) {
|
|
758
778
|
return ip_bitplane_avx512(
|
|
759
779
|
sign_bits, ex_code, rotated_q, d, ex_bits, cb);
|
|
760
780
|
}
|
|
761
|
-
#endif
|
|
762
781
|
return ip_scalar(sign_bits, ex_code, rotated_q, 0, d, ex_bits, cb);
|
|
763
782
|
}
|
|
764
783
|
|
|
765
784
|
} // namespace faiss::rabitq::multibit
|
|
766
|
-
|
|
767
|
-
#endif // COMPILE_SIMD_AVX512
|
|
@@ -30,8 +30,6 @@
|
|
|
30
30
|
* the AVX512 implementation to avoid duplicating that code path.
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
|
-
#ifdef COMPILE_SIMD_AVX512_VPOPCNT
|
|
34
|
-
|
|
35
33
|
#include <faiss/utils/popcount.h>
|
|
36
34
|
#include <faiss/utils/rabitq_simd.h>
|
|
37
35
|
#include <immintrin.h>
|
|
@@ -63,6 +61,43 @@ uint64_t bitwise_xor_dot_product<SIMDLevel::AVX512>(
|
|
|
63
61
|
template <>
|
|
64
62
|
uint64_t popcount<SIMDLevel::AVX512>(const uint8_t* data, size_t size);
|
|
65
63
|
|
|
64
|
+
template <>
|
|
65
|
+
void bitwise_q4_batch_4<SIMDLevel::AVX512_VPOPCNT>(
|
|
66
|
+
const uint8_t* query,
|
|
67
|
+
const uint8_t* const* data,
|
|
68
|
+
size_t size,
|
|
69
|
+
BitwiseAndDotProductResult* results) {
|
|
70
|
+
__m512i dots[4], pops[4];
|
|
71
|
+
for (int i = 0; i < 4; ++i) {
|
|
72
|
+
dots[i] = pops[i] = _mm512_setzero_si512();
|
|
73
|
+
}
|
|
74
|
+
for (size_t off = 0; off < size; off += 64) {
|
|
75
|
+
const size_t count = std::min(size - off, size_t(64));
|
|
76
|
+
const __mmask64 mask =
|
|
77
|
+
count == 64 ? ~__mmask64(0) : (__mmask64(1) << count) - 1;
|
|
78
|
+
__m512i x[4];
|
|
79
|
+
for (int i = 0; i < 4; ++i) {
|
|
80
|
+
x[i] = _mm512_maskz_loadu_epi8(mask, data[i] + off);
|
|
81
|
+
pops[i] = _mm512_add_epi64(pops[i], _mm512_popcnt_epi64(x[i]));
|
|
82
|
+
}
|
|
83
|
+
for (int bit = 0; bit < 4; ++bit) {
|
|
84
|
+
// Load each query plane once for four independent database codes.
|
|
85
|
+
const __m512i q =
|
|
86
|
+
_mm512_maskz_loadu_epi8(mask, query + bit * size + off);
|
|
87
|
+
for (int i = 0; i < 4; ++i) {
|
|
88
|
+
const __m512i p =
|
|
89
|
+
_mm512_popcnt_epi64(_mm512_and_si512(q, x[i]));
|
|
90
|
+
dots[i] = _mm512_add_epi64(dots[i], _mm512_slli_epi64(p, bit));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
for (int i = 0; i < 4; ++i) {
|
|
95
|
+
results[i] = {
|
|
96
|
+
static_cast<uint64_t>(_mm512_reduce_add_epi64(dots[i])),
|
|
97
|
+
static_cast<uint64_t>(_mm512_reduce_add_epi64(pops[i]))};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
66
101
|
namespace {
|
|
67
102
|
|
|
68
103
|
// 512-bit popcount using AVX-512 VPOPCNTDQ (vpopcntq).
|
|
@@ -164,10 +199,11 @@ uint64_t bitwise_and_dot_product<SIMDLevel::AVX512_VPOPCNT>(
|
|
|
164
199
|
|
|
165
200
|
// 64-bit scalar tail.
|
|
166
201
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
167
|
-
|
|
202
|
+
uint64_t yv;
|
|
203
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
168
204
|
for (size_t j = 0; j < qb; j++) {
|
|
169
|
-
|
|
170
|
-
|
|
205
|
+
uint64_t qv;
|
|
206
|
+
std::memcpy(&qv, query + j * size + offset, sizeof(qv));
|
|
171
207
|
sum += static_cast<uint64_t>(popcount64(qv & yv)) << j;
|
|
172
208
|
}
|
|
173
209
|
}
|
|
@@ -255,11 +291,12 @@ BitwiseAndDotProductResult bitwise_and_dot_product_with_popcount<
|
|
|
255
291
|
popcount_sum += reduce_add_128(pop_128);
|
|
256
292
|
|
|
257
293
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
258
|
-
|
|
294
|
+
uint64_t yv;
|
|
295
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
259
296
|
popcount_sum += popcount64(yv);
|
|
260
297
|
for (size_t j = 0; j < qb; j++) {
|
|
261
|
-
|
|
262
|
-
|
|
298
|
+
uint64_t qv;
|
|
299
|
+
std::memcpy(&qv, query + j * size + offset, sizeof(qv));
|
|
263
300
|
dot_product += static_cast<uint64_t>(popcount64(qv & yv)) << j;
|
|
264
301
|
}
|
|
265
302
|
}
|
|
@@ -336,10 +373,11 @@ uint64_t bitwise_xor_dot_product<SIMDLevel::AVX512_VPOPCNT>(
|
|
|
336
373
|
sum += reduce_add_128(sum_128);
|
|
337
374
|
|
|
338
375
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
339
|
-
|
|
376
|
+
uint64_t yv;
|
|
377
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
340
378
|
for (size_t j = 0; j < qb; j++) {
|
|
341
|
-
|
|
342
|
-
|
|
379
|
+
uint64_t qv;
|
|
380
|
+
std::memcpy(&qv, query + j * size + offset, sizeof(qv));
|
|
343
381
|
sum += static_cast<uint64_t>(popcount64(qv ^ yv)) << j;
|
|
344
382
|
}
|
|
345
383
|
}
|
|
@@ -389,7 +427,8 @@ uint64_t popcount<SIMDLevel::AVX512_VPOPCNT>(const uint8_t* data, size_t size) {
|
|
|
389
427
|
sum += reduce_add_128(sum_128);
|
|
390
428
|
|
|
391
429
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
392
|
-
|
|
430
|
+
uint64_t yv;
|
|
431
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
393
432
|
sum += popcount64(yv);
|
|
394
433
|
}
|
|
395
434
|
for (; offset < size; ++offset) {
|
|
@@ -428,5 +467,3 @@ float compute_inner_product<SIMDLevel::AVX512_VPOPCNT>(
|
|
|
428
467
|
}
|
|
429
468
|
|
|
430
469
|
} // namespace faiss::rabitq::multibit
|
|
431
|
-
|
|
432
|
-
#endif // COMPILE_SIMD_AVX512_VPOPCNT
|
|
@@ -7,17 +7,78 @@
|
|
|
7
7
|
|
|
8
8
|
#include <faiss/utils/rabitq_simd.h>
|
|
9
9
|
|
|
10
|
-
#
|
|
10
|
+
#include <arm_neon.h>
|
|
11
|
+
|
|
12
|
+
#include <array>
|
|
13
|
+
|
|
14
|
+
#include <faiss/impl/FaissAssert.h>
|
|
11
15
|
|
|
12
16
|
namespace faiss::rabitq {
|
|
13
17
|
|
|
18
|
+
namespace {
|
|
19
|
+
|
|
20
|
+
// One accumulator per query bit plane. RaBitQuantizer caps qb at 8, so the
|
|
21
|
+
// accumulator arrays below are fixed size rather than heap allocated.
|
|
22
|
+
constexpr size_t kMaxQueryBits = 8;
|
|
23
|
+
|
|
24
|
+
inline uint32x4_t accumulate_popcount(uint32x4_t acc, uint8x16_t value) {
|
|
25
|
+
const uint16x8_t pair_counts = vpaddlq_u8(vcntq_u8(value));
|
|
26
|
+
return vpadalq_u16(acc, pair_counts);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
inline uint64_t reduce_popcount(uint32x4_t acc) {
|
|
30
|
+
return vaddlvq_u32(acc);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
} // namespace
|
|
34
|
+
|
|
14
35
|
template <>
|
|
15
36
|
uint64_t bitwise_and_dot_product<SIMDLevel::ARM_NEON>(
|
|
16
37
|
const uint8_t* query,
|
|
17
38
|
const uint8_t* data,
|
|
18
39
|
size_t size,
|
|
19
40
|
size_t qb) {
|
|
20
|
-
|
|
41
|
+
FAISS_THROW_IF_NOT(qb <= kMaxQueryBits);
|
|
42
|
+
std::array<uint32x4_t, kMaxQueryBits> accumulators;
|
|
43
|
+
for (size_t j = 0; j < qb; j++) {
|
|
44
|
+
accumulators[j] = vdupq_n_u32(0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
size_t offset = 0;
|
|
48
|
+
for (; offset + 16 <= size; offset += 16) {
|
|
49
|
+
const uint8x16_t value = vld1q_u8(data + offset);
|
|
50
|
+
for (size_t j = 0; j < qb; j++) {
|
|
51
|
+
const uint8x16_t query_value = vld1q_u8(query + j * size + offset);
|
|
52
|
+
accumulators[j] = accumulate_popcount(
|
|
53
|
+
accumulators[j], vandq_u8(query_value, value));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
uint64_t result = 0;
|
|
58
|
+
for (size_t j = 0; j < qb; j++) {
|
|
59
|
+
result += reduce_popcount(accumulators[j]) << j;
|
|
60
|
+
}
|
|
61
|
+
for (; offset + 8 <= size; offset += 8) {
|
|
62
|
+
uint64_t value;
|
|
63
|
+
memcpy(&value, data + offset, sizeof(value));
|
|
64
|
+
for (size_t j = 0; j < qb; j++) {
|
|
65
|
+
uint64_t query_value;
|
|
66
|
+
memcpy(&query_value,
|
|
67
|
+
query + j * size + offset,
|
|
68
|
+
sizeof(query_value));
|
|
69
|
+
result += static_cast<uint64_t>(popcount64(query_value & value))
|
|
70
|
+
<< j;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (; offset < size; offset++) {
|
|
74
|
+
const uint8_t value = data[offset];
|
|
75
|
+
for (size_t j = 0; j < qb; j++) {
|
|
76
|
+
result += static_cast<uint64_t>(
|
|
77
|
+
popcount32(query[j * size + offset] & value))
|
|
78
|
+
<< j;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
21
82
|
}
|
|
22
83
|
|
|
23
84
|
template <>
|
|
@@ -27,8 +88,52 @@ BitwiseAndDotProductResult bitwise_and_dot_product_with_popcount<
|
|
|
27
88
|
const uint8_t* data,
|
|
28
89
|
size_t size,
|
|
29
90
|
size_t qb) {
|
|
30
|
-
|
|
31
|
-
|
|
91
|
+
FAISS_THROW_IF_NOT(qb <= kMaxQueryBits);
|
|
92
|
+
std::array<uint32x4_t, kMaxQueryBits> dot_accumulators;
|
|
93
|
+
for (size_t j = 0; j < qb; j++) {
|
|
94
|
+
dot_accumulators[j] = vdupq_n_u32(0);
|
|
95
|
+
}
|
|
96
|
+
uint32x4_t popcount_accumulator = vdupq_n_u32(0);
|
|
97
|
+
|
|
98
|
+
size_t offset = 0;
|
|
99
|
+
for (; offset + 16 <= size; offset += 16) {
|
|
100
|
+
const uint8x16_t value = vld1q_u8(data + offset);
|
|
101
|
+
popcount_accumulator = accumulate_popcount(popcount_accumulator, value);
|
|
102
|
+
for (size_t j = 0; j < qb; j++) {
|
|
103
|
+
const uint8x16_t query_value = vld1q_u8(query + j * size + offset);
|
|
104
|
+
dot_accumulators[j] = accumulate_popcount(
|
|
105
|
+
dot_accumulators[j], vandq_u8(query_value, value));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
uint64_t dot_product = 0;
|
|
110
|
+
for (size_t j = 0; j < qb; j++) {
|
|
111
|
+
dot_product += reduce_popcount(dot_accumulators[j]) << j;
|
|
112
|
+
}
|
|
113
|
+
uint64_t popcount_sum = reduce_popcount(popcount_accumulator);
|
|
114
|
+
for (; offset + 8 <= size; offset += 8) {
|
|
115
|
+
uint64_t value;
|
|
116
|
+
memcpy(&value, data + offset, sizeof(value));
|
|
117
|
+
popcount_sum += popcount64(value);
|
|
118
|
+
for (size_t j = 0; j < qb; j++) {
|
|
119
|
+
uint64_t query_value;
|
|
120
|
+
memcpy(&query_value,
|
|
121
|
+
query + j * size + offset,
|
|
122
|
+
sizeof(query_value));
|
|
123
|
+
dot_product +=
|
|
124
|
+
static_cast<uint64_t>(popcount64(query_value & value)) << j;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
for (; offset < size; offset++) {
|
|
128
|
+
const uint8_t value = data[offset];
|
|
129
|
+
popcount_sum += popcount32(value);
|
|
130
|
+
for (size_t j = 0; j < qb; j++) {
|
|
131
|
+
dot_product += static_cast<uint64_t>(
|
|
132
|
+
popcount32(query[j * size + offset] & value))
|
|
133
|
+
<< j;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return {dot_product, popcount_sum};
|
|
32
137
|
}
|
|
33
138
|
|
|
34
139
|
template <>
|
|
@@ -37,18 +142,185 @@ uint64_t bitwise_xor_dot_product<SIMDLevel::ARM_NEON>(
|
|
|
37
142
|
const uint8_t* data,
|
|
38
143
|
size_t size,
|
|
39
144
|
size_t qb) {
|
|
40
|
-
|
|
145
|
+
FAISS_THROW_IF_NOT(qb <= kMaxQueryBits);
|
|
146
|
+
std::array<uint32x4_t, kMaxQueryBits> accumulators;
|
|
147
|
+
for (size_t j = 0; j < qb; j++) {
|
|
148
|
+
accumulators[j] = vdupq_n_u32(0);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
size_t offset = 0;
|
|
152
|
+
for (; offset + 16 <= size; offset += 16) {
|
|
153
|
+
const uint8x16_t value = vld1q_u8(data + offset);
|
|
154
|
+
for (size_t j = 0; j < qb; j++) {
|
|
155
|
+
const uint8x16_t query_value = vld1q_u8(query + j * size + offset);
|
|
156
|
+
accumulators[j] = accumulate_popcount(
|
|
157
|
+
accumulators[j], veorq_u8(query_value, value));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
uint64_t result = 0;
|
|
162
|
+
for (size_t j = 0; j < qb; j++) {
|
|
163
|
+
result += reduce_popcount(accumulators[j]) << j;
|
|
164
|
+
}
|
|
165
|
+
for (; offset + 8 <= size; offset += 8) {
|
|
166
|
+
uint64_t value;
|
|
167
|
+
memcpy(&value, data + offset, sizeof(value));
|
|
168
|
+
for (size_t j = 0; j < qb; j++) {
|
|
169
|
+
uint64_t query_value;
|
|
170
|
+
memcpy(&query_value,
|
|
171
|
+
query + j * size + offset,
|
|
172
|
+
sizeof(query_value));
|
|
173
|
+
result += static_cast<uint64_t>(popcount64(query_value ^ value))
|
|
174
|
+
<< j;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
for (; offset < size; offset++) {
|
|
178
|
+
const uint8_t value = data[offset];
|
|
179
|
+
for (size_t j = 0; j < qb; j++) {
|
|
180
|
+
result += static_cast<uint64_t>(
|
|
181
|
+
popcount32(query[j * size + offset] ^ value))
|
|
182
|
+
<< j;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
41
186
|
}
|
|
42
187
|
|
|
43
188
|
template <>
|
|
44
189
|
uint64_t popcount<SIMDLevel::ARM_NEON>(const uint8_t* data, size_t size) {
|
|
45
|
-
|
|
190
|
+
uint32x4_t accumulator = vdupq_n_u32(0);
|
|
191
|
+
size_t offset = 0;
|
|
192
|
+
for (; offset + 16 <= size; offset += 16) {
|
|
193
|
+
accumulator = accumulate_popcount(accumulator, vld1q_u8(data + offset));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
uint64_t result = reduce_popcount(accumulator);
|
|
197
|
+
for (; offset + 8 <= size; offset += 8) {
|
|
198
|
+
uint64_t value;
|
|
199
|
+
memcpy(&value, data + offset, sizeof(value));
|
|
200
|
+
result += popcount64(value);
|
|
201
|
+
}
|
|
202
|
+
for (; offset < size; offset++) {
|
|
203
|
+
result += popcount32(data[offset]);
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
46
206
|
}
|
|
47
207
|
|
|
48
208
|
} // namespace faiss::rabitq
|
|
49
209
|
|
|
50
210
|
namespace faiss::rabitq::multibit {
|
|
51
211
|
|
|
212
|
+
namespace {
|
|
213
|
+
|
|
214
|
+
inline float horizontal_sum(float32x4_t low, float32x4_t high) {
|
|
215
|
+
return vaddvq_f32(vaddq_f32(low, high));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
inline float ip_1exbit_neon(
|
|
219
|
+
const uint8_t* __restrict sign_bits,
|
|
220
|
+
const uint8_t* __restrict ex_code,
|
|
221
|
+
const float* __restrict rotated_q,
|
|
222
|
+
size_t d,
|
|
223
|
+
float cb) {
|
|
224
|
+
const uint32x4_t low_bit_positions = {1, 2, 4, 8};
|
|
225
|
+
const uint32x4_t high_bit_positions = {16, 32, 64, 128};
|
|
226
|
+
const uint32x4_t sign_weight = vdupq_n_u32(2);
|
|
227
|
+
const uint32x4_t ex_weight = vdupq_n_u32(1);
|
|
228
|
+
const float32x4_t bias = vdupq_n_f32(cb);
|
|
229
|
+
float32x4_t low_accumulator = vdupq_n_f32(0.0f);
|
|
230
|
+
float32x4_t high_accumulator = vdupq_n_f32(0.0f);
|
|
231
|
+
|
|
232
|
+
size_t i = 0;
|
|
233
|
+
for (; i + 8 <= d; i += 8) {
|
|
234
|
+
const uint32x4_t sign = vdupq_n_u32(sign_bits[i / 8]);
|
|
235
|
+
const uint32x4_t extra = vdupq_n_u32(ex_code[i / 8]);
|
|
236
|
+
|
|
237
|
+
const uint32x4_t low_values = vaddq_u32(
|
|
238
|
+
vandq_u32(vtstq_u32(sign, low_bit_positions), sign_weight),
|
|
239
|
+
vandq_u32(vtstq_u32(extra, low_bit_positions), ex_weight));
|
|
240
|
+
const uint32x4_t high_values = vaddq_u32(
|
|
241
|
+
vandq_u32(vtstq_u32(sign, high_bit_positions), sign_weight),
|
|
242
|
+
vandq_u32(vtstq_u32(extra, high_bit_positions), ex_weight));
|
|
243
|
+
|
|
244
|
+
const float32x4_t low_reconstruction =
|
|
245
|
+
vaddq_f32(vcvtq_f32_u32(low_values), bias);
|
|
246
|
+
const float32x4_t high_reconstruction =
|
|
247
|
+
vaddq_f32(vcvtq_f32_u32(high_values), bias);
|
|
248
|
+
low_accumulator = vfmaq_f32(
|
|
249
|
+
low_accumulator, vld1q_f32(rotated_q + i), low_reconstruction);
|
|
250
|
+
high_accumulator = vfmaq_f32(
|
|
251
|
+
high_accumulator,
|
|
252
|
+
vld1q_f32(rotated_q + i + 4),
|
|
253
|
+
high_reconstruction);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
float result = horizontal_sum(low_accumulator, high_accumulator);
|
|
257
|
+
result += ip_scalar(sign_bits, ex_code, rotated_q, i, d, 1, cb);
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
template <size_t ExBits>
|
|
262
|
+
inline float ip_multibit_neon(
|
|
263
|
+
const uint8_t* __restrict sign_bits,
|
|
264
|
+
const uint8_t* __restrict ex_code,
|
|
265
|
+
const float* __restrict rotated_q,
|
|
266
|
+
size_t d,
|
|
267
|
+
float cb) {
|
|
268
|
+
static_assert(ExBits >= 2 && ExBits <= 7);
|
|
269
|
+
const uint32x4_t low_bit_positions = {1, 2, 4, 8};
|
|
270
|
+
const uint32x4_t high_bit_positions = {16, 32, 64, 128};
|
|
271
|
+
const uint32x4_t sign_weight =
|
|
272
|
+
vdupq_n_u32(static_cast<uint32_t>(1u << ExBits));
|
|
273
|
+
const uint64x2_t code_mask =
|
|
274
|
+
vdupq_n_u64(static_cast<uint64_t>((1u << ExBits) - 1));
|
|
275
|
+
constexpr int64_t bit_width = static_cast<int64_t>(ExBits);
|
|
276
|
+
const int64x2_t shifts_01 = {0, -bit_width};
|
|
277
|
+
const int64x2_t shifts_23 = {-2 * bit_width, -3 * bit_width};
|
|
278
|
+
const int64x2_t shifts_45 = {-4 * bit_width, -5 * bit_width};
|
|
279
|
+
const int64x2_t shifts_67 = {-6 * bit_width, -7 * bit_width};
|
|
280
|
+
const float32x4_t bias = vdupq_n_f32(cb);
|
|
281
|
+
float32x4_t low_accumulator = vdupq_n_f32(0.0f);
|
|
282
|
+
float32x4_t high_accumulator = vdupq_n_f32(0.0f);
|
|
283
|
+
|
|
284
|
+
size_t i = 0;
|
|
285
|
+
for (; i + 8 <= d; i += 8) {
|
|
286
|
+
uint64_t packed_codes = 0;
|
|
287
|
+
memcpy(&packed_codes, ex_code + (i / 8) * ExBits, ExBits);
|
|
288
|
+
const uint64x2_t packed = vdupq_n_u64(packed_codes);
|
|
289
|
+
|
|
290
|
+
const uint32x4_t low_codes = vcombine_u32(
|
|
291
|
+
vmovn_u64(vandq_u64(vshlq_u64(packed, shifts_01), code_mask)),
|
|
292
|
+
vmovn_u64(vandq_u64(vshlq_u64(packed, shifts_23), code_mask)));
|
|
293
|
+
const uint32x4_t high_codes = vcombine_u32(
|
|
294
|
+
vmovn_u64(vandq_u64(vshlq_u64(packed, shifts_45), code_mask)),
|
|
295
|
+
vmovn_u64(vandq_u64(vshlq_u64(packed, shifts_67), code_mask)));
|
|
296
|
+
|
|
297
|
+
const uint32x4_t sign = vdupq_n_u32(sign_bits[i / 8]);
|
|
298
|
+
const uint32x4_t low_values = vaddq_u32(
|
|
299
|
+
low_codes,
|
|
300
|
+
vandq_u32(vtstq_u32(sign, low_bit_positions), sign_weight));
|
|
301
|
+
const uint32x4_t high_values = vaddq_u32(
|
|
302
|
+
high_codes,
|
|
303
|
+
vandq_u32(vtstq_u32(sign, high_bit_positions), sign_weight));
|
|
304
|
+
|
|
305
|
+
const float32x4_t low_reconstruction =
|
|
306
|
+
vaddq_f32(vcvtq_f32_u32(low_values), bias);
|
|
307
|
+
const float32x4_t high_reconstruction =
|
|
308
|
+
vaddq_f32(vcvtq_f32_u32(high_values), bias);
|
|
309
|
+
low_accumulator = vfmaq_f32(
|
|
310
|
+
low_accumulator, vld1q_f32(rotated_q + i), low_reconstruction);
|
|
311
|
+
high_accumulator = vfmaq_f32(
|
|
312
|
+
high_accumulator,
|
|
313
|
+
vld1q_f32(rotated_q + i + 4),
|
|
314
|
+
high_reconstruction);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
float result = horizontal_sum(low_accumulator, high_accumulator);
|
|
318
|
+
result += ip_scalar(sign_bits, ex_code, rotated_q, i, d, ExBits, cb);
|
|
319
|
+
return result;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
} // namespace
|
|
323
|
+
|
|
52
324
|
template <>
|
|
53
325
|
float compute_inner_product<SIMDLevel::ARM_NEON>(
|
|
54
326
|
const uint8_t* __restrict sign_bits,
|
|
@@ -57,10 +329,25 @@ float compute_inner_product<SIMDLevel::ARM_NEON>(
|
|
|
57
329
|
size_t d,
|
|
58
330
|
size_t ex_bits,
|
|
59
331
|
float cb) {
|
|
60
|
-
|
|
61
|
-
|
|
332
|
+
if (ex_bits == 1) {
|
|
333
|
+
return ip_1exbit_neon(sign_bits, ex_code, rotated_q, d, cb);
|
|
334
|
+
}
|
|
335
|
+
switch (ex_bits) {
|
|
336
|
+
case 2:
|
|
337
|
+
return ip_multibit_neon<2>(sign_bits, ex_code, rotated_q, d, cb);
|
|
338
|
+
case 3:
|
|
339
|
+
return ip_multibit_neon<3>(sign_bits, ex_code, rotated_q, d, cb);
|
|
340
|
+
case 4:
|
|
341
|
+
return ip_multibit_neon<4>(sign_bits, ex_code, rotated_q, d, cb);
|
|
342
|
+
case 5:
|
|
343
|
+
return ip_multibit_neon<5>(sign_bits, ex_code, rotated_q, d, cb);
|
|
344
|
+
case 6:
|
|
345
|
+
return ip_multibit_neon<6>(sign_bits, ex_code, rotated_q, d, cb);
|
|
346
|
+
case 7:
|
|
347
|
+
return ip_multibit_neon<7>(sign_bits, ex_code, rotated_q, d, cb);
|
|
348
|
+
default:
|
|
349
|
+
return ip_scalar(sign_bits, ex_code, rotated_q, 0, d, ex_bits, cb);
|
|
350
|
+
}
|
|
62
351
|
}
|
|
63
352
|
|
|
64
353
|
} // namespace faiss::rabitq::multibit
|
|
65
|
-
|
|
66
|
-
#endif // COMPILE_SIMD_ARM_NEON
|
|
@@ -9,8 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
#include <faiss/utils/rabitq_simd.h>
|
|
11
11
|
|
|
12
|
-
#ifdef COMPILE_SIMD_RISCV_RVV
|
|
13
|
-
|
|
14
12
|
#include <riscv_vector.h>
|
|
15
13
|
|
|
16
14
|
namespace faiss::rabitq {
|
|
@@ -188,5 +186,3 @@ compute_inner_product<SIMDLevel::RISCV_RVV>(
|
|
|
188
186
|
}
|
|
189
187
|
|
|
190
188
|
} // namespace faiss::rabitq::multibit
|
|
191
|
-
|
|
192
|
-
#endif // COMPILE_SIMD_RISCV_RVV
|
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
#ifdef COMPILE_SIMD_AVX2
|
|
9
|
-
|
|
10
8
|
#include <faiss/utils/simd_impl/super_kmeans_kernels.h>
|
|
11
9
|
|
|
12
10
|
#include <immintrin.h>
|
|
@@ -53,5 +51,3 @@ float block_l2<SIMDLevel::AVX2>(const float* x, const float* y, int n) {
|
|
|
53
51
|
|
|
54
52
|
} // namespace detail
|
|
55
53
|
} // namespace faiss
|
|
56
|
-
|
|
57
|
-
#endif // COMPILE_SIMD_AVX2
|
|
@@ -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
|
|
9
|
-
|
|
10
8
|
#include <faiss/utils/simd_impl/super_kmeans_kernels.h>
|
|
11
9
|
|
|
12
10
|
#include <immintrin.h>
|
|
@@ -41,5 +39,3 @@ float block_l2<SIMDLevel::AVX512>(const float* x, const float* y, int n) {
|
|
|
41
39
|
|
|
42
40
|
} // namespace detail
|
|
43
41
|
} // namespace faiss
|
|
44
|
-
|
|
45
|
-
#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_ARM_SVE
|
|
9
|
-
|
|
10
8
|
#include <faiss/utils/simd_impl/super_kmeans_kernels.h>
|
|
11
9
|
|
|
12
10
|
#include <arm_sve.h>
|
|
@@ -30,5 +28,3 @@ float block_l2<SIMDLevel::ARM_SVE>(const float* x, const float* y, int n) {
|
|
|
30
28
|
|
|
31
29
|
} // namespace detail
|
|
32
30
|
} // namespace faiss
|
|
33
|
-
|
|
34
|
-
#endif // COMPILE_SIMD_ARM_SVE
|