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
|
@@ -47,6 +47,19 @@ int sgemm_(
|
|
|
47
47
|
float* c,
|
|
48
48
|
FINTEGER* ldc);
|
|
49
49
|
|
|
50
|
+
int sgemv_(
|
|
51
|
+
const char* trans,
|
|
52
|
+
FINTEGER* m,
|
|
53
|
+
FINTEGER* n,
|
|
54
|
+
float* alpha,
|
|
55
|
+
const float* a,
|
|
56
|
+
FINTEGER* lda,
|
|
57
|
+
const float* x,
|
|
58
|
+
FINTEGER* incx,
|
|
59
|
+
float* beta,
|
|
60
|
+
float* y,
|
|
61
|
+
FINTEGER* incy);
|
|
62
|
+
|
|
50
63
|
int dgemm_(
|
|
51
64
|
const char* transa,
|
|
52
65
|
const char* transb,
|
|
@@ -192,6 +205,25 @@ void LinearTransform::apply_noalloc(idx_t n, const float* x, float* xt) const {
|
|
|
192
205
|
|
|
193
206
|
float one = 1;
|
|
194
207
|
FINTEGER nbiti = d_out, ni = static_cast<FINTEGER>(n), di = d_in;
|
|
208
|
+
if (n == 1) {
|
|
209
|
+
FINTEGER onei = 1;
|
|
210
|
+
// Avoid GEMM packing overhead for single-vector transforms. GEMV is
|
|
211
|
+
// mathematically equivalent but may not be bit-exact with GEMM because
|
|
212
|
+
// BLAS implementations can use different accumulation orders.
|
|
213
|
+
sgemv_("Transposed",
|
|
214
|
+
&di,
|
|
215
|
+
&nbiti,
|
|
216
|
+
&one,
|
|
217
|
+
A.data(),
|
|
218
|
+
&di,
|
|
219
|
+
x,
|
|
220
|
+
&onei,
|
|
221
|
+
&c_factor,
|
|
222
|
+
xt,
|
|
223
|
+
&onei);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
195
227
|
sgemm_("Transposed",
|
|
196
228
|
"Not transposed",
|
|
197
229
|
&nbiti,
|
|
@@ -1064,8 +1096,7 @@ ITQTransform::ITQTransform(int din, int dout, bool do_pca_in)
|
|
|
1064
1096
|
}
|
|
1065
1097
|
|
|
1066
1098
|
void ITQTransform::train(idx_t n, const float* x_in) {
|
|
1067
|
-
|
|
1068
|
-
!is_trained, "ITQTransform has already been trained");
|
|
1099
|
+
FAISS_THROW_IF_MSG(is_trained, "ITQTransform has already been trained");
|
|
1069
1100
|
|
|
1070
1101
|
size_t max_train_points = std::max(d_in * max_train_per_dim, 32768);
|
|
1071
1102
|
const float* x =
|
|
@@ -18,10 +18,12 @@
|
|
|
18
18
|
#include <faiss/IndexBinaryFlat.h>
|
|
19
19
|
#include <faiss/IndexBinaryHNSW.h>
|
|
20
20
|
#include <faiss/IndexBinaryIVF.h>
|
|
21
|
+
#include <faiss/IndexEDEN.h>
|
|
21
22
|
#include <faiss/IndexFlat.h>
|
|
22
23
|
#include <faiss/IndexHNSW.h>
|
|
23
24
|
#include <faiss/IndexIVF.h>
|
|
24
25
|
#include <faiss/IndexIVFAdditiveQuantizerFastScan.h>
|
|
26
|
+
#include <faiss/IndexIVFEDEN.h>
|
|
25
27
|
#include <faiss/IndexIVFFlat.h>
|
|
26
28
|
#include <faiss/IndexIVFFlatPanorama.h>
|
|
27
29
|
#include <faiss/IndexIVFPQ.h>
|
|
@@ -77,6 +79,7 @@ VectorTransform* Cloner::clone_VectorTransform(const VectorTransform* vt) {
|
|
|
77
79
|
TRYCLONE(PCAMatrix, vt)
|
|
78
80
|
TRYCLONE(ITQMatrix, vt)
|
|
79
81
|
TRYCLONE(RandomRotationMatrix, vt)
|
|
82
|
+
TRYCLONE(HadamardRotation, vt)
|
|
80
83
|
TRYCLONE(LinearTransform, vt) {
|
|
81
84
|
FAISS_THROW_MSG("clone not supported for this type of VectorTransform");
|
|
82
85
|
}
|
|
@@ -98,6 +101,7 @@ IndexIVF* Cloner::clone_IndexIVF(const IndexIVF* ivf) {
|
|
|
98
101
|
TRYCLONE(IndexIVFResidualQuantizerFastScan, ivf)
|
|
99
102
|
TRYCLONE(IndexIVFPQFastScan, ivf)
|
|
100
103
|
|
|
104
|
+
TRYCLONE(IndexIVFEDEN, ivf)
|
|
101
105
|
TRYCLONE(IndexIVFRaBitQFastScan, ivf)
|
|
102
106
|
TRYCLONE(IndexIVFRaBitQ, ivf)
|
|
103
107
|
|
|
@@ -287,6 +291,7 @@ Index* Cloner::clone_Index(const Index* index) {
|
|
|
287
291
|
TRYCLONE(IndexLattice, index)
|
|
288
292
|
TRYCLONE(IndexRandom, index)
|
|
289
293
|
TRYCLONE(IndexPQFastScan, index)
|
|
294
|
+
TRYCLONE(IndexEDEN, index)
|
|
290
295
|
|
|
291
296
|
TRYCLONE(IndexScalarQuantizer, index)
|
|
292
297
|
TRYCLONE(MultiIndexQuantizer, index)
|
|
@@ -14,8 +14,10 @@
|
|
|
14
14
|
#include <faiss/IndexBinaryFlat.h>
|
|
15
15
|
#include <faiss/IndexBinaryHNSW.h>
|
|
16
16
|
#include <faiss/IndexBinaryIVF.h>
|
|
17
|
+
#include <faiss/IndexEDEN.h>
|
|
17
18
|
#include <faiss/IndexHNSW.h>
|
|
18
19
|
#include <faiss/IndexIDMap.h>
|
|
20
|
+
#include <faiss/IndexIVFEDEN.h>
|
|
19
21
|
#include <faiss/IndexIVFFlat.h>
|
|
20
22
|
#include <faiss/IndexIVFPQFastScan.h>
|
|
21
23
|
#include <faiss/IndexIVFRaBitQ.h>
|
|
@@ -33,11 +35,17 @@ namespace {
|
|
|
33
35
|
const std::map<faiss::ScalarQuantizer::QuantizerType, std::string> sq_types = {
|
|
34
36
|
{faiss::ScalarQuantizer::QT_8bit, "SQ8"},
|
|
35
37
|
{faiss::ScalarQuantizer::QT_4bit, "SQ4"},
|
|
38
|
+
// QT_8bit_uniform and QT_4bit_uniform have no round-trippable
|
|
39
|
+
// index_factory string; the names below are synthetic identifiers used
|
|
40
|
+
// for telemetry logging only.
|
|
41
|
+
{faiss::ScalarQuantizer::QT_8bit_uniform, "SQ8u"},
|
|
42
|
+
{faiss::ScalarQuantizer::QT_4bit_uniform, "SQ4u"},
|
|
36
43
|
{faiss::ScalarQuantizer::QT_6bit, "SQ6"},
|
|
37
44
|
{faiss::ScalarQuantizer::QT_fp16, "SQfp16"},
|
|
38
45
|
{faiss::ScalarQuantizer::QT_bf16, "SQbf16"},
|
|
39
46
|
{faiss::ScalarQuantizer::QT_8bit_direct_signed, "SQ8_direct_signed"},
|
|
40
47
|
{faiss::ScalarQuantizer::QT_8bit_direct, "SQ8_direct"},
|
|
48
|
+
{faiss::ScalarQuantizer::QT_0bit, "SQ0"},
|
|
41
49
|
{faiss::ScalarQuantizer::QT_1bit_tqmse, "SQtqmse1"},
|
|
42
50
|
{faiss::ScalarQuantizer::QT_2bit_tqmse, "SQtqmse2"},
|
|
43
51
|
{faiss::ScalarQuantizer::QT_3bit_tqmse, "SQtqmse3"},
|
|
@@ -65,6 +73,19 @@ int get_hnsw_M(const faiss::IndexBinaryHNSW* index) {
|
|
|
65
73
|
return 0;
|
|
66
74
|
}
|
|
67
75
|
|
|
76
|
+
std::string eden_factory_string(
|
|
77
|
+
const faiss::ScalarQuantizer& sq,
|
|
78
|
+
faiss::EDENScaleType scale_type) {
|
|
79
|
+
std::string result = "EDEN";
|
|
80
|
+
if (sq.bits != 1) {
|
|
81
|
+
result += std::to_string(sq.bits);
|
|
82
|
+
}
|
|
83
|
+
if (scale_type == faiss::EDENScaleType_BIASED) {
|
|
84
|
+
result += "BIASED";
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
68
89
|
} // namespace
|
|
69
90
|
|
|
70
91
|
// Reference for reverse_index_factory:
|
|
@@ -114,8 +135,17 @@ std::string reverse_index_factory(const faiss::Index* index) {
|
|
|
114
135
|
ivf_index)) {
|
|
115
136
|
return prefix + ",PQ" + std::to_string(ivfpqfs_index->pq.M) + "x" +
|
|
116
137
|
std::to_string(ivfpqfs_index->pq.nbits) + "fs";
|
|
117
|
-
} else if (
|
|
118
|
-
|
|
138
|
+
} else if (
|
|
139
|
+
const faiss::IndexIVFRaBitQ* ivfrabitq_index =
|
|
140
|
+
dynamic_cast<const faiss::IndexIVFRaBitQ*>(ivf_index)) {
|
|
141
|
+
size_t nb_bits = ivfrabitq_index->rabitq.nb_bits;
|
|
142
|
+
return prefix + ",RaBitQ" +
|
|
143
|
+
(nb_bits == 1 ? "" : std::to_string(nb_bits));
|
|
144
|
+
} else if (
|
|
145
|
+
const faiss::IndexIVFEDEN* ivf_eden =
|
|
146
|
+
dynamic_cast<const faiss::IndexIVFEDEN*>(ivf_index)) {
|
|
147
|
+
return prefix + "," +
|
|
148
|
+
eden_factory_string(ivf_eden->sq, ivf_eden->scale_type);
|
|
119
149
|
}
|
|
120
150
|
} else if (
|
|
121
151
|
const faiss::IndexPreTransform* pretransform_index =
|
|
@@ -184,12 +214,25 @@ std::string reverse_index_factory(const faiss::Index* index) {
|
|
|
184
214
|
const faiss::IndexScalarQuantizer* sq_index =
|
|
185
215
|
dynamic_cast<const faiss::IndexScalarQuantizer*>(index)) {
|
|
186
216
|
return sq_types.at(sq_index->sq.qtype);
|
|
217
|
+
} else if (
|
|
218
|
+
// IndexIDMap2 inherits IndexIDMap — check subclass first.
|
|
219
|
+
const faiss::IndexIDMap2* idmap2 =
|
|
220
|
+
dynamic_cast<const faiss::IndexIDMap2*>(index)) {
|
|
221
|
+
return std::string("IDMap2,") + reverse_index_factory(idmap2->index);
|
|
187
222
|
} else if (
|
|
188
223
|
const faiss::IndexIDMap* idmap =
|
|
189
224
|
dynamic_cast<const faiss::IndexIDMap*>(index)) {
|
|
190
225
|
return std::string("IDMap,") + reverse_index_factory(idmap->index);
|
|
191
|
-
} else if (
|
|
192
|
-
|
|
226
|
+
} else if (
|
|
227
|
+
const faiss::IndexRaBitQ* rabitq_index =
|
|
228
|
+
dynamic_cast<const faiss::IndexRaBitQ*>(index)) {
|
|
229
|
+
size_t nb_bits = rabitq_index->rabitq.nb_bits;
|
|
230
|
+
return "RaBitQ" +
|
|
231
|
+
(nb_bits == 1 ? std::string() : std::to_string(nb_bits));
|
|
232
|
+
} else if (
|
|
233
|
+
const faiss::IndexEDEN* eden =
|
|
234
|
+
dynamic_cast<const faiss::IndexEDEN*>(index)) {
|
|
235
|
+
return eden_factory_string(eden->sq, eden->scale_type);
|
|
193
236
|
}
|
|
194
237
|
// Avoid runtime error, just return empty string for logging.
|
|
195
238
|
return "";
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
#include <faiss/IndexBinaryFlat.h>
|
|
16
16
|
#include <faiss/IndexFlat.h>
|
|
17
|
-
#if defined
|
|
17
|
+
#if defined(USE_NVIDIA_CUVS) && !defined(FAISS_CUVS_NO_CAGRA)
|
|
18
18
|
#include <faiss/IndexBinaryHNSW.h>
|
|
19
19
|
#include <faiss/IndexHNSW.h>
|
|
20
20
|
#endif
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
#include <faiss/MetaIndexes.h>
|
|
29
29
|
#include <faiss/gpu/GpuIndex.h>
|
|
30
30
|
#include <faiss/gpu/GpuIndexBinaryFlat.h>
|
|
31
|
-
#if defined
|
|
31
|
+
#if defined(USE_NVIDIA_CUVS) && !defined(FAISS_CUVS_NO_CAGRA)
|
|
32
32
|
#include <faiss/gpu/GpuIndexBinaryCagra.h>
|
|
33
33
|
#include <faiss/gpu/GpuIndexCagra.h>
|
|
34
34
|
#endif
|
|
@@ -92,7 +92,7 @@ Index* ToCPUCloner::clone_Index(const Index* index) {
|
|
|
92
92
|
// (inverse op of ToGpuClonerMultiple)
|
|
93
93
|
|
|
94
94
|
}
|
|
95
|
-
#if defined
|
|
95
|
+
#if defined(USE_NVIDIA_CUVS) && !defined(FAISS_CUVS_NO_CAGRA)
|
|
96
96
|
else if (auto icg = dynamic_cast<const GpuIndexCagra*>(index)) {
|
|
97
97
|
IndexHNSWCagra* res = new IndexHNSWCagra();
|
|
98
98
|
if (icg->get_numeric_type() != faiss::NumericType::Float32) {
|
|
@@ -150,8 +150,8 @@ Index* ToGpuCloner::clone_Index(const Index* index) {
|
|
|
150
150
|
GpuIndexFlatConfig config;
|
|
151
151
|
config.device = device;
|
|
152
152
|
config.useFloat16 = true;
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
FAISS_THROW_IF_MSG(
|
|
154
|
+
use_cuvs, "this type of index is not implemented for cuVS");
|
|
155
155
|
GpuIndexFlat* gif = new GpuIndexFlat(
|
|
156
156
|
provider, index->d, index->metric_type, config);
|
|
157
157
|
// transfer data by blocks
|
|
@@ -187,8 +187,8 @@ Index* ToGpuCloner::clone_Index(const Index* index) {
|
|
|
187
187
|
config.device = device;
|
|
188
188
|
config.indicesOptions = indicesOptions;
|
|
189
189
|
config.flatConfig.useFloat16 = useFloat16CoarseQuantizer;
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
config.use_cuvs = use_cuvs;
|
|
191
|
+
config.allowCpuCoarseQuantizer = allowCpuCoarseQuantizer;
|
|
192
192
|
|
|
193
193
|
GpuIndexIVFScalarQuantizer* res = new GpuIndexIVFScalarQuantizer(
|
|
194
194
|
provider,
|
|
@@ -233,7 +233,7 @@ Index* ToGpuCloner::clone_Index(const Index* index) {
|
|
|
233
233
|
|
|
234
234
|
return res;
|
|
235
235
|
}
|
|
236
|
-
#if defined
|
|
236
|
+
#if defined(USE_NVIDIA_CUVS) && !defined(FAISS_CUVS_NO_CAGRA)
|
|
237
237
|
else if (auto icg = dynamic_cast<const faiss::IndexHNSWCagra*>(index)) {
|
|
238
238
|
GpuIndexCagraConfig config;
|
|
239
239
|
config.device = device;
|
|
@@ -533,7 +533,7 @@ faiss::IndexBinary* index_binary_gpu_to_cpu(
|
|
|
533
533
|
ii->copyTo(ret);
|
|
534
534
|
return ret;
|
|
535
535
|
}
|
|
536
|
-
#if defined
|
|
536
|
+
#if defined(USE_NVIDIA_CUVS) && !defined(FAISS_CUVS_NO_CAGRA)
|
|
537
537
|
else if (auto ii = dynamic_cast<const GpuIndexBinaryCagra*>(gpu_index)) {
|
|
538
538
|
IndexBinaryHNSWCagra* ret = new IndexBinaryHNSWCagra();
|
|
539
539
|
ii->copyTo(ret);
|
|
@@ -549,13 +549,13 @@ faiss::IndexBinary* index_binary_cpu_to_gpu(
|
|
|
549
549
|
GpuResourcesProvider* provider,
|
|
550
550
|
int device,
|
|
551
551
|
const faiss::IndexBinary* index,
|
|
552
|
-
const GpuClonerOptions* options) {
|
|
552
|
+
const GpuClonerOptions* /*options*/) {
|
|
553
553
|
if (auto ii = dynamic_cast<const IndexBinaryFlat*>(index)) {
|
|
554
554
|
GpuIndexBinaryFlatConfig config;
|
|
555
555
|
config.device = device;
|
|
556
556
|
return new GpuIndexBinaryFlat(provider, ii, config);
|
|
557
557
|
}
|
|
558
|
-
#if defined
|
|
558
|
+
#if defined(USE_NVIDIA_CUVS) && !defined(FAISS_CUVS_NO_CAGRA)
|
|
559
559
|
else if (
|
|
560
560
|
auto ii = dynamic_cast<const faiss::IndexBinaryHNSWCagra*>(index)) {
|
|
561
561
|
GpuIndexCagraConfig config;
|
|
@@ -177,6 +177,33 @@ class GpuIndex : public faiss::Index {
|
|
|
177
177
|
}
|
|
178
178
|
};
|
|
179
179
|
|
|
180
|
+
virtual void addImplPrecomputed_(
|
|
181
|
+
idx_t n,
|
|
182
|
+
const float* x,
|
|
183
|
+
const idx_t* ids,
|
|
184
|
+
const idx_t* precomputed_idx);
|
|
185
|
+
|
|
186
|
+
virtual void addImplPrecomputed_ex_(
|
|
187
|
+
idx_t n,
|
|
188
|
+
const void* x,
|
|
189
|
+
NumericType numeric_type,
|
|
190
|
+
const idx_t* ids,
|
|
191
|
+
const idx_t* precomputed_idx);
|
|
192
|
+
|
|
193
|
+
/// Handles paged adds if the add set is too large, passes to
|
|
194
|
+
/// addImpl_ to actually perform the add for the current page
|
|
195
|
+
void addPaged_(
|
|
196
|
+
idx_t n,
|
|
197
|
+
const float* x,
|
|
198
|
+
const idx_t* ids,
|
|
199
|
+
const idx_t* precomputed_idx = nullptr);
|
|
200
|
+
void addPaged_ex_(
|
|
201
|
+
idx_t n,
|
|
202
|
+
const void* x,
|
|
203
|
+
NumericType numeric_type,
|
|
204
|
+
const idx_t* ids,
|
|
205
|
+
const idx_t* precomputed_idx = nullptr);
|
|
206
|
+
|
|
180
207
|
/// Overridden to actually perform the search
|
|
181
208
|
/// All data is guaranteed to be resident on our device
|
|
182
209
|
virtual void searchImpl_(
|
|
@@ -209,22 +236,18 @@ class GpuIndex : public faiss::Index {
|
|
|
209
236
|
}
|
|
210
237
|
|
|
211
238
|
private:
|
|
212
|
-
/// Handles paged adds if the add set is too large, passes to
|
|
213
|
-
/// addImpl_ to actually perform the add for the current page
|
|
214
|
-
void addPaged_(idx_t n, const float* x, const idx_t* ids);
|
|
215
|
-
void addPaged_ex_(
|
|
216
|
-
idx_t n,
|
|
217
|
-
const void* x,
|
|
218
|
-
NumericType numeric_type,
|
|
219
|
-
const idx_t* ids);
|
|
220
|
-
|
|
221
239
|
/// Calls addImpl_ for a single page of GPU-resident data
|
|
222
|
-
void addPage_(
|
|
240
|
+
void addPage_(
|
|
241
|
+
idx_t n,
|
|
242
|
+
const float* x,
|
|
243
|
+
const idx_t* ids,
|
|
244
|
+
const idx_t* precomputed_idx = nullptr);
|
|
223
245
|
void addPage_ex_(
|
|
224
246
|
idx_t n,
|
|
225
247
|
const void* x,
|
|
226
248
|
NumericType numeric_type,
|
|
227
|
-
const idx_t* ids
|
|
249
|
+
const idx_t* ids,
|
|
250
|
+
const idx_t* precomputed_idx = nullptr);
|
|
228
251
|
|
|
229
252
|
/// Calls searchImpl_ for a single page of GPU-resident data
|
|
230
253
|
void searchNonPaged_(
|
|
@@ -284,6 +284,46 @@ struct GpuIndexCagra : public GpuIndex {
|
|
|
284
284
|
/// in the index instance
|
|
285
285
|
void copyTo(faiss::IndexHNSWCagra* index) const;
|
|
286
286
|
|
|
287
|
+
/// Train CAGRA using multiple GPUs by sharding the dataset.
|
|
288
|
+
/// Uses cuVS native SNMG (single-node multi-GPU) CAGRA build.
|
|
289
|
+
/// Each device builds one shard in parallel via OpenMP.
|
|
290
|
+
/// Float32 only. After training, call copyTo() to produce a CPU
|
|
291
|
+
/// IndexHNSWCagra with full HNSW upper levels.
|
|
292
|
+
/// The training data pointer must remain valid until copyTo() completes.
|
|
293
|
+
/// stitch_mode: 0=CPU HNSW (Approach C), 1=GPU brute-force (Approach B)
|
|
294
|
+
void trainMultiGpu(
|
|
295
|
+
idx_t n,
|
|
296
|
+
const float* x,
|
|
297
|
+
std::vector<GpuResourcesProvider*>& providers,
|
|
298
|
+
std::vector<int>& devices,
|
|
299
|
+
idx_t stitch_per_shard = 0,
|
|
300
|
+
int stitch_k = 2,
|
|
301
|
+
int stitch_mode = 0);
|
|
302
|
+
|
|
303
|
+
/// Build a unified CAGRA graph using cuVS all_neighbors
|
|
304
|
+
/// (multi-GPU kNN graph construction with overlapping clusters) followed
|
|
305
|
+
/// by cagra::optimize (graph pruning). Produces a single unified graph
|
|
306
|
+
/// without stitching. The training data pointer must remain valid until
|
|
307
|
+
/// copyTo() completes.
|
|
308
|
+
/// build_algo: 0=NN-descent (default), 1=brute-force, 2=IVF-PQ
|
|
309
|
+
/// refinement_rate: IVF-PQ refinement multiplier (only used when
|
|
310
|
+
/// build_algo==2). Higher values trade build time for recall; the cuVS
|
|
311
|
+
/// default is 2.0.
|
|
312
|
+
/// ivfpq_search_batch: cap the IVF-PQ search `max_internal_batch_size` used
|
|
313
|
+
/// during the all_neighbors kNN build (build_algo==2). 0 = cuVS default
|
|
314
|
+
/// (128*1024), which can OOM at 100M; a smaller value (e.g. 8192) bounds
|
|
315
|
+
/// the GPU search workspace with no effect on results (recall-neutral).
|
|
316
|
+
void trainAllNeighbors(
|
|
317
|
+
idx_t n,
|
|
318
|
+
const float* x,
|
|
319
|
+
std::vector<int>& devices,
|
|
320
|
+
int n_clusters = 0,
|
|
321
|
+
int overlap_factor = 0,
|
|
322
|
+
bool multi_gpu_optimize = false,
|
|
323
|
+
int build_algo = 0,
|
|
324
|
+
float refinement_rate = 2.0f,
|
|
325
|
+
int ivfpq_search_batch = 0);
|
|
326
|
+
|
|
287
327
|
void reset() override;
|
|
288
328
|
|
|
289
329
|
std::vector<idx_t> get_knngraph() const;
|
|
@@ -317,6 +357,8 @@ struct GpuIndexCagra : public GpuIndex {
|
|
|
317
357
|
idx_t* labels,
|
|
318
358
|
const SearchParameters* search_params) const override;
|
|
319
359
|
|
|
360
|
+
void copyToMultiGpu_(faiss::IndexHNSWCagra* index) const;
|
|
361
|
+
|
|
320
362
|
/// Our configuration options
|
|
321
363
|
const GpuIndexCagraConfig cagraConfig_;
|
|
322
364
|
|
|
@@ -329,6 +371,11 @@ struct GpuIndexCagra : public GpuIndex {
|
|
|
329
371
|
std::shared_ptr<CuvsCagra<half>>,
|
|
330
372
|
std::shared_ptr<CuvsCagra<int8_t>>>
|
|
331
373
|
index_;
|
|
374
|
+
|
|
375
|
+
/// Multi-GPU state: populated by trainMultiGpu(), used by copyTo()
|
|
376
|
+
std::vector<idx_t> merged_knngraph_;
|
|
377
|
+
idx_t merged_knngraph_degree_ = 0;
|
|
378
|
+
const float* multi_gpu_dataset_ = nullptr;
|
|
332
379
|
};
|
|
333
380
|
|
|
334
381
|
} // namespace gpu
|
|
@@ -98,6 +98,17 @@ class GpuIndexIVF : public GpuIndex, public IndexIVFInterface {
|
|
|
98
98
|
/// debugging purposes.
|
|
99
99
|
virtual std::vector<idx_t> getListIndices(idx_t listId) const;
|
|
100
100
|
|
|
101
|
+
/// Add vectors with precomputed IVF list assignments.
|
|
102
|
+
/// Same naming and argument order as IndexIVF::add_core.
|
|
103
|
+
/// `x`, `xids`, and `precomputed_idx` can be resident on the CPU or any
|
|
104
|
+
/// GPU; copies are performed as needed.
|
|
105
|
+
void add_core(
|
|
106
|
+
idx_t n,
|
|
107
|
+
const float* x,
|
|
108
|
+
const idx_t* xids,
|
|
109
|
+
const idx_t* precomputed_idx,
|
|
110
|
+
void* inverted_list_context = nullptr);
|
|
111
|
+
|
|
101
112
|
void search_preassigned(
|
|
102
113
|
idx_t n,
|
|
103
114
|
const float* x,
|
|
@@ -133,6 +144,12 @@ class GpuIndexIVF : public GpuIndex, public IndexIVFInterface {
|
|
|
133
144
|
/// Called from GpuIndex for add/add_with_ids
|
|
134
145
|
void addImpl_(idx_t n, const float* x, const idx_t* ids) override;
|
|
135
146
|
|
|
147
|
+
void addImplPrecomputed_(
|
|
148
|
+
idx_t n,
|
|
149
|
+
const float* x,
|
|
150
|
+
const idx_t* xids,
|
|
151
|
+
const idx_t* precomputed_idx) override;
|
|
152
|
+
|
|
136
153
|
/// Called from GpuIndex for search
|
|
137
154
|
void searchImpl_(
|
|
138
155
|
idx_t n,
|
|
@@ -93,6 +93,22 @@ class GpuIndexIVFScalarQuantizer : public GpuIndexIVF {
|
|
|
93
93
|
/// Validates index SQ parameters
|
|
94
94
|
void verifySQSettings_() const;
|
|
95
95
|
|
|
96
|
+
/// Whether this index configuration can use cuVS IVF-SQ
|
|
97
|
+
bool shouldUseCuvs_() const;
|
|
98
|
+
|
|
99
|
+
/// Construct the backing IVF implementation
|
|
100
|
+
void setIndex_(
|
|
101
|
+
GpuResources* resources,
|
|
102
|
+
int dim,
|
|
103
|
+
idx_t nlist,
|
|
104
|
+
faiss::MetricType metric,
|
|
105
|
+
float metricArg,
|
|
106
|
+
bool useResidual,
|
|
107
|
+
faiss::ScalarQuantizer* scalarQ,
|
|
108
|
+
bool interleavedLayout,
|
|
109
|
+
IndicesOptions indicesOptions,
|
|
110
|
+
MemorySpace space);
|
|
111
|
+
|
|
96
112
|
/// Called from train to handle SQ residual training
|
|
97
113
|
void trainResiduals_(idx_t n, const float* x);
|
|
98
114
|
|
|
@@ -42,7 +42,7 @@ using namespace faiss::gpu;
|
|
|
42
42
|
int main(int argc, char** argv) {
|
|
43
43
|
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
|
44
44
|
|
|
45
|
-
cudaProfilerStop();
|
|
45
|
+
CUDA_VERIFY(cudaProfilerStop());
|
|
46
46
|
|
|
47
47
|
auto seed = FLAGS_seed != -1 ? FLAGS_seed : time(nullptr);
|
|
48
48
|
printf("using seed %ld\n", seed);
|
|
@@ -31,7 +31,7 @@ DEFINE_bool(reserve_memory, false, "whether or not to pre-reserve memory");
|
|
|
31
31
|
int main(int argc, char** argv) {
|
|
32
32
|
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
|
33
33
|
|
|
34
|
-
cudaProfilerStop();
|
|
34
|
+
CUDA_VERIFY(cudaProfilerStop());
|
|
35
35
|
|
|
36
36
|
int dim = FLAGS_dim;
|
|
37
37
|
int numCentroids = FLAGS_centroids;
|
|
@@ -72,7 +72,7 @@ int main(int argc, char** argv) {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
cudaDeviceSynchronize();
|
|
75
|
+
CUDA_VERIFY(cudaDeviceSynchronize());
|
|
76
76
|
CUDA_VERIFY(cudaProfilerStart());
|
|
77
77
|
|
|
78
78
|
float totalGpuTime = 0.0f;
|