faiss 0.6.4 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/ext/faiss/extconf.rb +1 -1
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/AutoTune.cpp +175 -0
- data/vendor/faiss/faiss/Clustering.cpp +150 -60
- data/vendor/faiss/faiss/Clustering.h +29 -0
- data/vendor/faiss/faiss/IVFlib.cpp +99 -0
- data/vendor/faiss/faiss/IVFlib.h +15 -0
- data/vendor/faiss/faiss/Index.cpp +44 -0
- data/vendor/faiss/faiss/Index.h +19 -14
- data/vendor/faiss/faiss/IndexBinary.cpp +8 -0
- data/vendor/faiss/faiss/IndexBinary.h +8 -0
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +82 -4
- data/vendor/faiss/faiss/IndexBinaryHNSW.h +19 -0
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +34 -0
- data/vendor/faiss/faiss/IndexFastScan.cpp +33 -17
- data/vendor/faiss/faiss/IndexFastScan.h +6 -3
- data/vendor/faiss/faiss/IndexFlat.cpp +56 -0
- data/vendor/faiss/faiss/IndexFlat.h +31 -0
- data/vendor/faiss/faiss/IndexFlatCodes.cpp +6 -1
- data/vendor/faiss/faiss/IndexHNSW.cpp +456 -10
- data/vendor/faiss/faiss/IndexHNSW.h +38 -0
- data/vendor/faiss/faiss/IndexIDMap.cpp +32 -0
- data/vendor/faiss/faiss/IndexIDMap.h +7 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +281 -31
- data/vendor/faiss/faiss/IndexIVF.h +53 -1
- data/vendor/faiss/faiss/IndexIVFFastScan.cpp +46 -14
- data/vendor/faiss/faiss/IndexIVFFastScan.h +4 -2
- data/vendor/faiss/faiss/IndexIVFFlat.cpp +33 -0
- data/vendor/faiss/faiss/IndexIVFFlat.h +16 -0
- data/vendor/faiss/faiss/IndexIVFPQFastScan.cpp +1 -0
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +3 -20
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +50 -14
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +5 -2
- data/vendor/faiss/faiss/IndexIVFSQFastScan.cpp +855 -0
- data/vendor/faiss/faiss/IndexIVFSQFastScan.h +145 -0
- data/vendor/faiss/faiss/IndexNNDescent.cpp +0 -3
- data/vendor/faiss/faiss/IndexPiPNN.cpp +201 -0
- data/vendor/faiss/faiss/IndexPiPNN.h +83 -0
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +6 -3
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +10 -4
- data/vendor/faiss/faiss/IndexReplicas.cpp +20 -0
- data/vendor/faiss/faiss/IndexReplicas.h +9 -0
- data/vendor/faiss/faiss/IndexSQFastScan.cpp +648 -0
- data/vendor/faiss/faiss/IndexSQFastScan.h +129 -0
- data/vendor/faiss/faiss/IndexShards.cpp +10 -0
- data/vendor/faiss/faiss/IndexShards.h +5 -0
- data/vendor/faiss/faiss/SuperKMeans.cpp +57 -15
- data/vendor/faiss/faiss/SuperKMeans.h +9 -4
- data/vendor/faiss/faiss/VectorTransform.cpp +3 -2
- data/vendor/faiss/faiss/clone_index.cpp +24 -0
- data/vendor/faiss/faiss/gpu/Dataset.h +112 -0
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +16 -13
- data/vendor/faiss/faiss/gpu/GpuCloner.h +4 -0
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +3 -0
- data/vendor/faiss/faiss/gpu/GpuIndex.h +4 -13
- data/vendor/faiss/faiss/gpu/GpuIndexBinaryCagra.h +26 -13
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +45 -22
- data/vendor/faiss/faiss/gpu/GpuIndexFlat.h +11 -0
- data/vendor/faiss/faiss/gpu/GpuIndexIVF.h +6 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuDatasetHeader.cpp +18 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexFlat.cpp +215 -0
- data/vendor/faiss/faiss/gpu/test/TestGpuIndexIVFFlat.cpp +98 -0
- data/vendor/faiss/faiss/gpu/utils/DeviceUtils.h +11 -0
- data/vendor/faiss/faiss/gpu/utils/StackDeviceMemory.cpp +1 -1
- data/vendor/faiss/faiss/gpu_metal/MetalCloner.h +11 -0
- data/vendor/faiss/faiss/gpu_metal/MetalDistance.h +92 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndex.h +4 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexBinaryFlat.h +69 -0
- data/vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h +38 -0
- data/vendor/faiss/faiss/gpu_metal/MetalKernels.h +106 -0
- data/vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h +10 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.cpp +2 -0
- data/vendor/faiss/faiss/impl/AuxIndexStructures.h +1 -6
- data/vendor/faiss/faiss/impl/ClusteringHelpers.cpp +134 -45
- data/vendor/faiss/faiss/impl/ClusteringHelpers.h +36 -0
- data/vendor/faiss/faiss/impl/ClusteringInitialization.cpp +286 -136
- data/vendor/faiss/faiss/impl/DistanceComputer.cpp +63 -0
- data/vendor/faiss/faiss/impl/DistanceComputer.h +3 -29
- data/vendor/faiss/faiss/impl/HNSW.cpp +46 -10
- data/vendor/faiss/faiss/impl/HNSW.h +72 -0
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +6 -19
- data/vendor/faiss/faiss/impl/NNDescent.cpp +2 -1
- data/vendor/faiss/faiss/impl/NSG.cpp +3 -2
- data/vendor/faiss/faiss/impl/Panorama.h +3 -2
- data/vendor/faiss/faiss/impl/PiPNN.cpp +822 -0
- data/vendor/faiss/faiss/impl/PiPNN.h +122 -0
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +54 -11
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +1 -1
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +81 -57
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +15 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +29 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +1 -6
- data/vendor/faiss/faiss/impl/approx_topk/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/approx_topk/neon.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/IndexBinaryHash_impl.h +5 -2
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/neon.cpp +0 -4
- data/vendor/faiss/faiss/impl/binary_hamming/rvv.cpp +0 -4
- data/vendor/faiss/faiss/impl/expanded_scanners.h +88 -0
- data/vendor/faiss/faiss/impl/fast_scan/FastScanDistancePostProcessing.h +4 -0
- data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops.h +61 -64
- data/vendor/faiss/faiss/impl/fast_scan/accumulate_loops_512.h +13 -14
- data/vendor/faiss/faiss/impl/fast_scan/decompose_qbs.h +17 -129
- data/vendor/faiss/faiss/impl/fast_scan/dispatching.h +25 -19
- data/vendor/faiss/faiss/impl/fast_scan/fast_scan.cpp +5 -0
- data/vendor/faiss/faiss/impl/fast_scan/impl-avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/fast_scan/impl-avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/fast_scan/impl-neon.cpp +0 -88
- data/vendor/faiss/faiss/impl/fast_scan/impl-riscv.cpp +0 -4
- data/vendor/faiss/faiss/impl/fast_scan/kernels_neon.h +155 -0
- data/vendor/faiss/faiss/impl/fast_scan/kernels_simd256.h +22 -1
- data/vendor/faiss/faiss/impl/fast_scan/kernels_simd512.h +3 -2
- data/vendor/faiss/faiss/impl/fast_scan/simd_result_handlers.h +41 -23
- data/vendor/faiss/faiss/impl/hnsw/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/hnsw/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/index_read.cpp +172 -0
- data/vendor/faiss/faiss/impl/index_write.cpp +95 -0
- data/vendor/faiss/faiss/impl/pipnn/HashPrune.cpp +159 -0
- data/vendor/faiss/faiss/impl/pipnn/HashPrune.h +69 -0
- data/vendor/faiss/faiss/impl/pipnn/Partition.cpp +587 -0
- data/vendor/faiss/faiss/impl/pipnn/Partition.h +93 -0
- data/vendor/faiss/faiss/impl/pipnn/kernels.cpp +326 -0
- data/vendor/faiss/faiss/impl/pipnn/kernels.h +92 -0
- data/vendor/faiss/faiss/impl/platform_macros.h +45 -0
- data/vendor/faiss/faiss/impl/polysemous_training/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h +79 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/PQDistanceComputer_impl.h +6 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/neon.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-avx2.h +4 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-avx512.h +4 -1
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.cpp +19 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-generic.h +6 -6
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-inl.h +131 -6
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_code_distance-sve.cpp +0 -4
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_rvv_kernel.h +89 -0
- data/vendor/faiss/faiss/impl/pq_code_distance/pq_scan_impl.h +21 -10
- data/vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp +45 -18
- data/vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp +2 -1
- data/vendor/faiss/faiss/impl/result_handler/avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/result_handler/avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp +0 -4
- data/vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp +0 -4
- data/vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h +5 -1
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +28 -52
- data/vendor/faiss/faiss/impl/scalar_quantizer/scanners.h +59 -11
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +226 -77
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-impl.h +482 -103
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512-spr.cpp +2 -149
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx512.cpp +3 -698
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-dispatch.h +66 -57
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +101 -96
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-rvv.cpp +3185 -144
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq8_coefficients.h +48 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq8_rvv_kernel.h +546 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/training.cpp +2 -2
- data/vendor/faiss/faiss/impl/simd_dispatch.h +7 -0
- data/vendor/faiss/faiss/impl/simdlib/simdlib_avx2.h +14 -0
- data/vendor/faiss/faiss/impl/simdlib/simdlib_dispatch.h +7 -8
- data/vendor/faiss/faiss/impl/sq_fastscan_utils.h +232 -0
- data/vendor/faiss/faiss/index_factory.cpp +76 -0
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +3 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +3 -2
- data/vendor/faiss/faiss/utils/AlignedTable.h +6 -1
- data/vendor/faiss/faiss/utils/Heap.cpp +4 -3
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +16 -5
- data/vendor/faiss/faiss/utils/bf16.h +36 -0
- data/vendor/faiss/faiss/utils/distances.cpp +226 -15
- data/vendor/faiss/faiss/utils/distances.h +34 -0
- data/vendor/faiss/faiss/utils/distances_dispatch.h +6 -4
- data/vendor/faiss/faiss/utils/distances_fused/avx512.cpp +2 -5
- data/vendor/faiss/faiss/utils/distances_fused/distances_fused.cpp +0 -14
- data/vendor/faiss/faiss/utils/distances_fused/rvv.cpp +25 -0
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based.cpp +0 -4
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_based_neon.cpp +0 -4
- data/vendor/faiss/faiss/utils/distances_fused/simdlib_kernel-inl.h +2 -1
- data/vendor/faiss/faiss/utils/distances_simd.cpp +9 -0
- data/vendor/faiss/faiss/utils/fp16-fp16c.h +4 -0
- data/vendor/faiss/faiss/utils/fp16-inl.h +26 -52
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx2.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_avx512_vpopcnt.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512.h +33 -5
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-avx512_vpopcnt.h +15 -30
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_computer-neon.h +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_impl.h +2 -1
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_neon.cpp +0 -4
- data/vendor/faiss/faiss/utils/hamming_distance/hamming_rvv.cpp +0 -4
- data/vendor/faiss/faiss/utils/pq_code_distance.h +8 -4
- data/vendor/faiss/faiss/utils/prefetch.h +1 -26
- data/vendor/faiss/faiss/utils/quantize_lut.cpp +26 -27
- data/vendor/faiss/faiss/utils/quantize_lut.h +11 -0
- data/vendor/faiss/faiss/utils/rabitq_simd.h +51 -16
- data/vendor/faiss/faiss/utils/simd_impl/distances_aarch64.cpp +9 -4
- data/vendor/faiss/faiss/utils/simd_impl/distances_arm_sve.cpp +37 -5
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx2.cpp +64 -5
- data/vendor/faiss/faiss/utils/simd_impl/distances_avx512.cpp +64 -5
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv.cpp +353 -71
- data/vendor/faiss/faiss/utils/simd_impl/distances_rvv_kernel.h +68 -0
- data/vendor/faiss/faiss/utils/simd_impl/exhaustive_L2sqr_blas_cmax.h +93 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels.h +76 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_avx2.cpp +52 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_avx512.cpp +52 -0
- data/vendor/faiss/faiss/utils/simd_impl/fp16_kernels_neon.cpp +48 -0
- data/vendor/faiss/faiss/utils/simd_impl/masked_sum-avx2.h +44 -0
- data/vendor/faiss/faiss/utils/simd_impl/masked_sum-avx512.h +43 -0
- data/vendor/faiss/faiss/utils/simd_impl/masked_sum.h +38 -0
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_avx2.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/partitioning_neon.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +54 -15
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +38 -21
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_vpopcnt.cpp +51 -14
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_neon.cpp +297 -10
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_rvv.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx2.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_avx512.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_impl/super_kmeans_kernels_sve.cpp +0 -4
- data/vendor/faiss/faiss/utils/simd_levels.cpp +19 -3
- data/vendor/faiss/faiss/utils/simd_levels.h +74 -1
- data/vendor/faiss/faiss/utils/transpose/transpose-avx2-inl.h +0 -4
- data/vendor/faiss/faiss/utils/transpose/transpose-avx512-inl.h +0 -4
- data/vendor/faiss/faiss/utils/utils.cpp +80 -0
- data/vendor/faiss/faiss/utils/utils.h +24 -0
- metadata +33 -1
|
@@ -7,11 +7,93 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
+
#include <algorithm>
|
|
11
|
+
#include <cstddef>
|
|
12
|
+
#include <cstdint>
|
|
13
|
+
#include <memory>
|
|
14
|
+
|
|
10
15
|
#include <faiss/impl/ResultHandler.h>
|
|
16
|
+
#include <faiss/utils/distances.h>
|
|
11
17
|
#include <faiss/utils/simd_levels.h>
|
|
18
|
+
#include <faiss/utils/utils.h>
|
|
12
19
|
|
|
13
20
|
namespace faiss {
|
|
14
21
|
|
|
22
|
+
/** fp32 query tiles for the BLAS exhaustive-search kernels.
|
|
23
|
+
*
|
|
24
|
+
* A kernel calls prepare_norms() once, then tile(i0, i1, x_norms) for each
|
|
25
|
+
* query tile; the returned rows stay valid until the next tile() call.
|
|
26
|
+
*/
|
|
27
|
+
struct Fp32QueryTiles {
|
|
28
|
+
const float* x;
|
|
29
|
+
size_t d;
|
|
30
|
+
|
|
31
|
+
/// squared L2 norms of all nx queries
|
|
32
|
+
void prepare_norms(size_t nx, float* x_norms) const {
|
|
33
|
+
fvec_norms_L2sqr(x_norms, x, d, nx);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const float* tile(size_t i0, size_t /*i1*/, float* /*x_norms*/) const {
|
|
37
|
+
return x + i0 * d;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/** Packed IEEE binary16 query tiles for the BLAS exhaustive-search kernels.
|
|
42
|
+
*
|
|
43
|
+
* Queries are widened in chunks of whole tiles (at most chunk_bytes of fp32,
|
|
44
|
+
* at least one tile) into a buffer reused across chunks: the fp32 copy stays
|
|
45
|
+
* bounded and each widened tile serves all database tiles. Norms are computed
|
|
46
|
+
* from the widened rows, so results match the fp32 kernels on the widened
|
|
47
|
+
* queries.
|
|
48
|
+
*/
|
|
49
|
+
struct Fp16QueryTiles {
|
|
50
|
+
static constexpr size_t chunk_bytes = size_t(16) << 20;
|
|
51
|
+
|
|
52
|
+
const uint16_t* x;
|
|
53
|
+
size_t d;
|
|
54
|
+
size_t nx;
|
|
55
|
+
std::unique_ptr<float[]> buffer;
|
|
56
|
+
size_t chunk_rows = 0;
|
|
57
|
+
size_t chunk_begin = 0;
|
|
58
|
+
size_t chunk_end = 0;
|
|
59
|
+
|
|
60
|
+
Fp16QueryTiles(const uint16_t* x_in, size_t d_in, size_t nx_in)
|
|
61
|
+
: x(x_in), d(d_in), nx(nx_in) {}
|
|
62
|
+
|
|
63
|
+
void prepare_norms(size_t /*nx*/, float* /*x_norms*/) const {}
|
|
64
|
+
|
|
65
|
+
/** widened rows [i0, i1), and their norms if x_norms is not null
|
|
66
|
+
*
|
|
67
|
+
* Tiles are requested in order, all of the same size except the last.
|
|
68
|
+
*/
|
|
69
|
+
const float* tile(size_t i0, size_t i1, float* x_norms) {
|
|
70
|
+
if (i1 > chunk_end) {
|
|
71
|
+
if (!buffer) {
|
|
72
|
+
const size_t tile_rows = i1 - i0;
|
|
73
|
+
chunk_rows =
|
|
74
|
+
tile_rows *
|
|
75
|
+
std::max<size_t>(
|
|
76
|
+
1,
|
|
77
|
+
chunk_bytes / (tile_rows * d * sizeof(float)));
|
|
78
|
+
chunk_rows = std::min(chunk_rows, nx - i0);
|
|
79
|
+
buffer.reset(new float[chunk_rows * d]);
|
|
80
|
+
}
|
|
81
|
+
chunk_begin = i0;
|
|
82
|
+
chunk_end = std::min(nx, i0 + chunk_rows);
|
|
83
|
+
const int64_t n = static_cast<int64_t>(chunk_end - chunk_begin);
|
|
84
|
+
#pragma omp parallel for if (n * static_cast<int64_t>(d) > (1 << 16))
|
|
85
|
+
for (int64_t i = 0; i < n; i++) {
|
|
86
|
+
float* row = buffer.get() + i * d;
|
|
87
|
+
fp16_to_fp32(d, x + (chunk_begin + i) * d, row);
|
|
88
|
+
if (x_norms) {
|
|
89
|
+
x_norms[chunk_begin + i] = fvec_norm_L2sqr(row, d);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return buffer.get() + (i0 - chunk_begin) * d;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
15
97
|
/// BLAS-accelerated exhaustive L2 search for the k=1 (top-1) case.
|
|
16
98
|
/// Specializations live in the per-SIMD translation units under simd_impl/.
|
|
17
99
|
template <SIMDLevel>
|
|
@@ -24,4 +106,15 @@ void exhaustive_L2sqr_blas_cmax(
|
|
|
24
106
|
Top1BlockResultHandler<CMax<float, int64_t>>& res,
|
|
25
107
|
const float* y_norms);
|
|
26
108
|
|
|
109
|
+
/// Same as exhaustive_L2sqr_blas_cmax for packed IEEE binary16 queries.
|
|
110
|
+
template <SIMDLevel>
|
|
111
|
+
void exhaustive_L2sqr_blas_cmax_fp16(
|
|
112
|
+
const uint16_t* x,
|
|
113
|
+
const float* y,
|
|
114
|
+
size_t d,
|
|
115
|
+
size_t nx,
|
|
116
|
+
size_t ny,
|
|
117
|
+
Top1BlockResultHandler<CMax<float, int64_t>>& res,
|
|
118
|
+
const float* y_norms);
|
|
119
|
+
|
|
27
120
|
} // namespace faiss
|
|
@@ -0,0 +1,76 @@
|
|
|
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
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include <cstddef>
|
|
11
|
+
#include <cstdint>
|
|
12
|
+
|
|
13
|
+
#include <faiss/utils/fp16.h>
|
|
14
|
+
#include <faiss/utils/simd_levels.h>
|
|
15
|
+
|
|
16
|
+
namespace faiss {
|
|
17
|
+
namespace detail {
|
|
18
|
+
|
|
19
|
+
// c[j] += fp32(x[j]) * w for j < d
|
|
20
|
+
template <SIMDLevel Level>
|
|
21
|
+
inline void fp16_madd(size_t d, const uint16_t* x, float w, float* c) {
|
|
22
|
+
for (size_t j = 0; j < d; ++j) {
|
|
23
|
+
c[j] += decode_fp16(x[j]) * w;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
template <SIMDLevel Level>
|
|
28
|
+
inline void fp16_to_fp32_kernel(size_t n, const uint16_t* x, float* out) {
|
|
29
|
+
for (size_t j = 0; j < n; ++j) {
|
|
30
|
+
out[j] = decode_fp16(x[j]);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
#ifdef COMPILE_SIMD_AVX2
|
|
35
|
+
template <>
|
|
36
|
+
void fp16_madd<SIMDLevel::AVX2>(size_t d, const uint16_t* x, float w, float* c);
|
|
37
|
+
|
|
38
|
+
template <>
|
|
39
|
+
void fp16_to_fp32_kernel<SIMDLevel::AVX2>(
|
|
40
|
+
size_t n,
|
|
41
|
+
const uint16_t* x,
|
|
42
|
+
float* out);
|
|
43
|
+
#endif
|
|
44
|
+
|
|
45
|
+
#ifdef COMPILE_SIMD_AVX512
|
|
46
|
+
template <>
|
|
47
|
+
void fp16_madd<SIMDLevel::AVX512>(
|
|
48
|
+
size_t d,
|
|
49
|
+
const uint16_t* x,
|
|
50
|
+
float w,
|
|
51
|
+
float* c);
|
|
52
|
+
|
|
53
|
+
template <>
|
|
54
|
+
void fp16_to_fp32_kernel<SIMDLevel::AVX512>(
|
|
55
|
+
size_t n,
|
|
56
|
+
const uint16_t* x,
|
|
57
|
+
float* out);
|
|
58
|
+
#endif
|
|
59
|
+
|
|
60
|
+
#ifdef COMPILE_SIMD_ARM_NEON
|
|
61
|
+
template <>
|
|
62
|
+
void fp16_madd<SIMDLevel::ARM_NEON>(
|
|
63
|
+
size_t d,
|
|
64
|
+
const uint16_t* x,
|
|
65
|
+
float w,
|
|
66
|
+
float* c);
|
|
67
|
+
|
|
68
|
+
template <>
|
|
69
|
+
void fp16_to_fp32_kernel<SIMDLevel::ARM_NEON>(
|
|
70
|
+
size_t n,
|
|
71
|
+
const uint16_t* x,
|
|
72
|
+
float* out);
|
|
73
|
+
#endif
|
|
74
|
+
|
|
75
|
+
} // namespace detail
|
|
76
|
+
} // namespace faiss
|
|
@@ -0,0 +1,52 @@
|
|
|
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/simd_impl/fp16_kernels.h>
|
|
9
|
+
|
|
10
|
+
#include <immintrin.h>
|
|
11
|
+
|
|
12
|
+
namespace faiss {
|
|
13
|
+
namespace detail {
|
|
14
|
+
|
|
15
|
+
template <>
|
|
16
|
+
void fp16_madd<SIMDLevel::AVX2>(
|
|
17
|
+
size_t d,
|
|
18
|
+
const uint16_t* x,
|
|
19
|
+
float w,
|
|
20
|
+
float* c) {
|
|
21
|
+
const __m256 wv = _mm256_set1_ps(w);
|
|
22
|
+
size_t j = 0;
|
|
23
|
+
for (; j + 8 <= d; j += 8) {
|
|
24
|
+
const __m256 xv = _mm256_cvtph_ps(
|
|
25
|
+
_mm_loadu_si128(reinterpret_cast<const __m128i*>(x + j)));
|
|
26
|
+
_mm256_storeu_ps(
|
|
27
|
+
c + j,
|
|
28
|
+
_mm256_add_ps(_mm256_loadu_ps(c + j), _mm256_mul_ps(xv, wv)));
|
|
29
|
+
}
|
|
30
|
+
for (; j < d; ++j) {
|
|
31
|
+
c[j] += decode_fp16(x[j]) * w;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
template <>
|
|
36
|
+
void fp16_to_fp32_kernel<SIMDLevel::AVX2>(
|
|
37
|
+
size_t n,
|
|
38
|
+
const uint16_t* x,
|
|
39
|
+
float* out) {
|
|
40
|
+
size_t j = 0;
|
|
41
|
+
for (; j + 8 <= n; j += 8) {
|
|
42
|
+
const __m128i h =
|
|
43
|
+
_mm_loadu_si128(reinterpret_cast<const __m128i*>(x + j));
|
|
44
|
+
_mm256_storeu_ps(out + j, _mm256_cvtph_ps(h));
|
|
45
|
+
}
|
|
46
|
+
for (; j < n; ++j) {
|
|
47
|
+
out[j] = decode_fp16(x[j]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
} // namespace detail
|
|
52
|
+
} // namespace faiss
|
|
@@ -0,0 +1,52 @@
|
|
|
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/simd_impl/fp16_kernels.h>
|
|
9
|
+
|
|
10
|
+
#include <immintrin.h>
|
|
11
|
+
|
|
12
|
+
namespace faiss {
|
|
13
|
+
namespace detail {
|
|
14
|
+
|
|
15
|
+
template <>
|
|
16
|
+
void fp16_madd<SIMDLevel::AVX512>(
|
|
17
|
+
size_t d,
|
|
18
|
+
const uint16_t* x,
|
|
19
|
+
float w,
|
|
20
|
+
float* c) {
|
|
21
|
+
const __m512 wv = _mm512_set1_ps(w);
|
|
22
|
+
size_t j = 0;
|
|
23
|
+
for (; j + 16 <= d; j += 16) {
|
|
24
|
+
const __m512 xv = _mm512_cvtph_ps(
|
|
25
|
+
_mm256_loadu_si256(reinterpret_cast<const __m256i*>(x + j)));
|
|
26
|
+
_mm512_storeu_ps(
|
|
27
|
+
c + j,
|
|
28
|
+
_mm512_add_ps(_mm512_loadu_ps(c + j), _mm512_mul_ps(xv, wv)));
|
|
29
|
+
}
|
|
30
|
+
for (; j < d; ++j) {
|
|
31
|
+
c[j] += decode_fp16(x[j]) * w;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
template <>
|
|
36
|
+
void fp16_to_fp32_kernel<SIMDLevel::AVX512>(
|
|
37
|
+
size_t n,
|
|
38
|
+
const uint16_t* x,
|
|
39
|
+
float* out) {
|
|
40
|
+
size_t j = 0;
|
|
41
|
+
for (; j + 16 <= n; j += 16) {
|
|
42
|
+
const __m256i h =
|
|
43
|
+
_mm256_loadu_si256(reinterpret_cast<const __m256i*>(x + j));
|
|
44
|
+
_mm512_storeu_ps(out + j, _mm512_cvtph_ps(h));
|
|
45
|
+
}
|
|
46
|
+
for (; j < n; ++j) {
|
|
47
|
+
out[j] = decode_fp16(x[j]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
} // namespace detail
|
|
52
|
+
} // namespace faiss
|
|
@@ -0,0 +1,48 @@
|
|
|
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/simd_impl/fp16_kernels.h>
|
|
9
|
+
|
|
10
|
+
#include <arm_neon.h>
|
|
11
|
+
|
|
12
|
+
namespace faiss {
|
|
13
|
+
namespace detail {
|
|
14
|
+
|
|
15
|
+
template <>
|
|
16
|
+
void fp16_madd<SIMDLevel::ARM_NEON>(
|
|
17
|
+
size_t d,
|
|
18
|
+
const uint16_t* x,
|
|
19
|
+
float w,
|
|
20
|
+
float* c) {
|
|
21
|
+
const float32x4_t wv = vdupq_n_f32(w);
|
|
22
|
+
size_t j = 0;
|
|
23
|
+
for (; j + 4 <= d; j += 4) {
|
|
24
|
+
const float32x4_t xv =
|
|
25
|
+
vcvt_f32_f16(vreinterpret_f16_u16(vld1_u16(x + j)));
|
|
26
|
+
vst1q_f32(c + j, vaddq_f32(vld1q_f32(c + j), vmulq_f32(xv, wv)));
|
|
27
|
+
}
|
|
28
|
+
for (; j < d; ++j) {
|
|
29
|
+
c[j] += decode_fp16(x[j]) * w;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
template <>
|
|
34
|
+
void fp16_to_fp32_kernel<SIMDLevel::ARM_NEON>(
|
|
35
|
+
size_t n,
|
|
36
|
+
const uint16_t* x,
|
|
37
|
+
float* out) {
|
|
38
|
+
size_t j = 0;
|
|
39
|
+
for (; j + 4 <= n; j += 4) {
|
|
40
|
+
vst1q_f32(out + j, vcvt_f32_f16(vreinterpret_f16_u16(vld1_u16(x + j))));
|
|
41
|
+
}
|
|
42
|
+
for (; j < n; ++j) {
|
|
43
|
+
out[j] = decode_fp16(x[j]);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
} // namespace detail
|
|
48
|
+
} // namespace faiss
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include <immintrin.h>
|
|
11
|
+
|
|
12
|
+
#include <faiss/utils/simd_impl/masked_sum.h>
|
|
13
|
+
|
|
14
|
+
namespace faiss {
|
|
15
|
+
namespace {
|
|
16
|
+
|
|
17
|
+
template <>
|
|
18
|
+
inline float masked_sum<SIMDLevel::AVX2>(
|
|
19
|
+
const float* x,
|
|
20
|
+
const uint8_t* bits,
|
|
21
|
+
size_t d) {
|
|
22
|
+
const __m256i bit_masks = _mm256_set_epi32(128, 64, 32, 16, 8, 4, 2, 1);
|
|
23
|
+
__m256 acc = _mm256_setzero_ps();
|
|
24
|
+
const size_t full_bytes = d / 8;
|
|
25
|
+
for (size_t byte_idx = 0; byte_idx < full_bytes; byte_idx++) {
|
|
26
|
+
const __m256i byte_broadcast = _mm256_set1_epi32(bits[byte_idx]);
|
|
27
|
+
const __m256i masked = _mm256_and_si256(byte_broadcast, bit_masks);
|
|
28
|
+
const __m256 mask =
|
|
29
|
+
_mm256_castsi256_ps(_mm256_cmpeq_epi32(masked, bit_masks));
|
|
30
|
+
const __m256 vals = _mm256_loadu_ps(x + byte_idx * 8);
|
|
31
|
+
acc = _mm256_add_ps(acc, _mm256_and_ps(mask, vals));
|
|
32
|
+
}
|
|
33
|
+
__m128 sum128 = _mm_add_ps(
|
|
34
|
+
_mm256_castps256_ps128(acc), _mm256_extractf128_ps(acc, 1));
|
|
35
|
+
__m128 shuf = _mm_movehdup_ps(sum128);
|
|
36
|
+
__m128 sums = _mm_add_ps(sum128, shuf);
|
|
37
|
+
shuf = _mm_movehl_ps(shuf, sums);
|
|
38
|
+
sums = _mm_add_ss(sums, shuf);
|
|
39
|
+
return _mm_cvtss_f32(sums) +
|
|
40
|
+
masked_sum_scalar(x + full_bytes * 8, bits + full_bytes, d % 8);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
} // namespace
|
|
44
|
+
} // namespace faiss
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include <cstring>
|
|
11
|
+
|
|
12
|
+
#include <immintrin.h>
|
|
13
|
+
|
|
14
|
+
#include <faiss/utils/simd_impl/masked_sum.h>
|
|
15
|
+
|
|
16
|
+
namespace faiss {
|
|
17
|
+
namespace {
|
|
18
|
+
|
|
19
|
+
template <>
|
|
20
|
+
inline float masked_sum<SIMDLevel::AVX512>(
|
|
21
|
+
const float* x,
|
|
22
|
+
const uint8_t* bits,
|
|
23
|
+
size_t d) {
|
|
24
|
+
__m512 acc = _mm512_setzero_ps();
|
|
25
|
+
size_t i = 0;
|
|
26
|
+
for (; i + 16 <= d; i += 16) {
|
|
27
|
+
uint16_t mask16;
|
|
28
|
+
memcpy(&mask16, bits + i / 8, sizeof(mask16));
|
|
29
|
+
acc = _mm512_mask_add_ps(acc, mask16, acc, _mm512_loadu_ps(x + i));
|
|
30
|
+
}
|
|
31
|
+
if (i < d) {
|
|
32
|
+
uint32_t mask = bits[i / 8];
|
|
33
|
+
if (d - i > 8) {
|
|
34
|
+
mask |= uint32_t(bits[i / 8 + 1]) << 8;
|
|
35
|
+
}
|
|
36
|
+
const __mmask16 k = mask & ((1u << (d - i)) - 1);
|
|
37
|
+
acc = _mm512_add_ps(acc, _mm512_maskz_loadu_ps(k, x + i));
|
|
38
|
+
}
|
|
39
|
+
return _mm512_reduce_add_ps(acc);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
} // namespace
|
|
43
|
+
} // namespace faiss
|
|
@@ -0,0 +1,38 @@
|
|
|
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
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include <cstddef>
|
|
11
|
+
#include <cstdint>
|
|
12
|
+
|
|
13
|
+
#include <faiss/utils/simd_levels.h>
|
|
14
|
+
|
|
15
|
+
namespace faiss {
|
|
16
|
+
|
|
17
|
+
// Internal linkage: each file compiles these with its own flags.
|
|
18
|
+
// masked_sum-avx2.h and masked_sum-avx512.h specialize masked_sum.
|
|
19
|
+
namespace {
|
|
20
|
+
|
|
21
|
+
inline float masked_sum_scalar(const float* x, const uint8_t* bits, size_t d) {
|
|
22
|
+
float sum = 0;
|
|
23
|
+
for (size_t j = 0; j < d; j++) {
|
|
24
|
+
if ((bits[j / 8] >> (j % 8)) & 1) {
|
|
25
|
+
sum += x[j];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return sum;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
template <SIMDLevel SL>
|
|
32
|
+
inline float masked_sum(const float* x, const uint8_t* bits, size_t d) {
|
|
33
|
+
return masked_sum_scalar(x, bits, d);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
} // namespace
|
|
37
|
+
|
|
38
|
+
} // namespace faiss
|
|
@@ -5,10 +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
|
#define THE_SIMD_LEVEL SIMDLevel::AVX2
|
|
11
9
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
12
10
|
#include <faiss/utils/simd_impl/partitioning_simdlib256.h>
|
|
13
|
-
|
|
14
|
-
#endif // COMPILE_SIMD_AVX2
|
|
@@ -5,10 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
#ifdef COMPILE_SIMD_ARM_NEON
|
|
9
|
-
|
|
10
8
|
#define THE_SIMD_LEVEL SIMDLevel::ARM_NEON
|
|
11
9
|
// NOLINTNEXTLINE(facebook-hte-InlineHeader)
|
|
12
10
|
#include <faiss/utils/simd_impl/partitioning_simdlib256.h>
|
|
13
|
-
|
|
14
|
-
#endif // COMPILE_SIMD_ARM_NEON
|
|
@@ -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/rabitq_simd.h>
|
|
11
9
|
#include <immintrin.h>
|
|
12
10
|
#include <limits>
|
|
@@ -275,9 +273,11 @@ uint64_t bitwise_and_dot_product<SIMDLevel::AVX2>(
|
|
|
275
273
|
}
|
|
276
274
|
sum += reduce_add_128(sum_128);
|
|
277
275
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
278
|
-
|
|
276
|
+
uint64_t yv;
|
|
277
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
279
278
|
for (int j = 0; j < qb; j++) {
|
|
280
|
-
|
|
279
|
+
uint64_t qv;
|
|
280
|
+
std::memcpy(&qv, query + j * size + offset, sizeof(qv));
|
|
281
281
|
sum += popcount64(qv & yv) << j;
|
|
282
282
|
}
|
|
283
283
|
}
|
|
@@ -336,10 +336,12 @@ BitwiseAndDotProductResult bitwise_and_dot_product_with_popcount<
|
|
|
336
336
|
dot_product += reduce_add_128(dot_128);
|
|
337
337
|
popcount_sum += reduce_add_128(pop_128);
|
|
338
338
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
339
|
-
|
|
339
|
+
uint64_t yv;
|
|
340
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
340
341
|
popcount_sum += popcount64(yv);
|
|
341
342
|
for (int j = 0; j < qb; j++) {
|
|
342
|
-
|
|
343
|
+
uint64_t qv;
|
|
344
|
+
std::memcpy(&qv, query + j * size + offset, sizeof(qv));
|
|
343
345
|
dot_product += popcount64(qv & yv) << j;
|
|
344
346
|
}
|
|
345
347
|
}
|
|
@@ -391,9 +393,11 @@ uint64_t bitwise_xor_dot_product<SIMDLevel::AVX2>(
|
|
|
391
393
|
}
|
|
392
394
|
sum += reduce_add_128(sum_128);
|
|
393
395
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
394
|
-
|
|
396
|
+
uint64_t yv;
|
|
397
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
395
398
|
for (int j = 0; j < qb; j++) {
|
|
396
|
-
|
|
399
|
+
uint64_t qv;
|
|
400
|
+
std::memcpy(&qv, query + j * size + offset, sizeof(qv));
|
|
397
401
|
sum += popcount64(qv ^ yv) << j;
|
|
398
402
|
}
|
|
399
403
|
}
|
|
@@ -427,7 +431,8 @@ uint64_t popcount<SIMDLevel::AVX2>(const uint8_t* data, size_t size) {
|
|
|
427
431
|
}
|
|
428
432
|
sum += reduce_add_128(sum_128);
|
|
429
433
|
for (size_t step = 64 / 8; offset + step <= size; offset += step) {
|
|
430
|
-
|
|
434
|
+
uint64_t yv;
|
|
435
|
+
std::memcpy(&yv, data + offset, sizeof(yv));
|
|
431
436
|
sum += popcount64(yv);
|
|
432
437
|
}
|
|
433
438
|
for (; offset < size; ++offset) {
|
|
@@ -517,7 +522,6 @@ inline float ip_1exbit_avx2(
|
|
|
517
522
|
return result;
|
|
518
523
|
}
|
|
519
524
|
|
|
520
|
-
#ifdef __BMI2__
|
|
521
525
|
inline float ip_bitplane_avx2(
|
|
522
526
|
const uint8_t* __restrict sign_bits,
|
|
523
527
|
const uint8_t* __restrict ex_code,
|
|
@@ -571,7 +575,6 @@ inline float ip_bitplane_avx2(
|
|
|
571
575
|
result += ip_scalar(sign_bits, ex_code, rotated_q, i, d, ex_bits, cb);
|
|
572
576
|
return result;
|
|
573
577
|
}
|
|
574
|
-
#endif // __BMI2__
|
|
575
578
|
|
|
576
579
|
} // namespace
|
|
577
580
|
|
|
@@ -583,18 +586,54 @@ float compute_inner_product<SIMDLevel::AVX2>(
|
|
|
583
586
|
size_t d,
|
|
584
587
|
size_t ex_bits,
|
|
585
588
|
float cb) {
|
|
589
|
+
if (ex_bits == 8) {
|
|
590
|
+
// Eight byte-aligned extra codes, plus their independent sign bits.
|
|
591
|
+
// One sign-word broadcast serves 32 dims, to save shuffle-port uops.
|
|
592
|
+
__m256 acc0 = _mm256_setzero_ps();
|
|
593
|
+
__m256 acc1 = _mm256_setzero_ps();
|
|
594
|
+
const __m256 weight = _mm256_set1_ps(256.f);
|
|
595
|
+
const __m256 offset = _mm256_set1_ps(cb);
|
|
596
|
+
const __m256i positions =
|
|
597
|
+
_mm256_setr_epi32(1, 2, 4, 8, 16, 32, 64, 128);
|
|
598
|
+
// cmpeq, not cmpgt: bit 31 of the shifted positions is a sign bit.
|
|
599
|
+
auto step = [&](__m256& acc, size_t i, __m256i signs, __m256i pos) {
|
|
600
|
+
const __m128i bytes = _mm_loadl_epi64(
|
|
601
|
+
reinterpret_cast<const __m128i*>(ex_code + i));
|
|
602
|
+
const __m256 extra =
|
|
603
|
+
_mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(bytes));
|
|
604
|
+
const __m256i mask =
|
|
605
|
+
_mm256_cmpeq_epi32(_mm256_and_si256(signs, pos), pos);
|
|
606
|
+
const __m256 recon = _mm256_add_ps(
|
|
607
|
+
extra, _mm256_and_ps(_mm256_castsi256_ps(mask), weight));
|
|
608
|
+
acc = _mm256_fmadd_ps(
|
|
609
|
+
_mm256_loadu_ps(rotated_q + i),
|
|
610
|
+
_mm256_add_ps(recon, offset),
|
|
611
|
+
acc);
|
|
612
|
+
};
|
|
613
|
+
size_t i = 0;
|
|
614
|
+
for (; i + 32 <= d; i += 32) {
|
|
615
|
+
uint32_t word;
|
|
616
|
+
memcpy(&word, sign_bits + i / 8, sizeof(word));
|
|
617
|
+
const __m256i signs = _mm256_set1_epi32(static_cast<int>(word));
|
|
618
|
+
step(acc0, i, signs, positions);
|
|
619
|
+
step(acc1, i + 8, signs, _mm256_slli_epi32(positions, 8));
|
|
620
|
+
step(acc0, i + 16, signs, _mm256_slli_epi32(positions, 16));
|
|
621
|
+
step(acc1, i + 24, signs, _mm256_slli_epi32(positions, 24));
|
|
622
|
+
}
|
|
623
|
+
for (; i + 8 <= d; i += 8) {
|
|
624
|
+
step(acc0, i, _mm256_set1_epi32(sign_bits[i / 8]), positions);
|
|
625
|
+
}
|
|
626
|
+
return hsum_avx2(_mm256_add_ps(acc0, acc1)) +
|
|
627
|
+
ip_scalar(sign_bits, ex_code, rotated_q, i, d, ex_bits, cb);
|
|
628
|
+
}
|
|
586
629
|
if (ex_bits == 1) {
|
|
587
630
|
return ip_1exbit_avx2(sign_bits, ex_code, rotated_q, d, cb);
|
|
588
631
|
}
|
|
589
632
|
|
|
590
|
-
#ifdef __BMI2__
|
|
591
633
|
if (ex_bits <= 7) {
|
|
592
634
|
return ip_bitplane_avx2(sign_bits, ex_code, rotated_q, d, ex_bits, cb);
|
|
593
635
|
}
|
|
594
|
-
#endif
|
|
595
636
|
return ip_scalar(sign_bits, ex_code, rotated_q, 0, d, ex_bits, cb);
|
|
596
637
|
}
|
|
597
638
|
|
|
598
639
|
} // namespace faiss::rabitq::multibit
|
|
599
|
-
|
|
600
|
-
#endif // COMPILE_SIMD_AVX2
|