faiss 0.6.2 → 0.6.3
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/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/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 +1 -2
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +4 -5
- data/vendor/faiss/faiss/IndexBinaryHash.cpp +5 -9
- data/vendor/faiss/faiss/IndexBinaryIVF.cpp +2 -4
- 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 +13 -50
- data/vendor/faiss/faiss/IndexHNSW.cpp +10 -11
- data/vendor/faiss/faiss/IndexIDMap.cpp +16 -3
- data/vendor/faiss/faiss/IndexIDMap.h +2 -0
- data/vendor/faiss/faiss/IndexIVF.cpp +17 -6
- 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 +40 -22
- 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 +2 -2
- data/vendor/faiss/faiss/IndexShardsIVF.cpp +2 -2
- data/vendor/faiss/faiss/MetaIndexes.cpp +2 -4
- data/vendor/faiss/faiss/SuperKMeans.cpp +256 -240
- data/vendor/faiss/faiss/SuperKMeans.h +30 -0
- data/vendor/faiss/faiss/VectorTransform.cpp +33 -2
- data/vendor/faiss/faiss/clone_index.cpp +5 -0
- data/vendor/faiss/faiss/factory_tools.cpp +47 -4
- data/vendor/faiss/faiss/gpu/GpuCloner.cpp +11 -11
- data/vendor/faiss/faiss/gpu/GpuIndex.h +34 -11
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +47 -0
- 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/ClusteringInitialization.cpp +2 -2
- 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 +109 -152
- data/vendor/faiss/faiss/impl/LocalSearchQuantizer.cpp +2 -2
- data/vendor/faiss/faiss/impl/NSG.cpp +3 -1
- data/vendor/faiss/faiss/impl/Panorama.h +9 -7
- data/vendor/faiss/faiss/impl/PolysemousTraining.cpp +152 -84
- data/vendor/faiss/faiss/impl/ProductQuantizer.cpp +34 -22
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +44 -36
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +35 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +168 -67
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +19 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +2 -11
- data/vendor/faiss/faiss/impl/ResultHandler.h +25 -31
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +258 -57
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +20 -0
- 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 +1 -1
- data/vendor/faiss/faiss/impl/binary_hamming/avx2.cpp +4 -4
- 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 +376 -36
- data/vendor/faiss/faiss/impl/index_write.cpp +55 -4
- 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/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/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 +882 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h +9 -8
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-avx2.cpp +85 -23
- 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 +136 -0
- data/vendor/faiss/faiss/impl/scalar_quantizer/sq-neon.cpp +16 -16
- data/vendor/faiss/faiss/impl/simd_dispatch.h +30 -9
- data/vendor/faiss/faiss/index_factory.cpp +32 -6
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +2 -2
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +19 -4
- 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 +31 -1
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +15 -2
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +1 -2
- data/vendor/faiss/faiss/utils/approx_topk_hamming/approx_topk_hamming.h +1 -1
- data/vendor/faiss/faiss/utils/distances.cpp +14 -2
- 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 +1 -1
- 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_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 +160 -18
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx2.cpp +245 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512.cpp +273 -0
- data/vendor/faiss/faiss/utils/simd_impl/rabitq_avx512_spr.cpp +92 -0
- 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_levels.cpp +44 -0
- data/vendor/faiss/faiss/utils/simd_levels.h +14 -0
- data/vendor/faiss/faiss/utils/utils.cpp +9 -27
- metadata +16 -1
|
@@ -5,19 +5,107 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
// -*- c++ -*-
|
|
9
|
+
|
|
8
10
|
#include <faiss/utils/rabitq_simd.h>
|
|
9
11
|
|
|
10
12
|
#ifdef COMPILE_SIMD_RISCV_RVV
|
|
11
13
|
|
|
14
|
+
#include <riscv_vector.h>
|
|
15
|
+
|
|
12
16
|
namespace faiss::rabitq {
|
|
13
17
|
|
|
18
|
+
// SWAR per-byte popcount over a u8m4 group: each output byte holds the
|
|
19
|
+
// population count (0..8) of the corresponding input byte.
|
|
20
|
+
static inline vuint8m4_t popcount_u8m4(vuint8m4_t v, size_t vl) {
|
|
21
|
+
vuint8m4_t t = __riscv_vsrl_vx_u8m4(v, 1, vl);
|
|
22
|
+
t = __riscv_vand_vx_u8m4(t, 0x55, vl);
|
|
23
|
+
v = __riscv_vsub_vv_u8m4(v, t, vl);
|
|
24
|
+
t = __riscv_vsrl_vx_u8m4(v, 2, vl);
|
|
25
|
+
t = __riscv_vand_vx_u8m4(t, 0x33, vl);
|
|
26
|
+
v = __riscv_vand_vx_u8m4(v, 0x33, vl);
|
|
27
|
+
v = __riscv_vadd_vv_u8m4(v, t, vl);
|
|
28
|
+
t = __riscv_vsrl_vx_u8m4(v, 4, vl);
|
|
29
|
+
v = __riscv_vadd_vv_u8m4(v, t, vl);
|
|
30
|
+
return __riscv_vand_vx_u8m4(v, 0x0F, vl);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Shared body for bitwise_{and,xor}_dot_product. @p combine applies the
|
|
34
|
+
// per-element bit op (AND or XOR) between the data and query bit-planes; the
|
|
35
|
+
// popcount of the result for query bit-plane j is weighted by 2^j.
|
|
36
|
+
template <typename Op>
|
|
37
|
+
static inline uint64_t bitwise_dot_product_rvv(
|
|
38
|
+
const uint8_t* query,
|
|
39
|
+
const uint8_t* data,
|
|
40
|
+
size_t size,
|
|
41
|
+
size_t qb,
|
|
42
|
+
Op combine) {
|
|
43
|
+
size_t vlmax = __riscv_vsetvlmax_e16m8();
|
|
44
|
+
vuint16m8_t acc = __riscv_vmv_v_x_u16m8(0, vlmax);
|
|
45
|
+
size_t i = 0;
|
|
46
|
+
while (i < size) {
|
|
47
|
+
size_t vl = __riscv_vsetvl_e8m4(size - i);
|
|
48
|
+
vuint8m4_t vx = __riscv_vle8_v_u8m4(data + i, vl);
|
|
49
|
+
for (size_t j = 0; j < qb; j++) {
|
|
50
|
+
vuint8m4_t vq = __riscv_vle8_v_u8m4(query + j * size + i, vl);
|
|
51
|
+
vuint8m4_t vp = popcount_u8m4(combine(vx, vq, vl), vl);
|
|
52
|
+
vuint16m8_t vw = __riscv_vzext_vf2_u16m8(vp, vl);
|
|
53
|
+
vw = __riscv_vsll_vx_u16m8(vw, j, vl);
|
|
54
|
+
acc = __riscv_vadd_vv_u16m8_tu(acc, acc, vw, vl);
|
|
55
|
+
}
|
|
56
|
+
i += vl;
|
|
57
|
+
}
|
|
58
|
+
vuint32m1_t red = __riscv_vmv_v_x_u32m1(0, 1);
|
|
59
|
+
red = __riscv_vwredsumu_vs_u16m8_u32m1(acc, red, vlmax);
|
|
60
|
+
return __riscv_vmv_x_s_u32m1_u32(red);
|
|
61
|
+
}
|
|
62
|
+
|
|
14
63
|
template <>
|
|
15
64
|
uint64_t bitwise_and_dot_product<SIMDLevel::RISCV_RVV>(
|
|
16
65
|
const uint8_t* query,
|
|
17
66
|
const uint8_t* data,
|
|
18
67
|
size_t size,
|
|
19
68
|
size_t qb) {
|
|
20
|
-
return
|
|
69
|
+
return bitwise_dot_product_rvv(
|
|
70
|
+
query, data, size, qb, [](vuint8m4_t a, vuint8m4_t b, size_t vl) {
|
|
71
|
+
return __riscv_vand_vv_u8m4(a, b, vl);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
template <>
|
|
76
|
+
BitwiseAndDotProductResult bitwise_and_dot_product_with_popcount<
|
|
77
|
+
SIMDLevel::RISCV_RVV>(
|
|
78
|
+
const uint8_t* query,
|
|
79
|
+
const uint8_t* data,
|
|
80
|
+
size_t size,
|
|
81
|
+
size_t qb) {
|
|
82
|
+
// Fused single pass over @p data: reuse each loaded data group for both the
|
|
83
|
+
// doc-side popcount and the qb AND-dot bit-planes, mirroring the separate
|
|
84
|
+
// popcount<RVV> and bitwise_and_dot_product<RVV> kernels above.
|
|
85
|
+
size_t vlmax = __riscv_vsetvlmax_e16m8();
|
|
86
|
+
vuint16m8_t dot_acc = __riscv_vmv_v_x_u16m8(0, vlmax);
|
|
87
|
+
vuint16m8_t pop_acc = __riscv_vmv_v_x_u16m8(0, vlmax);
|
|
88
|
+
size_t i = 0;
|
|
89
|
+
while (i < size) {
|
|
90
|
+
size_t vl = __riscv_vsetvl_e8m4(size - i);
|
|
91
|
+
vuint8m4_t vx = __riscv_vle8_v_u8m4(data + i, vl);
|
|
92
|
+
vuint16m8_t vxp = __riscv_vzext_vf2_u16m8(popcount_u8m4(vx, vl), vl);
|
|
93
|
+
pop_acc = __riscv_vadd_vv_u16m8_tu(pop_acc, pop_acc, vxp, vl);
|
|
94
|
+
for (size_t j = 0; j < qb; j++) {
|
|
95
|
+
vuint8m4_t vq = __riscv_vle8_v_u8m4(query + j * size + i, vl);
|
|
96
|
+
vuint8m4_t vp = popcount_u8m4(__riscv_vand_vv_u8m4(vx, vq, vl), vl);
|
|
97
|
+
vuint16m8_t vw = __riscv_vzext_vf2_u16m8(vp, vl);
|
|
98
|
+
vw = __riscv_vsll_vx_u16m8(vw, j, vl);
|
|
99
|
+
dot_acc = __riscv_vadd_vv_u16m8_tu(dot_acc, dot_acc, vw, vl);
|
|
100
|
+
}
|
|
101
|
+
i += vl;
|
|
102
|
+
}
|
|
103
|
+
vuint32m1_t dot_red = __riscv_vmv_v_x_u32m1(0, 1);
|
|
104
|
+
dot_red = __riscv_vwredsumu_vs_u16m8_u32m1(dot_acc, dot_red, vlmax);
|
|
105
|
+
vuint32m1_t pop_red = __riscv_vmv_v_x_u32m1(0, 1);
|
|
106
|
+
pop_red = __riscv_vwredsumu_vs_u16m8_u32m1(pop_acc, pop_red, vlmax);
|
|
107
|
+
return {__riscv_vmv_x_s_u32m1_u32(dot_red),
|
|
108
|
+
__riscv_vmv_x_s_u32m1_u32(pop_red)};
|
|
21
109
|
}
|
|
22
110
|
|
|
23
111
|
template <>
|
|
@@ -26,28 +114,77 @@ uint64_t bitwise_xor_dot_product<SIMDLevel::RISCV_RVV>(
|
|
|
26
114
|
const uint8_t* data,
|
|
27
115
|
size_t size,
|
|
28
116
|
size_t qb) {
|
|
29
|
-
return
|
|
117
|
+
return bitwise_dot_product_rvv(
|
|
118
|
+
query, data, size, qb, [](vuint8m4_t a, vuint8m4_t b, size_t vl) {
|
|
119
|
+
return __riscv_vxor_vv_u8m4(a, b, vl);
|
|
120
|
+
});
|
|
30
121
|
}
|
|
31
122
|
|
|
32
123
|
template <>
|
|
33
124
|
uint64_t popcount<SIMDLevel::RISCV_RVV>(const uint8_t* data, size_t size) {
|
|
34
|
-
|
|
125
|
+
size_t vlmax = __riscv_vsetvlmax_e16m8();
|
|
126
|
+
vuint16m8_t acc = __riscv_vmv_v_x_u16m8(0, vlmax);
|
|
127
|
+
size_t i = 0;
|
|
128
|
+
while (i < size) {
|
|
129
|
+
size_t vl = __riscv_vsetvl_e8m4(size - i);
|
|
130
|
+
vuint8m4_t v = popcount_u8m4(__riscv_vle8_v_u8m4(data + i, vl), vl);
|
|
131
|
+
vuint16m8_t vw = __riscv_vzext_vf2_u16m8(v, vl);
|
|
132
|
+
acc = __riscv_vadd_vv_u16m8_tu(acc, acc, vw, vl);
|
|
133
|
+
i += vl;
|
|
134
|
+
}
|
|
135
|
+
vuint32m1_t red = __riscv_vmv_v_x_u32m1(0, 1);
|
|
136
|
+
red = __riscv_vwredsumu_vs_u16m8_u32m1(acc, red, vlmax);
|
|
137
|
+
return __riscv_vmv_x_s_u32m1_u32(red);
|
|
35
138
|
}
|
|
36
139
|
|
|
37
140
|
} // namespace faiss::rabitq
|
|
38
141
|
|
|
39
142
|
namespace faiss::rabitq::multibit {
|
|
40
143
|
|
|
144
|
+
static float ip_1exbit_rvv(
|
|
145
|
+
const uint8_t* __restrict sign_bits,
|
|
146
|
+
const uint8_t* __restrict ex_code,
|
|
147
|
+
const float* __restrict rotated_q,
|
|
148
|
+
size_t d,
|
|
149
|
+
float cb) {
|
|
150
|
+
size_t vlmax = __riscv_vsetvlmax_e32m8();
|
|
151
|
+
vfloat32m8_t acc = __riscv_vfmv_v_f_f32m8(0.0f, vlmax);
|
|
152
|
+
size_t i = 0;
|
|
153
|
+
while (i < d) {
|
|
154
|
+
size_t vl = __riscv_vsetvl_e32m8(d - i);
|
|
155
|
+
vbool4_t sb = __riscv_vlm_v_b4(sign_bits + i / 8, vl);
|
|
156
|
+
vbool4_t eb = __riscv_vlm_v_b4(ex_code + i / 8, vl);
|
|
157
|
+
vfloat32m8_t recon = __riscv_vfmv_v_f_f32m8(cb, vl);
|
|
158
|
+
recon = __riscv_vfadd_vf_f32m8_mu(sb, recon, recon, 2.0f, vl);
|
|
159
|
+
recon = __riscv_vfadd_vf_f32m8_mu(eb, recon, recon, 1.0f, vl);
|
|
160
|
+
vfloat32m8_t rq = __riscv_vle32_v_f32m8(rotated_q + i, vl);
|
|
161
|
+
acc = __riscv_vfmacc_vv_f32m8_tu(acc, rq, recon, vl);
|
|
162
|
+
i += vl;
|
|
163
|
+
}
|
|
164
|
+
vfloat32m1_t sum = __riscv_vfmv_s_f_f32m1(0.0f, 1);
|
|
165
|
+
sum = __riscv_vfredusum_vs_f32m8_f32m1(acc, sum, vlmax);
|
|
166
|
+
return __riscv_vfmv_f_s_f32m1_f32(sum);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// no-tree-vectorize keeps the ex_bits >= 2 tail on the existing scalar
|
|
170
|
+
// ip_scalar without GCC turning its 64-bit memcpy window into a vluxei64 gather
|
|
171
|
+
// at unaligned addresses, which SIGBUSes on strict-align RVV cores (SpacemiT
|
|
172
|
+
// X60).
|
|
41
173
|
template <>
|
|
42
|
-
float
|
|
174
|
+
__attribute__((optimize("no-tree-vectorize", "no-tree-slp-vectorize"))) float
|
|
175
|
+
compute_inner_product<SIMDLevel::RISCV_RVV>(
|
|
43
176
|
const uint8_t* __restrict sign_bits,
|
|
44
177
|
const uint8_t* __restrict ex_code,
|
|
45
178
|
const float* __restrict rotated_q,
|
|
46
179
|
size_t d,
|
|
47
180
|
size_t ex_bits,
|
|
48
181
|
float cb) {
|
|
49
|
-
|
|
50
|
-
|
|
182
|
+
if (ex_bits == 1) {
|
|
183
|
+
return ip_1exbit_rvv(sign_bits, ex_code, rotated_q, d, cb);
|
|
184
|
+
}
|
|
185
|
+
// ex_bits >= 2 needs strided bit-plane extraction (PEXT on x86); RVV has no
|
|
186
|
+
// cheap equivalent without Zvbb, so reuse the scalar kernel.
|
|
187
|
+
return ip_scalar(sign_bits, ex_code, rotated_q, 0, d, ex_bits, cb);
|
|
51
188
|
}
|
|
52
189
|
|
|
53
190
|
} // namespace faiss::rabitq::multibit
|
|
@@ -20,6 +20,10 @@ SIMDLevel SIMDConfig::level = SIMDLevel::NONE;
|
|
|
20
20
|
// Bitmask of supported SIMD levels (1 << SIMDLevel)
|
|
21
21
|
uint64_t SIMDConfig::supported_simd_levels = 0;
|
|
22
22
|
|
|
23
|
+
// Microarchitecture flags (x86). Default false; set by
|
|
24
|
+
// detect_x86_uarch_flags() at load time.
|
|
25
|
+
bool SIMDConfig::avx512_split = false;
|
|
26
|
+
|
|
23
27
|
// ARM SVE runtime detection
|
|
24
28
|
#if defined(__aarch64__) || defined(_M_ARM64)
|
|
25
29
|
|
|
@@ -53,6 +57,43 @@ static bool has_sve() {
|
|
|
53
57
|
}
|
|
54
58
|
#endif
|
|
55
59
|
|
|
60
|
+
// Detect x86 microarchitecture flags used for kernel routing. Uses raw
|
|
61
|
+
// cpuid so it is safe to run on any CPU regardless of compiled SIMD level.
|
|
62
|
+
#if defined(__x86_64__)
|
|
63
|
+
namespace {
|
|
64
|
+
void detect_x86_uarch_flags() {
|
|
65
|
+
unsigned int eax, ebx, ecx, edx;
|
|
66
|
+
|
|
67
|
+
// Vendor string (CPUID.0): "AuthenticAMD" is EBX="Auth", EDX="enti",
|
|
68
|
+
// ECX="cAMD".
|
|
69
|
+
eax = 0;
|
|
70
|
+
ecx = 0;
|
|
71
|
+
asm volatile("cpuid"
|
|
72
|
+
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
|
73
|
+
: "a"(eax), "c"(ecx));
|
|
74
|
+
const bool is_amd =
|
|
75
|
+
ebx == 0x68747541u && edx == 0x69746e65u && ecx == 0x444d4163u;
|
|
76
|
+
|
|
77
|
+
// Family/model (CPUID.1 EAX).
|
|
78
|
+
eax = 1;
|
|
79
|
+
ecx = 0;
|
|
80
|
+
asm volatile("cpuid"
|
|
81
|
+
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
|
82
|
+
: "a"(eax), "c"(ecx));
|
|
83
|
+
const unsigned int base_family = (eax >> 8) & 0xfu;
|
|
84
|
+
const unsigned int display_family =
|
|
85
|
+
base_family + (base_family == 0xfu ? ((eax >> 20) & 0xffu) : 0u);
|
|
86
|
+
// AMD Zen 4 / Zen 4c (Bergamo) is family 0x19 and splits AVX-512.
|
|
87
|
+
// (Zen 5, family 0x1A, has a native 512-bit datapath and is excluded.)
|
|
88
|
+
SIMDConfig::avx512_split = is_amd && display_family == 0x19u;
|
|
89
|
+
}
|
|
90
|
+
} // namespace
|
|
91
|
+
#else
|
|
92
|
+
namespace {
|
|
93
|
+
void detect_x86_uarch_flags() {}
|
|
94
|
+
} // namespace
|
|
95
|
+
#endif
|
|
96
|
+
|
|
56
97
|
#ifdef FAISS_ENABLE_DD
|
|
57
98
|
|
|
58
99
|
// =============================================================================
|
|
@@ -101,6 +142,8 @@ bool SIMDConfig::is_simd_level_available(SIMDLevel l) {
|
|
|
101
142
|
SIMDLevel SIMDConfig::auto_detect_simd_level() {
|
|
102
143
|
SIMDLevel detected_level = SIMDLevel::NONE;
|
|
103
144
|
|
|
145
|
+
detect_x86_uarch_flags();
|
|
146
|
+
|
|
104
147
|
#if defined(__x86_64__) && \
|
|
105
148
|
(defined(COMPILE_SIMD_AVX2) || defined(COMPILE_SIMD_AVX512))
|
|
106
149
|
unsigned int eax, ebx, ecx, edx;
|
|
@@ -264,6 +307,7 @@ bool SIMDConfig::is_simd_level_available(SIMDLevel l) {
|
|
|
264
307
|
}
|
|
265
308
|
|
|
266
309
|
SIMDLevel SIMDConfig::auto_detect_simd_level() {
|
|
310
|
+
detect_x86_uarch_flags();
|
|
267
311
|
// In static mode, return the compiled-in level
|
|
268
312
|
#if defined(COMPILE_SIMD_AVX512_SPR)
|
|
269
313
|
return SIMDLevel::AVX512_SPR;
|
|
@@ -161,8 +161,22 @@ struct FAISS_API SIMDConfig {
|
|
|
161
161
|
/// Returns bitmask of supported SIMD levels (1 << SIMDLevel).
|
|
162
162
|
static uint64_t supported_simd_levels;
|
|
163
163
|
|
|
164
|
+
/// CPU implements AVX-512 by splitting over a 256-bit datapath
|
|
165
|
+
/// (AMD Zen 4 / Zen 4c "Bergamo", family 0x19). On such CPUs 512-bit
|
|
166
|
+
/// ops give no throughput gain, so the fast-scan QBS path prefers the
|
|
167
|
+
/// 256-bit kernel.
|
|
168
|
+
static bool avx512_split;
|
|
169
|
+
|
|
164
170
|
static SIMDLevel auto_detect_simd_level();
|
|
165
171
|
|
|
172
|
+
static constexpr bool has_dynamic_dispatch() {
|
|
173
|
+
#ifdef FAISS_ENABLE_DD
|
|
174
|
+
return true;
|
|
175
|
+
#else
|
|
176
|
+
return false;
|
|
177
|
+
#endif
|
|
178
|
+
}
|
|
179
|
+
|
|
166
180
|
SIMDConfig(const char** faiss_simd_level_env = nullptr);
|
|
167
181
|
|
|
168
182
|
/// Set the SIMD level. Throws FaissException if level is not supported.
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
#include <algorithm>
|
|
31
31
|
#include <set>
|
|
32
32
|
#include <type_traits>
|
|
33
|
+
#include <unordered_set>
|
|
33
34
|
#include <vector>
|
|
34
35
|
|
|
35
36
|
#include <faiss/impl/AuxIndexStructures.h>
|
|
@@ -362,39 +363,20 @@ size_t ranklist_intersection_size(
|
|
|
362
363
|
const int64_t* v2_in) {
|
|
363
364
|
if (k2 > k1)
|
|
364
365
|
return ranklist_intersection_size(k2, v2_in, k1, v1);
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
for (size_t i = 0; i < k2; i++) {
|
|
372
|
-
if (v2[i] != prev) {
|
|
373
|
-
v2[wp++] = prev = v2[i];
|
|
374
|
-
}
|
|
366
|
+
// erase-on-hit avoids double-counting; negatives are padding, not IDs
|
|
367
|
+
std::unordered_set<int64_t> remaining;
|
|
368
|
+
remaining.reserve(k2);
|
|
369
|
+
for (size_t i = 0; i < k2; i++) {
|
|
370
|
+
if (v2_in[i] >= 0) {
|
|
371
|
+
remaining.insert(v2_in[i]);
|
|
375
372
|
}
|
|
376
|
-
k2 = wp;
|
|
377
373
|
}
|
|
378
|
-
const int64_t seen_flag = int64_t{1} << 60;
|
|
379
374
|
size_t count = 0;
|
|
380
375
|
for (size_t i = 0; i < k1; i++) {
|
|
381
|
-
|
|
382
|
-
size_t i0 = 0, i1 = k2;
|
|
383
|
-
while (i0 + 1 < i1) {
|
|
384
|
-
size_t imed = (i1 + i0) / 2;
|
|
385
|
-
int64_t piv = v2[imed] & ~seen_flag;
|
|
386
|
-
if (piv <= q)
|
|
387
|
-
i0 = imed;
|
|
388
|
-
else
|
|
389
|
-
i1 = imed;
|
|
390
|
-
}
|
|
391
|
-
if (v2[i0] == q) {
|
|
376
|
+
if (remaining.erase(v1[i]) != 0) {
|
|
392
377
|
count++;
|
|
393
|
-
v2[i0] |= seen_flag;
|
|
394
378
|
}
|
|
395
379
|
}
|
|
396
|
-
delete[] v2;
|
|
397
|
-
|
|
398
380
|
return count;
|
|
399
381
|
}
|
|
400
382
|
|
|
@@ -462,7 +444,7 @@ uint64_t ivec_checksum(size_t n, const int32_t* assigned) {
|
|
|
462
444
|
uint64_t bvec_checksum(size_t n, const uint8_t* a) {
|
|
463
445
|
uint64_t cs = ivec_checksum(n / 4, (const int32_t*)a);
|
|
464
446
|
for (size_t i = n / 4 * 4; i < n; i++) {
|
|
465
|
-
cs = cs * 65713 + a[
|
|
447
|
+
cs = cs * 65713 + a[i] * 1686049;
|
|
466
448
|
}
|
|
467
449
|
return cs;
|
|
468
450
|
}
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: faiss
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Kane
|
|
@@ -85,6 +85,8 @@ files:
|
|
|
85
85
|
- vendor/faiss/faiss/IndexBinaryHash.h
|
|
86
86
|
- vendor/faiss/faiss/IndexBinaryIVF.cpp
|
|
87
87
|
- vendor/faiss/faiss/IndexBinaryIVF.h
|
|
88
|
+
- vendor/faiss/faiss/IndexEDEN.cpp
|
|
89
|
+
- vendor/faiss/faiss/IndexEDEN.h
|
|
88
90
|
- vendor/faiss/faiss/IndexFastScan.cpp
|
|
89
91
|
- vendor/faiss/faiss/IndexFastScan.h
|
|
90
92
|
- vendor/faiss/faiss/IndexFlat.cpp
|
|
@@ -101,6 +103,8 @@ files:
|
|
|
101
103
|
- vendor/faiss/faiss/IndexIVFAdditiveQuantizer.h
|
|
102
104
|
- vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.cpp
|
|
103
105
|
- vendor/faiss/faiss/IndexIVFAdditiveQuantizerFastScan.h
|
|
106
|
+
- vendor/faiss/faiss/IndexIVFEDEN.cpp
|
|
107
|
+
- vendor/faiss/faiss/IndexIVFEDEN.h
|
|
104
108
|
- vendor/faiss/faiss/IndexIVFFastScan.cpp
|
|
105
109
|
- vendor/faiss/faiss/IndexIVFFastScan.h
|
|
106
110
|
- vendor/faiss/faiss/IndexIVFFlat.cpp
|
|
@@ -238,11 +242,13 @@ files:
|
|
|
238
242
|
- vendor/faiss/faiss/gpu_metal/MetalIndex.h
|
|
239
243
|
- vendor/faiss/faiss/gpu_metal/MetalIndexFlat.h
|
|
240
244
|
- vendor/faiss/faiss/gpu_metal/MetalIndexIVFFlat.h
|
|
245
|
+
- vendor/faiss/faiss/gpu_metal/MetalIndexIVFPQ.h
|
|
241
246
|
- vendor/faiss/faiss/gpu_metal/MetalKernels.h
|
|
242
247
|
- vendor/faiss/faiss/gpu_metal/MetalPythonBridge.h
|
|
243
248
|
- vendor/faiss/faiss/gpu_metal/MetalResources.h
|
|
244
249
|
- vendor/faiss/faiss/gpu_metal/StandardMetalResources.h
|
|
245
250
|
- vendor/faiss/faiss/gpu_metal/impl/MetalIVFFlat.h
|
|
251
|
+
- vendor/faiss/faiss/gpu_metal/impl/MetalIVFPQ.h
|
|
246
252
|
- vendor/faiss/faiss/impl/AdSampling.cpp
|
|
247
253
|
- vendor/faiss/faiss/impl/AdSampling.h
|
|
248
254
|
- vendor/faiss/faiss/impl/AdditiveQuantizer.cpp
|
|
@@ -258,6 +264,7 @@ files:
|
|
|
258
264
|
- vendor/faiss/faiss/impl/CodePackerRaBitQ.cpp
|
|
259
265
|
- vendor/faiss/faiss/impl/CodePackerRaBitQ.h
|
|
260
266
|
- vendor/faiss/faiss/impl/DistanceComputer.h
|
|
267
|
+
- vendor/faiss/faiss/impl/EDENQuantizer.h
|
|
261
268
|
- vendor/faiss/faiss/impl/FaissAssert.h
|
|
262
269
|
- vendor/faiss/faiss/impl/FaissException.cpp
|
|
263
270
|
- vendor/faiss/faiss/impl/FaissException.h
|
|
@@ -356,6 +363,8 @@ files:
|
|
|
356
363
|
- vendor/faiss/faiss/impl/mapped_io.h
|
|
357
364
|
- vendor/faiss/faiss/impl/maybe_owned_vector.h
|
|
358
365
|
- vendor/faiss/faiss/impl/platform_macros.h
|
|
366
|
+
- vendor/faiss/faiss/impl/polysemous_training/avx512.cpp
|
|
367
|
+
- vendor/faiss/faiss/impl/polysemous_training/dispatch.h
|
|
359
368
|
- vendor/faiss/faiss/impl/pq_code_distance/IVFPQScanner_impl.h
|
|
360
369
|
- vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.cpp
|
|
361
370
|
- vendor/faiss/faiss/impl/pq_code_distance/IVFPQ_QueryTables.h
|
|
@@ -373,6 +382,12 @@ files:
|
|
|
373
382
|
- vendor/faiss/faiss/impl/pq_code_distance/rvv.cpp
|
|
374
383
|
- vendor/faiss/faiss/impl/residual_quantizer_encode_steps.cpp
|
|
375
384
|
- vendor/faiss/faiss/impl/residual_quantizer_encode_steps.h
|
|
385
|
+
- vendor/faiss/faiss/impl/result_handler/ResultHandler.cpp
|
|
386
|
+
- vendor/faiss/faiss/impl/result_handler/avx2.cpp
|
|
387
|
+
- vendor/faiss/faiss/impl/result_handler/avx512.cpp
|
|
388
|
+
- vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx2.cpp
|
|
389
|
+
- vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer-avx512.cpp
|
|
390
|
+
- vendor/faiss/faiss/impl/scalar_quantizer/EDENQuantizer.cpp
|
|
376
391
|
- vendor/faiss/faiss/impl/scalar_quantizer/codecs.h
|
|
377
392
|
- vendor/faiss/faiss/impl/scalar_quantizer/distance_computers.h
|
|
378
393
|
- vendor/faiss/faiss/impl/scalar_quantizer/quantizers.h
|