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
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
#include <faiss/utils/distances_dispatch.h>
|
|
27
27
|
#include <faiss/utils/distances_fused/distances_fused.h>
|
|
28
28
|
#include <faiss/utils/simd_impl/exhaustive_L2sqr_blas_cmax.h>
|
|
29
|
+
#include <faiss/utils/utils.h>
|
|
29
30
|
|
|
30
31
|
#ifndef FINTEGER
|
|
31
32
|
#define FINTEGER long
|
|
@@ -361,10 +362,11 @@ void exhaustive_L2sqr_seq(
|
|
|
361
362
|
}
|
|
362
363
|
}
|
|
363
364
|
|
|
364
|
-
/** Find the nearest neighbors for nx queries in a set
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
365
|
+
/** Find the nearest neighbors for nx queries (see Fp32QueryTiles) in a set
|
|
366
|
+
* of ny vectors */
|
|
367
|
+
template <class BlockResultHandler, class QueryTiles>
|
|
368
|
+
void exhaustive_inner_product_blas_tiles(
|
|
369
|
+
QueryTiles& queries,
|
|
368
370
|
const float* y,
|
|
369
371
|
size_t d,
|
|
370
372
|
size_t nx,
|
|
@@ -386,6 +388,8 @@ void exhaustive_inner_product_blas(
|
|
|
386
388
|
i1 = nx;
|
|
387
389
|
}
|
|
388
390
|
|
|
391
|
+
const float* xt = queries.tile(i0, i1, nullptr);
|
|
392
|
+
|
|
389
393
|
res.begin_multiple(i0, i1);
|
|
390
394
|
|
|
391
395
|
for (size_t j0 = 0; j0 < ny; j0 += bs_y) {
|
|
@@ -405,7 +409,7 @@ void exhaustive_inner_product_blas(
|
|
|
405
409
|
&one,
|
|
406
410
|
y + j0 * d,
|
|
407
411
|
&di,
|
|
408
|
-
|
|
412
|
+
xt,
|
|
409
413
|
&di,
|
|
410
414
|
&zero,
|
|
411
415
|
ip_block.get(),
|
|
@@ -421,9 +425,9 @@ void exhaustive_inner_product_blas(
|
|
|
421
425
|
|
|
422
426
|
// distance correction is an operator that can be applied to transform
|
|
423
427
|
// the distances
|
|
424
|
-
template <class BlockResultHandler>
|
|
425
|
-
void
|
|
426
|
-
|
|
428
|
+
template <class BlockResultHandler, class QueryTiles>
|
|
429
|
+
void exhaustive_L2sqr_blas_tiles(
|
|
430
|
+
QueryTiles& queries,
|
|
427
431
|
const float* y,
|
|
428
432
|
size_t d,
|
|
429
433
|
size_t nx,
|
|
@@ -443,7 +447,7 @@ void exhaustive_L2sqr_blas_default_impl(
|
|
|
443
447
|
std::unique_ptr<float[]> x_norms(new float[nx]);
|
|
444
448
|
std::unique_ptr<float[]> del2;
|
|
445
449
|
|
|
446
|
-
|
|
450
|
+
queries.prepare_norms(nx, x_norms.get());
|
|
447
451
|
|
|
448
452
|
if (!y_norms) {
|
|
449
453
|
float* y_norms2 = new float[ny];
|
|
@@ -458,6 +462,8 @@ void exhaustive_L2sqr_blas_default_impl(
|
|
|
458
462
|
i1 = nx;
|
|
459
463
|
}
|
|
460
464
|
|
|
465
|
+
const float* xt = queries.tile(i0, i1, x_norms.get());
|
|
466
|
+
|
|
461
467
|
res.begin_multiple(i0, i1);
|
|
462
468
|
|
|
463
469
|
for (size_t j0 = 0; j0 < ny; j0 += bs_y) {
|
|
@@ -477,7 +483,7 @@ void exhaustive_L2sqr_blas_default_impl(
|
|
|
477
483
|
&one,
|
|
478
484
|
y + j0 * d,
|
|
479
485
|
&di,
|
|
480
|
-
|
|
486
|
+
xt,
|
|
481
487
|
&di,
|
|
482
488
|
&zero,
|
|
483
489
|
ip_block.get(),
|
|
@@ -510,6 +516,31 @@ void exhaustive_L2sqr_blas_default_impl(
|
|
|
510
516
|
}
|
|
511
517
|
}
|
|
512
518
|
|
|
519
|
+
template <class BlockResultHandler>
|
|
520
|
+
void exhaustive_inner_product_blas(
|
|
521
|
+
const float* x,
|
|
522
|
+
const float* y,
|
|
523
|
+
size_t d,
|
|
524
|
+
size_t nx,
|
|
525
|
+
size_t ny,
|
|
526
|
+
BlockResultHandler& res) {
|
|
527
|
+
Fp32QueryTiles queries{x, d};
|
|
528
|
+
exhaustive_inner_product_blas_tiles(queries, y, d, nx, ny, res);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
template <class BlockResultHandler>
|
|
532
|
+
void exhaustive_L2sqr_blas_default_impl(
|
|
533
|
+
const float* x,
|
|
534
|
+
const float* y,
|
|
535
|
+
size_t d,
|
|
536
|
+
size_t nx,
|
|
537
|
+
size_t ny,
|
|
538
|
+
BlockResultHandler& res,
|
|
539
|
+
const float* y_norms = nullptr) {
|
|
540
|
+
Fp32QueryTiles queries{x, d};
|
|
541
|
+
exhaustive_L2sqr_blas_tiles(queries, y, d, nx, ny, res, y_norms);
|
|
542
|
+
}
|
|
543
|
+
|
|
513
544
|
template <class BlockResultHandler>
|
|
514
545
|
void exhaustive_L2sqr_blas(
|
|
515
546
|
const float* x,
|
|
@@ -556,6 +587,44 @@ void exhaustive_L2sqr_blas<Top1BlockResultHandler<CMax<float, int64_t>>>(
|
|
|
556
587
|
});
|
|
557
588
|
}
|
|
558
589
|
|
|
590
|
+
/// exhaustive_L2sqr_blas for packed IEEE binary16 queries
|
|
591
|
+
template <class BlockResultHandler>
|
|
592
|
+
void exhaustive_L2sqr_blas_fp16(
|
|
593
|
+
const uint16_t* x,
|
|
594
|
+
const float* y,
|
|
595
|
+
size_t d,
|
|
596
|
+
size_t nx,
|
|
597
|
+
size_t ny,
|
|
598
|
+
BlockResultHandler& res,
|
|
599
|
+
const float* y_norms) {
|
|
600
|
+
Fp16QueryTiles queries(x, d, nx);
|
|
601
|
+
exhaustive_L2sqr_blas_tiles(queries, y, d, nx, ny, res, y_norms);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
template <>
|
|
605
|
+
void exhaustive_L2sqr_blas_fp16<Top1BlockResultHandler<CMax<float, int64_t>>>(
|
|
606
|
+
const uint16_t* x,
|
|
607
|
+
const float* y,
|
|
608
|
+
size_t d,
|
|
609
|
+
size_t nx,
|
|
610
|
+
size_t ny,
|
|
611
|
+
Top1BlockResultHandler<CMax<float, int64_t>>& res,
|
|
612
|
+
const float* y_norms) {
|
|
613
|
+
with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_WITH_SVE>(
|
|
614
|
+
[&]<SIMDLevel SL>() {
|
|
615
|
+
if constexpr (
|
|
616
|
+
SL == SIMDLevel::AVX2 || SL == SIMDLevel::AVX512 ||
|
|
617
|
+
SL == SIMDLevel::ARM_SVE) {
|
|
618
|
+
exhaustive_L2sqr_blas_cmax_fp16<SL>(
|
|
619
|
+
x, y, d, nx, ny, res, y_norms);
|
|
620
|
+
} else {
|
|
621
|
+
Fp16QueryTiles queries(x, d, nx);
|
|
622
|
+
exhaustive_L2sqr_blas_tiles(
|
|
623
|
+
queries, y, d, nx, ny, res, y_norms);
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
|
|
559
628
|
struct Run_search_inner_product {
|
|
560
629
|
using T = void;
|
|
561
630
|
template <class BlockResultHandler>
|
|
@@ -598,6 +667,35 @@ struct Run_search_L2sqr {
|
|
|
598
667
|
}
|
|
599
668
|
};
|
|
600
669
|
|
|
670
|
+
// fp16 consumers only run the BLAS kernels, see use_fp16_blas_kernels
|
|
671
|
+
struct Run_search_inner_product_fp16 {
|
|
672
|
+
using T = void;
|
|
673
|
+
template <class BlockResultHandler>
|
|
674
|
+
void f(BlockResultHandler& res,
|
|
675
|
+
const uint16_t* x,
|
|
676
|
+
const float* y,
|
|
677
|
+
size_t d,
|
|
678
|
+
size_t nx,
|
|
679
|
+
size_t ny) {
|
|
680
|
+
Fp16QueryTiles queries(x, d, nx);
|
|
681
|
+
exhaustive_inner_product_blas_tiles(queries, y, d, nx, ny, res);
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
struct Run_search_L2sqr_fp16 {
|
|
686
|
+
using T = void;
|
|
687
|
+
template <class BlockResultHandler>
|
|
688
|
+
void f(BlockResultHandler& res,
|
|
689
|
+
const uint16_t* x,
|
|
690
|
+
const float* y,
|
|
691
|
+
size_t d,
|
|
692
|
+
size_t nx,
|
|
693
|
+
size_t ny,
|
|
694
|
+
const float* y_norm2) {
|
|
695
|
+
exhaustive_L2sqr_blas_fp16(x, y, d, nx, ny, res, y_norm2);
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
|
|
601
699
|
} // anonymous namespace
|
|
602
700
|
|
|
603
701
|
/*******************************************************
|
|
@@ -630,7 +728,7 @@ static void knn_db_parallel_impl(
|
|
|
630
728
|
int nt = omp_get_max_threads();
|
|
631
729
|
const size_t bs_y = distance_compute_blas_database_bs;
|
|
632
730
|
|
|
633
|
-
//
|
|
731
|
+
// Result heaps: nt segments x nx queries x k results
|
|
634
732
|
std::vector<T> all_dis(static_cast<size_t>(nt) * nx * k);
|
|
635
733
|
std::vector<TI> all_ids(static_cast<size_t>(nt) * nx * k);
|
|
636
734
|
|
|
@@ -649,9 +747,8 @@ static void knn_db_parallel_impl(
|
|
|
649
747
|
}
|
|
650
748
|
}
|
|
651
749
|
|
|
652
|
-
#pragma omp parallel
|
|
653
|
-
{
|
|
654
|
-
int tid = omp_get_thread_num();
|
|
750
|
+
#pragma omp parallel for
|
|
751
|
+
for (int tid = 0; tid < nt; tid++) {
|
|
655
752
|
size_t j_begin = static_cast<size_t>(tid) * ny / nt;
|
|
656
753
|
size_t j_end = static_cast<size_t>(tid + 1) * ny / nt;
|
|
657
754
|
size_t local_ny = j_end - j_begin;
|
|
@@ -734,7 +831,7 @@ static void knn_db_parallel_impl(
|
|
|
734
831
|
}
|
|
735
832
|
}
|
|
736
833
|
|
|
737
|
-
// Merge per-
|
|
834
|
+
// Merge per-segment heaps into output, parallelized over queries
|
|
738
835
|
#pragma omp parallel for
|
|
739
836
|
for (int64_t i = 0; i < static_cast<int64_t>(nx); i++) {
|
|
740
837
|
heap_heapify<C>(k, vals + i * k, ids + i * k);
|
|
@@ -894,6 +991,120 @@ void knn_L2sqr(
|
|
|
894
991
|
knn_L2sqr(x, y, d, nx, ny, res->k, res->val, res->ids, y_norm2, sel);
|
|
895
992
|
}
|
|
896
993
|
|
|
994
|
+
namespace {
|
|
995
|
+
|
|
996
|
+
/** Whether fp16 queries go to the BLAS kernels directly.
|
|
997
|
+
*
|
|
998
|
+
* Other cases widen chunks of queries and run the fp32 search: selectors,
|
|
999
|
+
* sequential and database-parallel searches, and small d, where the fused
|
|
1000
|
+
* top-1 kernels need fp32 rows.
|
|
1001
|
+
*/
|
|
1002
|
+
bool use_fp16_blas_kernels(
|
|
1003
|
+
size_t d,
|
|
1004
|
+
size_t nx,
|
|
1005
|
+
size_t ny,
|
|
1006
|
+
const IDSelector* sel) {
|
|
1007
|
+
return !sel && ny > 0 && d > 32 &&
|
|
1008
|
+
nx * d >= static_cast<size_t>(distance_compute_blas_threshold) &&
|
|
1009
|
+
!should_use_db_parallel(nx, ny, sel);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
/// widens chunks of queries and calls search(x_chunk, n_chunk, i0) on them
|
|
1013
|
+
template <class Fp32Search>
|
|
1014
|
+
void search_fp16_by_chunks(
|
|
1015
|
+
const uint16_t* x,
|
|
1016
|
+
size_t d,
|
|
1017
|
+
size_t nx,
|
|
1018
|
+
const Fp32Search& search) {
|
|
1019
|
+
// a multiple of the query tile, so the fp32 kernels see the same tiles
|
|
1020
|
+
const size_t bs_x = std::max(distance_compute_blas_query_bs, 1);
|
|
1021
|
+
const size_t chunk = bs_x *
|
|
1022
|
+
std::max<size_t>(1, (size_t(8) << 20) / (bs_x * d * sizeof(float)));
|
|
1023
|
+
std::vector<float> buffer(std::min(nx, chunk) * d);
|
|
1024
|
+
for (size_t i0 = 0; i0 < nx; i0 += chunk) {
|
|
1025
|
+
const size_t i1 = std::min(nx, i0 + chunk);
|
|
1026
|
+
fp16_to_fp32((i1 - i0) * d, x + i0 * d, buffer.data());
|
|
1027
|
+
search(buffer.data(), i1 - i0, i0);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
} // namespace
|
|
1032
|
+
|
|
1033
|
+
void knn_inner_product_fp16(
|
|
1034
|
+
const uint16_t* x,
|
|
1035
|
+
const float* y,
|
|
1036
|
+
size_t d,
|
|
1037
|
+
size_t nx,
|
|
1038
|
+
size_t ny,
|
|
1039
|
+
size_t k,
|
|
1040
|
+
float* vals,
|
|
1041
|
+
int64_t* ids,
|
|
1042
|
+
const IDSelector* sel) {
|
|
1043
|
+
if (!use_fp16_blas_kernels(d, nx, ny, sel)) {
|
|
1044
|
+
search_fp16_by_chunks(
|
|
1045
|
+
x, d, nx, [&](const float* xc, size_t nc, size_t i0) {
|
|
1046
|
+
knn_inner_product(
|
|
1047
|
+
xc,
|
|
1048
|
+
y,
|
|
1049
|
+
d,
|
|
1050
|
+
nc,
|
|
1051
|
+
ny,
|
|
1052
|
+
k,
|
|
1053
|
+
vals + i0 * k,
|
|
1054
|
+
ids + i0 * k,
|
|
1055
|
+
sel);
|
|
1056
|
+
});
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
Run_search_inner_product_fp16 r;
|
|
1060
|
+
dispatch_knn_ResultHandler(
|
|
1061
|
+
nx,
|
|
1062
|
+
vals,
|
|
1063
|
+
ids,
|
|
1064
|
+
k,
|
|
1065
|
+
METRIC_INNER_PRODUCT,
|
|
1066
|
+
nullptr,
|
|
1067
|
+
r,
|
|
1068
|
+
x,
|
|
1069
|
+
y,
|
|
1070
|
+
d,
|
|
1071
|
+
nx,
|
|
1072
|
+
ny);
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
void knn_L2sqr_fp16(
|
|
1076
|
+
const uint16_t* x,
|
|
1077
|
+
const float* y,
|
|
1078
|
+
size_t d,
|
|
1079
|
+
size_t nx,
|
|
1080
|
+
size_t ny,
|
|
1081
|
+
size_t k,
|
|
1082
|
+
float* vals,
|
|
1083
|
+
int64_t* ids,
|
|
1084
|
+
const float* y_norm2,
|
|
1085
|
+
const IDSelector* sel) {
|
|
1086
|
+
if (!use_fp16_blas_kernels(d, nx, ny, sel)) {
|
|
1087
|
+
search_fp16_by_chunks(
|
|
1088
|
+
x, d, nx, [&](const float* xc, size_t nc, size_t i0) {
|
|
1089
|
+
knn_L2sqr(
|
|
1090
|
+
xc,
|
|
1091
|
+
y,
|
|
1092
|
+
d,
|
|
1093
|
+
nc,
|
|
1094
|
+
ny,
|
|
1095
|
+
k,
|
|
1096
|
+
vals + i0 * k,
|
|
1097
|
+
ids + i0 * k,
|
|
1098
|
+
y_norm2,
|
|
1099
|
+
sel);
|
|
1100
|
+
});
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1103
|
+
Run_search_L2sqr_fp16 r;
|
|
1104
|
+
dispatch_knn_ResultHandler(
|
|
1105
|
+
nx, vals, ids, k, METRIC_L2, nullptr, r, x, y, d, nx, ny, y_norm2);
|
|
1106
|
+
}
|
|
1107
|
+
|
|
897
1108
|
/***************************************************************************
|
|
898
1109
|
* Range search
|
|
899
1110
|
***************************************************************************/
|
|
@@ -455,6 +455,36 @@ void knn_L2sqr(
|
|
|
455
455
|
const float* y_norm2 = nullptr,
|
|
456
456
|
const IDSelector* sel = nullptr);
|
|
457
457
|
|
|
458
|
+
/** knn_inner_product for packed IEEE binary16 queries (x: nx * d uint16_t).
|
|
459
|
+
*
|
|
460
|
+
* The BLAS kernels widen each query tile once and reuse it for all database
|
|
461
|
+
* tiles, so there is no fp32 copy of the queries. Results are the same as
|
|
462
|
+
* knn_inner_product on the widened queries.
|
|
463
|
+
*/
|
|
464
|
+
void knn_inner_product_fp16(
|
|
465
|
+
const uint16_t* x,
|
|
466
|
+
const float* y,
|
|
467
|
+
size_t d,
|
|
468
|
+
size_t nx,
|
|
469
|
+
size_t ny,
|
|
470
|
+
size_t k,
|
|
471
|
+
float* distances,
|
|
472
|
+
int64_t* indexes,
|
|
473
|
+
const IDSelector* sel = nullptr);
|
|
474
|
+
|
|
475
|
+
/// knn_L2sqr for packed IEEE binary16 queries, see knn_inner_product_fp16
|
|
476
|
+
void knn_L2sqr_fp16(
|
|
477
|
+
const uint16_t* x,
|
|
478
|
+
const float* y,
|
|
479
|
+
size_t d,
|
|
480
|
+
size_t nx,
|
|
481
|
+
size_t ny,
|
|
482
|
+
size_t k,
|
|
483
|
+
float* distances,
|
|
484
|
+
int64_t* indexes,
|
|
485
|
+
const float* y_norm2 = nullptr,
|
|
486
|
+
const IDSelector* sel = nullptr);
|
|
487
|
+
|
|
458
488
|
/** Find the max inner product neighbors for nx queries in a set of ny vectors
|
|
459
489
|
* indexed by ids. May be useful for re-ranking a pre-selected vector list
|
|
460
490
|
*
|
|
@@ -600,4 +630,8 @@ int fvec_madd_and_argmin(
|
|
|
600
630
|
const float* b,
|
|
601
631
|
float* c);
|
|
602
632
|
|
|
633
|
+
/// sum of x[j] for every j < d whose bit is set in bits (LSB-first per byte)
|
|
634
|
+
template <SIMDLevel>
|
|
635
|
+
float fvec_masked_sum(const float* x, const uint8_t* bits, size_t d);
|
|
636
|
+
|
|
603
637
|
} // namespace faiss
|
|
@@ -184,7 +184,7 @@ inline void fvec_sub_dispatch(
|
|
|
184
184
|
const float* a,
|
|
185
185
|
const float* b,
|
|
186
186
|
float* c) {
|
|
187
|
-
|
|
187
|
+
with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_NO_AVX512>(
|
|
188
188
|
[&]<SIMDLevel level>() { fvec_sub<level>(d, a, b, c); });
|
|
189
189
|
}
|
|
190
190
|
|
|
@@ -193,7 +193,7 @@ inline void fvec_add_dispatch(
|
|
|
193
193
|
const float* a,
|
|
194
194
|
const float* b,
|
|
195
195
|
float* c) {
|
|
196
|
-
|
|
196
|
+
with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_NO_AVX512>(
|
|
197
197
|
[&]<SIMDLevel level>() { fvec_add<level>(d, a, b, c); });
|
|
198
198
|
}
|
|
199
199
|
|
|
@@ -202,7 +202,7 @@ inline void fvec_add_scalar_dispatch(
|
|
|
202
202
|
const float* a,
|
|
203
203
|
float b,
|
|
204
204
|
float* c) {
|
|
205
|
-
|
|
205
|
+
with_selected_simd_levels<AVAILABLE_SIMD_LEVELS_BASE_NO_AVX512>(
|
|
206
206
|
[&]<SIMDLevel level>() { fvec_add<level>(d, a, b, c); });
|
|
207
207
|
}
|
|
208
208
|
|
|
@@ -214,7 +214,9 @@ inline void compute_PQ_dis_tables_dsub2_dispatch(
|
|
|
214
214
|
const float* x,
|
|
215
215
|
bool is_inner_product,
|
|
216
216
|
float* dis_tables) {
|
|
217
|
-
|
|
217
|
+
constexpr int dsub2_mask =
|
|
218
|
+
AVAILABLE_SIMD_LEVELS_AVX2_NEON | (1 << int(SIMDLevel::RISCV_RVV));
|
|
219
|
+
with_selected_simd_levels<dsub2_mask>([&]<SIMDLevel level>() {
|
|
218
220
|
compute_PQ_dis_tables_dsub2<level>(
|
|
219
221
|
d, ksub, centroids, nx, x, is_inner_product, dis_tables);
|
|
220
222
|
});
|
|
@@ -7,10 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
// -*- c++ -*-
|
|
9
9
|
|
|
10
|
+
#include <faiss/impl/platform_macros.h>
|
|
10
11
|
#include <faiss/utils/distances_fused/distances_fused.h>
|
|
11
12
|
|
|
12
|
-
#ifdef COMPILE_SIMD_AVX512
|
|
13
|
-
|
|
14
13
|
#include <immintrin.h>
|
|
15
14
|
|
|
16
15
|
namespace faiss {
|
|
@@ -264,7 +263,7 @@ void exhaustive_L2sqr_fused_cmax(
|
|
|
264
263
|
|
|
265
264
|
const idx_t nx_p = (nx / NX_POINTS_PER_LOOP) * NX_POINTS_PER_LOOP;
|
|
266
265
|
// the main loop.
|
|
267
|
-
#pragma omp parallel for schedule(
|
|
266
|
+
#pragma omp parallel for schedule(FAISS_OMP_DYNAMIC)
|
|
268
267
|
for (idx_t i = 0; i < nx_p; i += NX_POINTS_PER_LOOP) {
|
|
269
268
|
kernel<DIM, NX_POINTS_PER_LOOP, NY_POINTS_PER_LOOP>(
|
|
270
269
|
x, y, y_transposed.data(), ny, res, y_norms, i);
|
|
@@ -343,5 +342,3 @@ bool exhaustive_L2sqr_fused_cmax<SIMDLevel::AVX512>(
|
|
|
343
342
|
}
|
|
344
343
|
|
|
345
344
|
} // namespace faiss
|
|
346
|
-
|
|
347
|
-
#endif // COMPILE_SIMD_AVX512
|
|
@@ -24,20 +24,6 @@ bool exhaustive_L2sqr_fused_cmax<SIMDLevel::NONE>(
|
|
|
24
24
|
return false;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
#ifdef COMPILE_SIMD_RISCV_RVV
|
|
28
|
-
template <>
|
|
29
|
-
bool exhaustive_L2sqr_fused_cmax<SIMDLevel::RISCV_RVV>(
|
|
30
|
-
const float*,
|
|
31
|
-
const float*,
|
|
32
|
-
size_t,
|
|
33
|
-
size_t,
|
|
34
|
-
size_t,
|
|
35
|
-
Top1BlockResultHandler<CMax<float, int64_t>>&,
|
|
36
|
-
const float*) {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
#endif // COMPILE_SIMD_RISCV_RVV
|
|
40
|
-
|
|
41
27
|
bool exhaustive_L2sqr_fused_cmax(
|
|
42
28
|
const float* x,
|
|
43
29
|
const float* y,
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
#include <faiss/utils/distances_fused/distances_fused.h>
|
|
9
|
+
|
|
10
|
+
namespace faiss {
|
|
11
|
+
|
|
12
|
+
// Scalar fallback: no fused kernel available.
|
|
13
|
+
template <>
|
|
14
|
+
bool exhaustive_L2sqr_fused_cmax<SIMDLevel::RISCV_RVV>(
|
|
15
|
+
const float*,
|
|
16
|
+
const float*,
|
|
17
|
+
size_t,
|
|
18
|
+
size_t,
|
|
19
|
+
size_t,
|
|
20
|
+
Top1BlockResultHandler<CMax<float, int64_t>>&,
|
|
21
|
+
const float*) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
} // namespace faiss
|
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
// AVX2 compilation unit for the simdlib-based fused distance kernel.
|
|
9
9
|
|
|
10
|
-
#ifdef COMPILE_SIMD_AVX2
|
|
11
|
-
|
|
12
10
|
#include <faiss/impl/simdlib/simdlib_avx2.h>
|
|
13
11
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
14
12
|
#include <faiss/utils/distances_fused/simdlib_kernel-inl.h>
|
|
@@ -71,5 +69,3 @@ bool exhaustive_L2sqr_fused_cmax<SIMDLevel::AVX2>(
|
|
|
71
69
|
}
|
|
72
70
|
|
|
73
71
|
} // namespace faiss
|
|
74
|
-
|
|
75
|
-
#endif // COMPILE_SIMD_AVX2
|
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
// ARM NEON compilation unit for the simdlib-based fused distance kernel.
|
|
9
9
|
|
|
10
|
-
#ifdef COMPILE_SIMD_ARM_NEON
|
|
11
|
-
|
|
12
10
|
#include <faiss/impl/simdlib/simdlib_neon.h>
|
|
13
11
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
14
12
|
#include <faiss/utils/distances_fused/simdlib_kernel-inl.h>
|
|
@@ -53,5 +51,3 @@ bool exhaustive_L2sqr_fused_cmax<SIMDLevel::ARM_NEON>(
|
|
|
53
51
|
}
|
|
54
52
|
|
|
55
53
|
} // namespace faiss
|
|
56
|
-
|
|
57
|
-
#endif // COMPILE_SIMD_ARM_NEON
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
#pragma once
|
|
16
16
|
|
|
17
|
+
#include <faiss/impl/platform_macros.h>
|
|
17
18
|
#include <faiss/utils/distances_fused/distances_fused.h>
|
|
18
19
|
|
|
19
20
|
namespace faiss {
|
|
@@ -267,7 +268,7 @@ void exhaustive_L2sqr_fused_cmax(
|
|
|
267
268
|
|
|
268
269
|
const size_t nx_p = (nx / NX_POINTS_PER_LOOP) * NX_POINTS_PER_LOOP;
|
|
269
270
|
// the main loop.
|
|
270
|
-
#pragma omp parallel for schedule(
|
|
271
|
+
#pragma omp parallel for schedule(FAISS_OMP_DYNAMIC)
|
|
271
272
|
for (int64_t i = 0; i < static_cast<int64_t>(nx_p);
|
|
272
273
|
i += NX_POINTS_PER_LOOP) {
|
|
273
274
|
kernel<DIM, NX_POINTS_PER_LOOP, NY_POINTS_PER_LOOP, SL>(
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
// -*- c++ -*-
|
|
9
9
|
|
|
10
10
|
#include <faiss/utils/distances.h>
|
|
11
|
+
#include <faiss/utils/simd_impl/masked_sum.h>
|
|
11
12
|
|
|
12
13
|
#include <cmath>
|
|
13
14
|
#include <cstring>
|
|
@@ -42,6 +43,14 @@ void fvec_madd<SIMDLevel::NONE>(
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
template <>
|
|
47
|
+
float fvec_masked_sum<SIMDLevel::NONE>(
|
|
48
|
+
const float* x,
|
|
49
|
+
const uint8_t* bits,
|
|
50
|
+
size_t d) {
|
|
51
|
+
return masked_sum<SIMDLevel::NONE>(x, bits, d);
|
|
52
|
+
}
|
|
53
|
+
|
|
45
54
|
template <>
|
|
46
55
|
void fvec_L2sqr_ny_transposed<SIMDLevel::NONE>(
|
|
47
56
|
float* dis,
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
namespace faiss {
|
|
14
14
|
|
|
15
|
+
namespace {
|
|
16
|
+
|
|
15
17
|
inline uint16_t encode_fp16(float x) {
|
|
16
18
|
__m128 xf = _mm_set1_ps(x);
|
|
17
19
|
__m128i xi =
|
|
@@ -25,4 +27,6 @@ inline float decode_fp16(uint16_t x) {
|
|
|
25
27
|
return _mm_cvtss_f32(xf);
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
} // namespace
|
|
31
|
+
|
|
28
32
|
} // namespace faiss
|
|
@@ -27,63 +27,35 @@ inline uint32_t intbits(float f) {
|
|
|
27
27
|
return *(uint32_t*)fptr;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
} // namespace
|
|
31
|
-
|
|
32
30
|
inline uint16_t encode_fp16(float f) {
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
// Rounds to nearest even, as the F16C and Arm conversions do, so that
|
|
32
|
+
// every SIMD level encodes the same bits. Via Fabian "ryg" Giesen
|
|
33
|
+
// (float_to_half_fast3_rtne): https://gist.github.com/2156668
|
|
34
|
+
const uint32_t f32infty = 255u << 23;
|
|
35
|
+
const uint32_t f16max = (127u + 16u) << 23;
|
|
36
|
+
const uint32_t denorm_magic = ((127u - 15u) + (23u - 10u) + 1u) << 23;
|
|
37
|
+
const uint32_t sign_mask = 0x80000000u;
|
|
37
38
|
|
|
38
39
|
uint32_t fint = intbits(f);
|
|
39
|
-
uint32_t sign = fint & sign_mask;
|
|
40
|
+
const uint32_t sign = fint & sign_mask;
|
|
40
41
|
fint ^= sign;
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const uint32_t round_mask = ~0xfffu;
|
|
59
|
-
const uint32_t magic = 15u << 23;
|
|
60
|
-
|
|
61
|
-
// Shift exponent down, denormalize if necessary.
|
|
62
|
-
// NOTE This represents half-float denormals using single
|
|
63
|
-
// precision denormals. The main reason to do this is that
|
|
64
|
-
// there's no shift with per-lane variable shifts in SSE*, which
|
|
65
|
-
// we'd otherwise need. It has some funky side effects though:
|
|
66
|
-
// - This conversion will actually respect the FTZ (Flush To Zero)
|
|
67
|
-
// flag in MXCSR - if it's set, no half-float denormals will be
|
|
68
|
-
// generated. I'm honestly not sure whether this is good or
|
|
69
|
-
// bad. It's definitely interesting.
|
|
70
|
-
// - If the underlying HW doesn't support denormals (not an issue
|
|
71
|
-
// with Intel CPUs, but might be a problem on GPUs or PS3 SPUs),
|
|
72
|
-
// you will always get flush-to-zero behavior. This is bad,
|
|
73
|
-
// unless you're on a CPU where you don't care.
|
|
74
|
-
// - Denormals tend to be slow. FP32 denormals are rare in
|
|
75
|
-
// practice outside of things like recursive filters in DSP -
|
|
76
|
-
// not a typical half-float application. Whether FP16 denormals
|
|
77
|
-
// are rare in practice, I don't know. Whatever slow path your
|
|
78
|
-
// HW may or may not have for denormals, this may well hit it.
|
|
79
|
-
float fscale = floatbits(fint & round_mask) * floatbits(magic);
|
|
80
|
-
fscale = std::min(fscale, floatbits((31u << 23) - 0x1000u));
|
|
81
|
-
int32_t fint2 = intbits(fscale) - round_mask;
|
|
82
|
-
|
|
83
|
-
if (fint < f32infty)
|
|
84
|
-
o = fint2 >> 13; // Take the bits!
|
|
85
|
-
|
|
86
|
-
return (o | (sign >> 16));
|
|
43
|
+
uint32_t o;
|
|
44
|
+
if (fint >= f16max) {
|
|
45
|
+
// Inf->Inf. NaN->qNaN with the top bits of the payload, as F16C.
|
|
46
|
+
o = (fint > f32infty) ? 0x7e00u | ((fint >> 13) & 0x3ffu) : 0x7c00u;
|
|
47
|
+
} else if (fint < (113u << 23)) {
|
|
48
|
+
// The result is subnormal or zero. Adding a magic value aligns the 10
|
|
49
|
+
// mantissa bits at the bottom of the float, and the float addition
|
|
50
|
+
// rounds to nearest even.
|
|
51
|
+
o = intbits(floatbits(fint) + floatbits(denorm_magic)) - denorm_magic;
|
|
52
|
+
} else {
|
|
53
|
+
const uint32_t mant_odd = (fint >> 13) & 1;
|
|
54
|
+
// rebias the exponent, and round to nearest even
|
|
55
|
+
fint += ((15u - 127u) << 23) + 0xfffu + mant_odd;
|
|
56
|
+
o = fint >> 13;
|
|
57
|
+
}
|
|
58
|
+
return static_cast<uint16_t>(o | (sign >> 16));
|
|
87
59
|
}
|
|
88
60
|
|
|
89
61
|
inline float decode_fp16(uint16_t h) {
|
|
@@ -105,4 +77,6 @@ inline float decode_fp16(uint16_t h) {
|
|
|
105
77
|
return floatbits(((exp == shifted_exp) ? infnan_val : reg_val) | sign_bit);
|
|
106
78
|
}
|
|
107
79
|
|
|
80
|
+
} // namespace
|
|
81
|
+
|
|
108
82
|
} // namespace faiss
|