faiss 0.6.2 → 0.6.4
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 +8 -0
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +3 -1
- data/vendor/faiss/faiss/Clustering.cpp +9 -1
- data/vendor/faiss/faiss/Clustering.h +8 -0
- data/vendor/faiss/faiss/IVFlib.cpp +14 -3
- data/vendor/faiss/faiss/Index.h +2 -2
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +9 -10
- data/vendor/faiss/faiss/IndexAdditiveQuantizerFastScan.cpp +2 -3
- data/vendor/faiss/faiss/IndexBinaryFromFloat.cpp +24 -4
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +16 -145
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +0 -6
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +8 -18
- data/vendor/faiss/faiss/IndexBinaryIVF.h +8 -1
- data/vendor/faiss/faiss/IndexEDEN.cpp +273 -0
- data/vendor/faiss/faiss/IndexEDEN.h +57 -0
- data/vendor/faiss/faiss/IndexFastScan.cpp +15 -4
- data/vendor/faiss/faiss/IndexFlat.cpp +21 -54
- data/vendor/faiss/faiss/IndexFlat.h +2 -2
- data/vendor/faiss/faiss/IndexHNSW.cpp +311 -102
- data/vendor/faiss/faiss/IndexHNSW.h +31 -7
- data/vendor/faiss/faiss/IndexIDMap.cpp +26 -8
- data/vendor/faiss/faiss/IndexIDMap.h +2 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +36 -10
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp +3 -4
- data/vendor/faiss/faiss/IndexIVFEDEN.cpp +302 -0
- data/vendor/faiss/faiss/IndexIVFEDEN.h +70 -0
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +5 -6
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +3 -4
- data/vendor/faiss/faiss/IndexIVFIndependentQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/IndexIVFPQ.cpp +49 -23
- data/vendor/faiss/faiss/IndexIVFPQ.h +11 -0
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +0 -1
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +19 -49
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +180 -76
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -4
- data/vendor/faiss/faiss/IndexIVFSpectralHash.cpp +8 -6
- data/vendor/faiss/faiss/IndexLSH.cpp +2 -3
- data/vendor/faiss/faiss/IndexLattice.cpp +5 -0
- data/vendor/faiss/faiss/IndexNNDescent.cpp +9 -2
- data/vendor/faiss/faiss/IndexNSG.cpp +7 -2
- data/vendor/faiss/faiss/IndexPQ.cpp +6 -8
- data/vendor/faiss/faiss/IndexPreTransform.cpp +15 -0
- data/vendor/faiss/faiss/IndexRaBitQ.cpp +2 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +1 -2
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +5 -1
- data/vendor/faiss/faiss/IndexRefine.cpp +30 -1
- data/vendor/faiss/faiss/IndexReplicas.cpp +1 -2
- data/vendor/faiss/faiss/IndexShards.cpp +5 -5
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +6 -5
- data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
- data/vendor/faiss/faiss/SuperKMeans.cpp +286 -247
- data/vendor/faiss/faiss/SuperKMeans.h +33 -2
- data/vendor/faiss/faiss/VectorTransform.cpp +71 -2
- data/vendor/faiss/faiss/VectorTransform.h +3 -0
- data/vendor/faiss/faiss/clone_index.cpp +8 -0
- data/vendor/faiss/faiss/factory_tools.cpp +47 -4
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +1 -5
- data/vendor/faiss/faiss/gpu/GpuDistance.h +2 -5
- data/vendor/faiss/faiss/gpu/GpuIndex.h +38 -16
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +71 -1
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +17 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVFScalarQuantizer.h +16 -0
- data/vendor/faiss/faiss/gpu/perf/PerfClustering.cpp +1 -1
- data/vendor/faiss/faiss/gpu/perf/PerfIVFPQAdd.cpp +2 -2
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFScalarQuantizer.cpp +180 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h +1 -5
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +88 -0
- data/vendor/faiss/faiss/gpu_metal/impl/MetalIVFPQ.h +134 -0
- data/vendor/faiss/faiss/impl/AdditiveQuantizer.cpp +1 -1
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +7 -4
- data/vendor/faiss/faiss/impl/DistanceComputer.h +34 -0
- data/vendor/faiss/faiss/impl/EDENQuantizer.h +119 -0
- data/vendor/faiss/faiss/impl/HNSW.cpp +528 -267
- data/vendor/faiss/faiss/impl/HNSW.h +46 -7
- data/vendor/faiss/faiss/impl/IDSelector.h +44 -0
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/impl/NNDescent.cpp +10 -3
- data/vendor/faiss/faiss/impl/NSG.cpp +3 -1
- data/vendor/faiss/faiss/impl/Panorama.h +20 -9
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +38 -26
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +45 -37
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +239 -72
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +66 -4
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +4 -13
- data/vendor/faiss/faiss/impl/ResultHandler.h +34 -34
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +287 -84
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +26 -10
- data/vendor/faiss/faiss/impl/ThreadedIndex-inl.h +2 -2
- data/vendor/faiss/faiss/impl/VisitedTable.cpp +22 -2
- data/vendor/faiss/faiss/impl/VisitedTable.h +20 -0
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryIVF_impl.h +90 -14
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
- data/vendor/faiss/faiss/impl/expanded_scanners.h +5 -1
- data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +1 -0
- data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +35 -2
- data/vendor/faiss/faiss/impl/hnsw/LockVector.cpp +1 -1
- data/vendor/faiss/faiss/impl/index_read.cpp +491 -50
- data/vendor/faiss/faiss/impl/index_write.cpp +86 -30
- data/vendor/faiss/faiss/impl/lattice_Zn.cpp +8 -9
- data/vendor/faiss/faiss/impl/platform_macros.h +3 -1
- data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +284 -0
- data/vendor/faiss/faiss/impl/polysemous_training/dispatch.h +115 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +73 -39
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp +0 -1
- data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +26 -15
- data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +4 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +4 -4
- data/vendor/faiss/faiss/impl/result_handler/ResultHandler.cpp +195 -0
- data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +133 -0
- data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +281 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +72 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +228 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp +887 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +2 -2
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +9 -8
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +90 -24
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +30 -30
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +4 -5
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +101 -34
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +169 -13
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +125 -26
- data/vendor/faiss/faiss/impl/simd_dispatch.h +70 -31
- data/vendor/faiss/faiss/index_factory.cpp +40 -7
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +9 -6
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +29 -8
- data/vendor/faiss/faiss/python/python_callbacks.cpp +3 -1
- data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +60 -0
- data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +26 -1
- data/vendor/faiss/faiss/svs/IndexSVSFlat.h +13 -0
- data/vendor/faiss/faiss/svs/IndexSVSIVF.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSIVFLeanVec.cpp +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +47 -5
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +23 -3
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +4 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +2 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +10 -4
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +2 -1
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
- data/vendor/faiss/faiss/utils/distances.cpp +30 -11
- data/vendor/faiss/faiss/utils/distances_dispatch.h +30 -24
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +1 -1
- data/vendor/faiss/faiss/utils/distances_simd.cpp +4 -3
- data/vendor/faiss/faiss/utils/extra_distances.cpp +4 -14
- data/vendor/faiss/faiss/utils/extra_distances.h +1 -2
- data/vendor/faiss/faiss/utils/hamming.cpp +16 -10
- data/vendor/faiss/faiss/utils/hamming.h +10 -1
- data/vendor/faiss/faiss/utils/hamming_distance/common.h +14 -3
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_vpopcnt.cpp +24 -0
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +1 -1
- data/vendor/faiss/faiss/utils/hamming_distance/{hamming_computer-avx512_spr.h → hamming_computer-avx512_vpopcnt.h} +85 -24
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +141 -0
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +29 -8
- data/vendor/faiss/faiss/utils/rabitq_simd.h +202 -0
- data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +194 -30
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +0 -1
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +263 -15
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +198 -18
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +330 -40
- data/vendor/faiss/faiss/utils/simd_impl/{rabitq_avx512_spr.cpp → rabitq_avx512_vpopcnt.cpp} +112 -23
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +11 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +143 -6
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_dispatch.h +2 -7
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels.h +6 -1
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_sve.cpp +34 -0
- data/vendor/faiss/faiss/utils/simd_levels.cpp +196 -47
- data/vendor/faiss/faiss/utils/simd_levels.h +33 -8
- data/vendor/faiss/faiss/utils/utils.cpp +9 -27
- metadata +21 -5
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_spr.cpp +0 -15
|
@@ -36,7 +36,8 @@ struct IndexSVSVamanaLeanVec : IndexSVSVamana {
|
|
|
36
36
|
MetricType metric = METRIC_L2,
|
|
37
37
|
size_t leanvec_dims = 0,
|
|
38
38
|
SVSStorageKind storage = SVSStorageKind::SVS_LeanVec4x4,
|
|
39
|
-
bool is_static = false
|
|
39
|
+
bool is_static = false,
|
|
40
|
+
bool store_vectors = true);
|
|
40
41
|
|
|
41
42
|
~IndexSVSVamanaLeanVec() override;
|
|
42
43
|
|
|
@@ -291,6 +291,11 @@ void exhaustive_inner_product_seq(
|
|
|
291
291
|
BlockResultHandler& res) {
|
|
292
292
|
using SingleResultHandler =
|
|
293
293
|
typename BlockResultHandler::SingleResultHandler;
|
|
294
|
+
|
|
295
|
+
if (nx == 0) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
|
|
294
299
|
[[maybe_unused]] int nt = std::min(int(nx), omp_get_max_threads());
|
|
295
300
|
|
|
296
301
|
#pragma omp parallel num_threads(nt)
|
|
@@ -327,6 +332,11 @@ void exhaustive_L2sqr_seq(
|
|
|
327
332
|
BlockResultHandler& res) {
|
|
328
333
|
using SingleResultHandler =
|
|
329
334
|
typename BlockResultHandler::SingleResultHandler;
|
|
335
|
+
|
|
336
|
+
if (nx == 0) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
330
340
|
[[maybe_unused]] int nt = std::min(int(nx), omp_get_max_threads());
|
|
331
341
|
|
|
332
342
|
#pragma omp parallel num_threads(nt)
|
|
@@ -531,15 +541,19 @@ void exhaustive_L2sqr_blas<Top1BlockResultHandler<CMax<float, int64_t>>>(
|
|
|
531
541
|
return;
|
|
532
542
|
}
|
|
533
543
|
|
|
534
|
-
with_selected_simd_levels<
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
544
|
+
with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
545
|
+
[&]<SIMDLevel SL>() {
|
|
546
|
+
if constexpr (
|
|
547
|
+
SL == SIMDLevel::AVX2 || SL == SIMDLevel::AVX512 ||
|
|
548
|
+
SL == SIMDLevel::ARM_SVE) {
|
|
549
|
+
exhaustive_L2sqr_blas_cmax<SL>(
|
|
550
|
+
x, y, d, nx, ny, res, y_norms);
|
|
551
|
+
} else {
|
|
552
|
+
exhaustive_L2sqr_blas_default_impl<
|
|
553
|
+
Top1BlockResultHandler<CMax<float, int64_t>>>(
|
|
554
|
+
x, y, d, nx, ny, res, y_norms);
|
|
555
|
+
}
|
|
556
|
+
});
|
|
543
557
|
}
|
|
544
558
|
|
|
545
559
|
struct Run_search_inner_product {
|
|
@@ -551,7 +565,11 @@ struct Run_search_inner_product {
|
|
|
551
565
|
size_t d,
|
|
552
566
|
size_t nx,
|
|
553
567
|
size_t ny) {
|
|
554
|
-
|
|
568
|
+
// ny == 0 goes to the sequential path: it guards only on nx, so its
|
|
569
|
+
// per-query begin()/end() still runs and each handler writes its own
|
|
570
|
+
// neutral distance and -1 label. The BLAS path instead returns early
|
|
571
|
+
// on ny == 0, before the handler is initialized.
|
|
572
|
+
if (res.sel || ny == 0 ||
|
|
555
573
|
nx * d < static_cast<size_t>(distance_compute_blas_threshold)) {
|
|
556
574
|
exhaustive_inner_product_seq(x, y, d, nx, ny, res);
|
|
557
575
|
} else {
|
|
@@ -570,7 +588,8 @@ struct Run_search_L2sqr {
|
|
|
570
588
|
size_t nx,
|
|
571
589
|
size_t ny,
|
|
572
590
|
const float* y_norm2) {
|
|
573
|
-
|
|
591
|
+
// See the note on ny == 0 in Run_search_inner_product.
|
|
592
|
+
if (res.sel || ny == 0 ||
|
|
574
593
|
nx * d < static_cast<size_t>(distance_compute_blas_threshold)) {
|
|
575
594
|
exhaustive_L2sqr_seq(x, y, d, nx, ny, res);
|
|
576
595
|
} else {
|
|
@@ -29,22 +29,22 @@
|
|
|
29
29
|
namespace faiss {
|
|
30
30
|
|
|
31
31
|
inline float fvec_L1_dispatch(const float* x, const float* y, size_t d) {
|
|
32
|
-
return with_selected_simd_levels<
|
|
32
|
+
return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
33
33
|
[&]<SIMDLevel SL>() { return fvec_L1<SL>(x, y, d); });
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
inline float fvec_Linf_dispatch(const float* x, const float* y, size_t d) {
|
|
37
|
-
return with_selected_simd_levels<
|
|
37
|
+
return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
38
38
|
[&]<SIMDLevel SL>() { return fvec_Linf<SL>(x, y, d); });
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
inline float fvec_norm_L2sqr_dispatch(const float* x, size_t d) {
|
|
42
|
-
return with_selected_simd_levels<
|
|
42
|
+
return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
43
43
|
[&]<SIMDLevel SL>() { return fvec_norm_L2sqr<SL>(x, d); });
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
inline float fvec_L2sqr_dispatch(const float* x, const float* y, size_t d) {
|
|
47
|
-
return with_selected_simd_levels<
|
|
47
|
+
return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
48
48
|
[&]<SIMDLevel SL>() { return fvec_L2sqr<SL>(x, y, d); });
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -52,7 +52,7 @@ inline float fvec_inner_product_dispatch(
|
|
|
52
52
|
const float* x,
|
|
53
53
|
const float* y,
|
|
54
54
|
size_t d) {
|
|
55
|
-
return with_selected_simd_levels<
|
|
55
|
+
return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
56
56
|
[&]<SIMDLevel SL>() { return fvec_inner_product<SL>(x, y, d); });
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -67,10 +67,11 @@ inline void fvec_inner_product_batch_4_dispatch(
|
|
|
67
67
|
float& dis1,
|
|
68
68
|
float& dis2,
|
|
69
69
|
float& dis3) {
|
|
70
|
-
with_selected_simd_levels<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
71
|
+
[&]<SIMDLevel SL>() {
|
|
72
|
+
fvec_inner_product_batch_4<SL>(
|
|
73
|
+
x, y0, y1, y2, y3, d, dis0, dis1, dis2, dis3);
|
|
74
|
+
});
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
inline void fvec_L2sqr_batch_4_dispatch(
|
|
@@ -84,9 +85,11 @@ inline void fvec_L2sqr_batch_4_dispatch(
|
|
|
84
85
|
float& dis1,
|
|
85
86
|
float& dis2,
|
|
86
87
|
float& dis3) {
|
|
87
|
-
with_selected_simd_levels<
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
89
|
+
[&]<SIMDLevel SL>() {
|
|
90
|
+
fvec_L2sqr_batch_4<SL>(
|
|
91
|
+
x, y0, y1, y2, y3, d, dis0, dis1, dis2, dis3);
|
|
92
|
+
});
|
|
90
93
|
}
|
|
91
94
|
|
|
92
95
|
inline void fvec_L2sqr_ny_transposed_dispatch(
|
|
@@ -97,9 +100,11 @@ inline void fvec_L2sqr_ny_transposed_dispatch(
|
|
|
97
100
|
size_t d,
|
|
98
101
|
size_t d_offset,
|
|
99
102
|
size_t ny) {
|
|
100
|
-
with_selected_simd_levels<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
104
|
+
[&]<SIMDLevel SL>() {
|
|
105
|
+
fvec_L2sqr_ny_transposed<SL>(
|
|
106
|
+
dis, x, y, y_sqlen, d, d_offset, ny);
|
|
107
|
+
});
|
|
103
108
|
}
|
|
104
109
|
|
|
105
110
|
inline void fvec_inner_products_ny_dispatch(
|
|
@@ -108,9 +113,10 @@ inline void fvec_inner_products_ny_dispatch(
|
|
|
108
113
|
const float* y,
|
|
109
114
|
size_t d,
|
|
110
115
|
size_t ny) {
|
|
111
|
-
with_selected_simd_levels<
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
117
|
+
[&]<SIMDLevel SL>() {
|
|
118
|
+
fvec_inner_products_ny<SL>(ip, x, y, d, ny);
|
|
119
|
+
});
|
|
114
120
|
}
|
|
115
121
|
|
|
116
122
|
inline void fvec_L2sqr_ny_dispatch(
|
|
@@ -119,7 +125,7 @@ inline void fvec_L2sqr_ny_dispatch(
|
|
|
119
125
|
const float* y,
|
|
120
126
|
size_t d,
|
|
121
127
|
size_t ny) {
|
|
122
|
-
with_selected_simd_levels<
|
|
128
|
+
with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
123
129
|
[&]<SIMDLevel SL>() { fvec_L2sqr_ny<SL>(dis, x, y, d, ny); });
|
|
124
130
|
}
|
|
125
131
|
|
|
@@ -129,7 +135,7 @@ inline size_t fvec_L2sqr_ny_nearest_dispatch(
|
|
|
129
135
|
const float* y,
|
|
130
136
|
size_t d,
|
|
131
137
|
size_t ny) {
|
|
132
|
-
return with_selected_simd_levels<
|
|
138
|
+
return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
133
139
|
[&]<SIMDLevel SL>() {
|
|
134
140
|
return fvec_L2sqr_ny_nearest<SL>(
|
|
135
141
|
distances_tmp_buffer, x, y, d, ny);
|
|
@@ -144,7 +150,7 @@ inline size_t fvec_L2sqr_ny_nearest_y_transposed_dispatch(
|
|
|
144
150
|
size_t d,
|
|
145
151
|
size_t d_offset,
|
|
146
152
|
size_t ny) {
|
|
147
|
-
return with_selected_simd_levels<
|
|
153
|
+
return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
148
154
|
[&]<SIMDLevel SL>() {
|
|
149
155
|
return fvec_L2sqr_ny_nearest_y_transposed<SL>(
|
|
150
156
|
distances_tmp_buffer, x, y, y_sqlen, d, d_offset, ny);
|
|
@@ -157,7 +163,7 @@ inline void fvec_madd_dispatch(
|
|
|
157
163
|
float bf,
|
|
158
164
|
const float* b,
|
|
159
165
|
float* c) {
|
|
160
|
-
with_selected_simd_levels<
|
|
166
|
+
with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
161
167
|
[&]<SIMDLevel SL>() { fvec_madd<SL>(n, a, bf, b, c); });
|
|
162
168
|
}
|
|
163
169
|
|
|
@@ -167,7 +173,7 @@ inline int fvec_madd_and_argmin_dispatch(
|
|
|
167
173
|
float bf,
|
|
168
174
|
const float* b,
|
|
169
175
|
float* c) {
|
|
170
|
-
return with_selected_simd_levels<
|
|
176
|
+
return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
171
177
|
[&]<SIMDLevel SL>() {
|
|
172
178
|
return fvec_madd_and_argmin<SL>(n, a, bf, b, c);
|
|
173
179
|
});
|
|
@@ -241,7 +247,7 @@ auto with_VectorDistance(
|
|
|
241
247
|
if constexpr (!has_simd) {
|
|
242
248
|
return call.template operator()<SIMDLevel::NONE>();
|
|
243
249
|
} else {
|
|
244
|
-
return
|
|
250
|
+
return with_simd_level_with_sve(call);
|
|
245
251
|
}
|
|
246
252
|
};
|
|
247
253
|
return with_metric_type(metric, dispatch_metric);
|
|
@@ -51,7 +51,7 @@ bool exhaustive_L2sqr_fused_cmax(
|
|
|
51
51
|
return true;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
return with_selected_simd_levels<
|
|
54
|
+
return with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE>(
|
|
55
55
|
[&]<SIMDLevel SL>() {
|
|
56
56
|
return exhaustive_L2sqr_fused_cmax<SL>(
|
|
57
57
|
x, y, d, nx, ny, res, y_norms);
|
|
@@ -10,18 +10,19 @@
|
|
|
10
10
|
#include <faiss/utils/distances.h>
|
|
11
11
|
|
|
12
12
|
#include <cmath>
|
|
13
|
-
#include <cstdio>
|
|
14
13
|
#include <cstring>
|
|
15
14
|
|
|
16
|
-
#include <faiss/impl/FaissAssert.h>
|
|
17
15
|
#include <faiss/impl/simdlib/simdlib_dispatch.h>
|
|
18
16
|
|
|
19
17
|
#define THE_SIMD_LEVEL SIMDLevel::NONE
|
|
20
18
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
21
19
|
#include <faiss/utils/simd_impl/distances_autovec-inl.h>
|
|
22
20
|
|
|
21
|
+
// This TU is the SIMDLevel::NONE build of the specializations that
|
|
22
|
+
// distances_simdlib256.h emits, so the include is required despite no symbol
|
|
23
|
+
// being named directly here.
|
|
23
24
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
24
|
-
#include <faiss/utils/simd_impl/distances_simdlib256.h>
|
|
25
|
+
#include <faiss/utils/simd_impl/distances_simdlib256.h> // IWYU pragma: keep
|
|
25
26
|
|
|
26
27
|
namespace faiss {
|
|
27
28
|
|
|
@@ -29,11 +29,9 @@ namespace {
|
|
|
29
29
|
template <class VD>
|
|
30
30
|
struct ExtraDistanceComputer : FlatCodesDistanceComputer {
|
|
31
31
|
VD vd;
|
|
32
|
-
idx_t nb;
|
|
33
|
-
const float* q;
|
|
34
|
-
const float* b;
|
|
35
32
|
|
|
36
33
|
float symmetric_dis(idx_t i, idx_t j) final {
|
|
34
|
+
const float* b = (const float*)codes;
|
|
37
35
|
return vd(b + j * vd.d, b + i * vd.d);
|
|
38
36
|
}
|
|
39
37
|
|
|
@@ -41,16 +39,9 @@ struct ExtraDistanceComputer : FlatCodesDistanceComputer {
|
|
|
41
39
|
return vd(q, (float*)code);
|
|
42
40
|
}
|
|
43
41
|
|
|
44
|
-
ExtraDistanceComputer(
|
|
45
|
-
const VD& vd_in,
|
|
46
|
-
const float* xb,
|
|
47
|
-
size_t nb_in,
|
|
48
|
-
const float* q_in = nullptr)
|
|
42
|
+
ExtraDistanceComputer(const VD& vd_in, const float* xb)
|
|
49
43
|
: FlatCodesDistanceComputer((uint8_t*)xb, vd_in.d * sizeof(float)),
|
|
50
|
-
vd(vd_in)
|
|
51
|
-
nb(nb_in),
|
|
52
|
-
q(q_in),
|
|
53
|
-
b(xb) {}
|
|
44
|
+
vd(vd_in) {}
|
|
54
45
|
|
|
55
46
|
void set_query(const float* x) override {
|
|
56
47
|
q = x;
|
|
@@ -149,11 +140,10 @@ FlatCodesDistanceComputer* get_extra_distance_computer(
|
|
|
149
140
|
size_t d,
|
|
150
141
|
MetricType mt,
|
|
151
142
|
float metric_arg,
|
|
152
|
-
size_t nb,
|
|
153
143
|
const float* xb) {
|
|
154
144
|
return with_VectorDistance(
|
|
155
145
|
d, mt, metric_arg, [&](auto vd) -> FlatCodesDistanceComputer* {
|
|
156
|
-
return new ExtraDistanceComputer<decltype(vd)>(vd, xb
|
|
146
|
+
return new ExtraDistanceComputer<decltype(vd)>(vd, xb);
|
|
157
147
|
});
|
|
158
148
|
}
|
|
159
149
|
|
|
@@ -49,12 +49,11 @@ void knn_extra_metrics(
|
|
|
49
49
|
const IDSelector* sel = nullptr);
|
|
50
50
|
|
|
51
51
|
/** get a DistanceComputer that refers to this type of distance and
|
|
52
|
-
* indexes a flat array
|
|
52
|
+
* indexes a flat array */
|
|
53
53
|
FlatCodesDistanceComputer* get_extra_distance_computer(
|
|
54
54
|
size_t d,
|
|
55
55
|
MetricType mt,
|
|
56
56
|
float metric_arg,
|
|
57
|
-
size_t nb,
|
|
58
57
|
const float* xb);
|
|
59
58
|
|
|
60
59
|
/// Dispatch to a lambda with MetricType as a compile-time constant.
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
// Scalar (NONE) fallback — only needs the generic specializations.
|
|
34
34
|
#define THE_SIMD_LEVEL SIMDLevel::NONE
|
|
35
35
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
36
|
-
#include <faiss/utils/hamming_distance/hamming_computer-generic.h>
|
|
36
|
+
#include <faiss/utils/hamming_distance/hamming_computer-generic.h> // IWYU pragma: keep
|
|
37
37
|
#include <faiss/utils/hamming_distance/hamming_impl.h>
|
|
38
38
|
#undef THE_SIMD_LEVEL
|
|
39
39
|
|
|
@@ -146,8 +146,14 @@ void hammings(
|
|
|
146
146
|
size_t nb,
|
|
147
147
|
size_t ncodes,
|
|
148
148
|
hamdis_t* __restrict dis) {
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
|
|
150
|
+
// Ragged sizes have their own kernel; keeping it out of
|
|
151
|
+
// hammings_fixSL() leaves the word-level paths untouched.
|
|
152
|
+
if (ncodes % 8 != 0) {
|
|
153
|
+
hammings_ragged_fixSL<SL>(a, b, na, nb, ncodes, dis);
|
|
154
|
+
} else {
|
|
155
|
+
hammings_fixSL<SL>(a, b, na, nb, ncodes, dis);
|
|
156
|
+
}
|
|
151
157
|
});
|
|
152
158
|
}
|
|
153
159
|
|
|
@@ -170,7 +176,7 @@ void hammings_knn_hc(
|
|
|
170
176
|
int order,
|
|
171
177
|
ApproxTopK_mode_t approx_topk_mode,
|
|
172
178
|
const faiss::IDSelector* sel) {
|
|
173
|
-
|
|
179
|
+
with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
|
|
174
180
|
hammings_knn_hc_fixSL<SL>(
|
|
175
181
|
ha, a, b, nb, ncodes, order, approx_topk_mode, sel);
|
|
176
182
|
});
|
|
@@ -186,7 +192,7 @@ void hammings_knn_mc(
|
|
|
186
192
|
int32_t* __restrict distances,
|
|
187
193
|
int64_t* __restrict labels,
|
|
188
194
|
const faiss::IDSelector* sel) {
|
|
189
|
-
|
|
195
|
+
with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
|
|
190
196
|
hammings_knn_mc_fixSL<SL>(
|
|
191
197
|
a, b, na, nb, k, ncodes, distances, labels, sel);
|
|
192
198
|
});
|
|
@@ -201,7 +207,7 @@ void hamming_range_search(
|
|
|
201
207
|
size_t code_size,
|
|
202
208
|
RangeSearchResult* result,
|
|
203
209
|
const faiss::IDSelector* sel) {
|
|
204
|
-
|
|
210
|
+
with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
|
|
205
211
|
hamming_range_search_fixSL<SL>(
|
|
206
212
|
a, b, na, nb, radius, code_size, result, sel);
|
|
207
213
|
});
|
|
@@ -215,7 +221,7 @@ void hamming_count_thres(
|
|
|
215
221
|
hamdis_t ht,
|
|
216
222
|
size_t ncodes,
|
|
217
223
|
size_t* nptr) {
|
|
218
|
-
|
|
224
|
+
with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
|
|
219
225
|
hamming_count_thres_fixSL<SL>(bs1, bs2, n1, n2, ht, ncodes, nptr);
|
|
220
226
|
});
|
|
221
227
|
}
|
|
@@ -226,7 +232,7 @@ void crosshamming_count_thres(
|
|
|
226
232
|
hamdis_t ht,
|
|
227
233
|
size_t ncodes,
|
|
228
234
|
size_t* nptr) {
|
|
229
|
-
|
|
235
|
+
with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
|
|
230
236
|
crosshamming_count_thres_fixSL<SL>(dbs, n, ht, ncodes, nptr);
|
|
231
237
|
});
|
|
232
238
|
}
|
|
@@ -240,7 +246,7 @@ size_t match_hamming_thres(
|
|
|
240
246
|
size_t ncodes,
|
|
241
247
|
int64_t* idx,
|
|
242
248
|
hamdis_t* dis) {
|
|
243
|
-
return
|
|
249
|
+
return with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() -> size_t {
|
|
244
250
|
return match_hamming_thres_fixSL<SL>(
|
|
245
251
|
bs1, bs2, n1, n2, ht, ncodes, idx, dis);
|
|
246
252
|
});
|
|
@@ -253,7 +259,7 @@ void generalized_hammings_knn_hc(
|
|
|
253
259
|
size_t nb,
|
|
254
260
|
size_t code_size,
|
|
255
261
|
int ordered) {
|
|
256
|
-
|
|
262
|
+
with_simd_level_with_vpopcnt([&]<SIMDLevel SL>() {
|
|
257
263
|
generalized_hammings_knn_hc_fixSL<SL>(ha, a, b, nb, code_size, ordered);
|
|
258
264
|
});
|
|
259
265
|
}
|
|
@@ -111,7 +111,7 @@ FAISS_API extern size_t hamming_batch_size;
|
|
|
111
111
|
*
|
|
112
112
|
* @param a size na * nbytespercode
|
|
113
113
|
* @param b size nb * nbytespercode
|
|
114
|
-
* @param nbytespercode
|
|
114
|
+
* @param nbytespercode any size; multiples of 8 take a faster kernel
|
|
115
115
|
* @param dis output distances, size na * nb
|
|
116
116
|
*/
|
|
117
117
|
void hammings(
|
|
@@ -327,6 +327,15 @@ void hamming_range_search_fixSL(
|
|
|
327
327
|
RangeSearchResult* result,
|
|
328
328
|
const IDSelector* sel);
|
|
329
329
|
|
|
330
|
+
template <SIMDLevel SL>
|
|
331
|
+
void hammings_ragged_fixSL(
|
|
332
|
+
const uint8_t* a,
|
|
333
|
+
const uint8_t* b,
|
|
334
|
+
size_t na,
|
|
335
|
+
size_t nb,
|
|
336
|
+
size_t ncodes,
|
|
337
|
+
hamdis_t* dis);
|
|
338
|
+
|
|
330
339
|
template <SIMDLevel SL>
|
|
331
340
|
void hammings_fixSL(
|
|
332
341
|
const uint8_t* a,
|
|
@@ -210,12 +210,23 @@ inline void hammings_impl(
|
|
|
210
210
|
size_t n2,
|
|
211
211
|
hamdis_t* __restrict dis) {
|
|
212
212
|
size_t i, j;
|
|
213
|
-
|
|
213
|
+
constexpr size_t nwords = nbits / 64;
|
|
214
214
|
for (i = 0; i < n1; i++) {
|
|
215
215
|
const uint64_t* __restrict bs1_ = bs1 + i * nwords;
|
|
216
216
|
hamdis_t* __restrict dis_ = dis + i * n2;
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
if constexpr (nwords >= 4) {
|
|
218
|
+
// Wide codes are quicker one candidate at a time; otherwise the
|
|
219
|
+
// compiler batches candidates and must gather scattered bytes.
|
|
220
|
+
#if defined(__clang__)
|
|
221
|
+
#pragma clang loop vectorize(disable)
|
|
222
|
+
#endif
|
|
223
|
+
for (j = 0; j < n2; j++) {
|
|
224
|
+
dis_[j] = hamming<nbits>(bs1_, bs2 + j * nwords);
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
for (j = 0; j < n2; j++) {
|
|
228
|
+
dis_[j] = hamming<nbits>(bs1_, bs2 + j * nwords);
|
|
229
|
+
}
|
|
219
230
|
}
|
|
220
231
|
}
|
|
221
232
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#ifdef COMPILE_SIMD_AVX512_VPOPCNT
|
|
9
|
+
|
|
10
|
+
#define THE_SIMD_LEVEL SIMDLevel::AVX512_VPOPCNT
|
|
11
|
+
#include <faiss/utils/hamming_distance/hamming_computer-avx512_vpopcnt.h>
|
|
12
|
+
#include <faiss/utils/hamming_distance/hamming_impl.h>
|
|
13
|
+
|
|
14
|
+
// Must follow the computer specializations above.
|
|
15
|
+
// clang-format off
|
|
16
|
+
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
17
|
+
#include <faiss/impl/binary_hamming/IndexBinaryIVF_impl.h>
|
|
18
|
+
// clang-format on
|
|
19
|
+
|
|
20
|
+
// Fails the build if the batch path stops being selected for this computer.
|
|
21
|
+
static_assert(faiss::has_hamming_batch<
|
|
22
|
+
faiss::HammingComputer20_tpl<faiss::SIMDLevel::AVX512_VPOPCNT>>);
|
|
23
|
+
|
|
24
|
+
#endif // COMPILE_SIMD_AVX512_VPOPCNT
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// Types without custom AVX512 code inherit from the NONE specializations
|
|
13
13
|
// in hamming_computer-generic.h. HammingComputer64 and
|
|
14
14
|
// HammingComputerDefault use scalar popcount here; the VPOPCNTDQ fast
|
|
15
|
-
// path lives in hamming_computer-
|
|
15
|
+
// path lives in hamming_computer-avx512_vpopcnt.h (AVX512_VPOPCNT level).
|
|
16
16
|
// GenHammingComputer classes leverage SSE/AVX2 intrinsics.
|
|
17
17
|
|
|
18
18
|
#include <cassert>
|
|
@@ -5,17 +5,19 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
#ifndef
|
|
9
|
-
#define
|
|
8
|
+
#ifndef HAMMING_COMPUTER_AVX512_VPOPCNT_H
|
|
9
|
+
#define HAMMING_COMPUTER_AVX512_VPOPCNT_H
|
|
10
10
|
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// without -mavx512vpopcntdq.
|
|
11
|
+
// AVX512_VPOPCNT HammingComputer specializations. The 32/64/Default kernels
|
|
12
|
+
// use VPOPCNTDQ; the batched 20-byte kernel uses AVX512_BITALG. This gives
|
|
13
|
+
// a faster path than the scalar popcount fallback used in the base AVX512
|
|
14
|
+
// specializations when compiled without -mavx512vpopcntdq.
|
|
16
15
|
|
|
17
16
|
#include <cassert>
|
|
18
17
|
#include <cstdint>
|
|
18
|
+
#include <cstring>
|
|
19
|
+
|
|
20
|
+
#include <faiss/utils/popcount.h>
|
|
19
21
|
|
|
20
22
|
#include <faiss/impl/platform_macros.h>
|
|
21
23
|
#include <faiss/utils/hamming_distance/hamming_computer-avx512.h>
|
|
@@ -25,31 +27,90 @@
|
|
|
25
27
|
namespace faiss {
|
|
26
28
|
|
|
27
29
|
/***************************************************************************
|
|
28
|
-
*
|
|
30
|
+
* AVX512_VPOPCNT inheriting specializations without custom VPOPCNT code.
|
|
29
31
|
***************************************************************************/
|
|
30
32
|
|
|
31
|
-
#define
|
|
32
|
-
template <>
|
|
33
|
-
struct Class##
|
|
34
|
-
_tpl<SIMDLevel::
|
|
35
|
-
using Class##_tpl<SIMDLevel::AVX512>::Class##_tpl;
|
|
33
|
+
#define FAISS_INHERIT_HAMMING_VPOPCNT(Class) \
|
|
34
|
+
template <> \
|
|
35
|
+
struct Class## \
|
|
36
|
+
_tpl<SIMDLevel::AVX512_VPOPCNT> : Class##_tpl<SIMDLevel::AVX512> { \
|
|
37
|
+
using Class##_tpl<SIMDLevel::AVX512>::Class##_tpl; \
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
FAISS_INHERIT_HAMMING_SPR(GenHammingComputerM8);
|
|
40
|
+
FAISS_INHERIT_HAMMING_VPOPCNT(HammingComputer16);
|
|
41
|
+
FAISS_INHERIT_HAMMING_VPOPCNT(GenHammingComputer8);
|
|
42
|
+
FAISS_INHERIT_HAMMING_VPOPCNT(GenHammingComputer16);
|
|
43
|
+
FAISS_INHERIT_HAMMING_VPOPCNT(GenHammingComputer32);
|
|
44
|
+
FAISS_INHERIT_HAMMING_VPOPCNT(GenHammingComputerM8);
|
|
44
45
|
|
|
45
|
-
#undef
|
|
46
|
+
#undef FAISS_INHERIT_HAMMING_VPOPCNT
|
|
46
47
|
|
|
47
48
|
/***************************************************************************
|
|
48
|
-
* Custom
|
|
49
|
+
* Custom AVX512_VPOPCNT specializations using VPOPCNTDQ.
|
|
49
50
|
***************************************************************************/
|
|
50
51
|
|
|
51
52
|
template <>
|
|
52
|
-
struct
|
|
53
|
+
struct HammingComputer20_tpl<SIMDLevel::AVX512_VPOPCNT>
|
|
54
|
+
: HammingComputer20_tpl<SIMDLevel::AVX512> {
|
|
55
|
+
using HammingComputer20_tpl<SIMDLevel::AVX512>::HammingComputer20_tpl;
|
|
56
|
+
|
|
57
|
+
static constexpr size_t batch_size = 8;
|
|
58
|
+
static constexpr size_t kStride = get_code_size();
|
|
59
|
+
// 160 bytes is what the three loads in hamming_batch() cover, and the
|
|
60
|
+
// 16+4 or 4+16 split it applies per lane is written out for 20 bytes:
|
|
61
|
+
// the literal offsets and the two group indices are not derived from
|
|
62
|
+
// kStride, so another width needs the body reworked, not just retuned.
|
|
63
|
+
static_assert(batch_size * kStride == 160);
|
|
64
|
+
static_assert(kStride == 20, "hamming_batch() hardcodes the 16+4 split");
|
|
65
|
+
static constexpr __mmask64 kTailMask = 0xFFFFFFFFull;
|
|
66
|
+
|
|
67
|
+
/// Writes the query repeated batch_size times. The caller owns the buffer,
|
|
68
|
+
/// so a computer used only through hamming() carries no batch state.
|
|
69
|
+
static void build_batch_query(const uint8_t* a8, uint8_t* tile) {
|
|
70
|
+
for (size_t k = 0; k < batch_size; k++) {
|
|
71
|
+
memcpy(tile + k * kStride, a8, kStride);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static void hamming_batch(
|
|
76
|
+
const uint8_t* tile,
|
|
77
|
+
const uint8_t* codes,
|
|
78
|
+
int32_t* dis) {
|
|
79
|
+
const __m512i zero = _mm512_setzero_si512();
|
|
80
|
+
const __m512i p0 = _mm512_popcnt_epi8(_mm512_xor_si512(
|
|
81
|
+
_mm512_loadu_si512(codes), _mm512_loadu_si512(tile)));
|
|
82
|
+
const __m512i p1 = _mm512_popcnt_epi8(_mm512_xor_si512(
|
|
83
|
+
_mm512_loadu_si512(codes + 64), _mm512_loadu_si512(tile + 64)));
|
|
84
|
+
const __m512i p2 = _mm512_popcnt_epi8(_mm512_xor_si512(
|
|
85
|
+
_mm512_maskz_loadu_epi8(kTailMask, codes + 128),
|
|
86
|
+
_mm512_maskz_loadu_epi8(kTailMask, tile + 128)));
|
|
87
|
+
|
|
88
|
+
alignas(64) uint64_t grp[24];
|
|
89
|
+
_mm512_store_si512(grp, _mm512_sad_epu8(p0, zero));
|
|
90
|
+
_mm512_store_si512(grp + 8, _mm512_sad_epu8(p1, zero));
|
|
91
|
+
_mm512_store_si512(grp + 16, _mm512_sad_epu8(p2, zero));
|
|
92
|
+
|
|
93
|
+
for (size_t k = 0; k < batch_size; k++) {
|
|
94
|
+
const size_t s = k * kStride;
|
|
95
|
+
const size_t g = s / 8;
|
|
96
|
+
uint32_t xh, qh;
|
|
97
|
+
if (s % 8 == 0) {
|
|
98
|
+
memcpy(&xh, codes + s + 16, 4);
|
|
99
|
+
memcpy(&qh, tile + s + 16, 4);
|
|
100
|
+
dis[k] = static_cast<int32_t>(
|
|
101
|
+
grp[g] + grp[g + 1] + popcount32(xh ^ qh));
|
|
102
|
+
} else {
|
|
103
|
+
memcpy(&xh, codes + s, 4);
|
|
104
|
+
memcpy(&qh, tile + s, 4);
|
|
105
|
+
dis[k] = static_cast<int32_t>(
|
|
106
|
+
popcount32(xh ^ qh) + grp[g + 1] + grp[g + 2]);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
template <>
|
|
113
|
+
struct HammingComputer32_tpl<SIMDLevel::AVX512_VPOPCNT> {
|
|
53
114
|
const uint8_t* a8;
|
|
54
115
|
|
|
55
116
|
HammingComputer32_tpl() {}
|
|
@@ -81,7 +142,7 @@ struct HammingComputer32_tpl<SIMDLevel::AVX512_SPR> {
|
|
|
81
142
|
};
|
|
82
143
|
|
|
83
144
|
template <>
|
|
84
|
-
struct HammingComputer64_tpl<SIMDLevel::
|
|
145
|
+
struct HammingComputer64_tpl<SIMDLevel::AVX512_VPOPCNT> {
|
|
85
146
|
const uint8_t* a8;
|
|
86
147
|
|
|
87
148
|
HammingComputer64_tpl() {}
|
|
@@ -108,7 +169,7 @@ struct HammingComputer64_tpl<SIMDLevel::AVX512_SPR> {
|
|
|
108
169
|
};
|
|
109
170
|
|
|
110
171
|
template <>
|
|
111
|
-
struct HammingComputerDefault_tpl<SIMDLevel::
|
|
172
|
+
struct HammingComputerDefault_tpl<SIMDLevel::AVX512_VPOPCNT> {
|
|
112
173
|
const uint8_t* a8;
|
|
113
174
|
int quotient8;
|
|
114
175
|
int remainder8;
|