faiss 0.5.0 → 0.5.1
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 +5 -0
- data/README.md +2 -0
- data/ext/faiss/index.cpp +8 -0
- data/lib/faiss/version.rb +1 -1
- data/vendor/faiss/faiss/IVFlib.cpp +25 -49
- data/vendor/faiss/faiss/Index.cpp +11 -0
- data/vendor/faiss/faiss/Index.h +24 -1
- data/vendor/faiss/faiss/IndexAdditiveQuantizer.cpp +1 -0
- data/vendor/faiss/faiss/IndexBinaryHNSW.cpp +5 -1
- data/vendor/faiss/faiss/IndexFastScan.cpp +1 -1
- data/vendor/faiss/faiss/IndexFastScan.h +3 -8
- data/vendor/faiss/faiss/IndexFlat.cpp +374 -4
- data/vendor/faiss/faiss/IndexFlat.h +80 -0
- data/vendor/faiss/faiss/IndexHNSW.cpp +90 -1
- data/vendor/faiss/faiss/IndexHNSW.h +57 -1
- data/vendor/faiss/faiss/IndexIVFFlatPanorama.cpp +34 -149
- data/vendor/faiss/faiss/IndexIVFRaBitQ.cpp +86 -2
- data/vendor/faiss/faiss/IndexIVFRaBitQ.h +3 -1
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.cpp +293 -115
- data/vendor/faiss/faiss/IndexIVFRaBitQFastScan.h +52 -16
- data/vendor/faiss/faiss/IndexPQ.cpp +4 -1
- data/vendor/faiss/faiss/IndexPreTransform.cpp +14 -0
- data/vendor/faiss/faiss/IndexPreTransform.h +9 -0
- data/vendor/faiss/faiss/IndexRaBitQ.cpp +96 -16
- data/vendor/faiss/faiss/IndexRaBitQ.h +5 -1
- data/vendor/faiss/faiss/IndexRaBitQFastScan.cpp +238 -93
- data/vendor/faiss/faiss/IndexRaBitQFastScan.h +35 -9
- data/vendor/faiss/faiss/IndexRefine.cpp +49 -0
- data/vendor/faiss/faiss/IndexRefine.h +17 -0
- data/vendor/faiss/faiss/clone_index.cpp +2 -0
- data/vendor/faiss/faiss/gpu/GpuClonerOptions.h +3 -1
- data/vendor/faiss/faiss/gpu/GpuIndexCagra.h +1 -1
- data/vendor/faiss/faiss/gpu/StandardGpuResources.cpp +1 -1
- data/vendor/faiss/faiss/impl/DistanceComputer.h +74 -3
- data/vendor/faiss/faiss/impl/HNSW.cpp +294 -15
- data/vendor/faiss/faiss/impl/HNSW.h +31 -2
- data/vendor/faiss/faiss/impl/IDSelector.h +3 -3
- data/vendor/faiss/faiss/impl/Panorama.cpp +193 -0
- data/vendor/faiss/faiss/impl/Panorama.h +204 -0
- data/vendor/faiss/faiss/impl/RaBitQStats.cpp +29 -0
- data/vendor/faiss/faiss/impl/RaBitQStats.h +56 -0
- data/vendor/faiss/faiss/impl/RaBitQUtils.cpp +54 -6
- data/vendor/faiss/faiss/impl/RaBitQUtils.h +183 -6
- data/vendor/faiss/faiss/impl/RaBitQuantizer.cpp +269 -84
- data/vendor/faiss/faiss/impl/RaBitQuantizer.h +71 -4
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.cpp +362 -0
- data/vendor/faiss/faiss/impl/RaBitQuantizerMultiBit.h +112 -0
- data/vendor/faiss/faiss/impl/ScalarQuantizer.cpp +6 -9
- data/vendor/faiss/faiss/impl/ScalarQuantizer.h +1 -3
- data/vendor/faiss/faiss/impl/index_read.cpp +156 -12
- data/vendor/faiss/faiss/impl/index_write.cpp +142 -19
- data/vendor/faiss/faiss/impl/platform_macros.h +12 -0
- data/vendor/faiss/faiss/impl/svs_io.cpp +86 -0
- data/vendor/faiss/faiss/impl/svs_io.h +67 -0
- data/vendor/faiss/faiss/index_factory.cpp +182 -15
- data/vendor/faiss/faiss/invlists/BlockInvertedLists.h +1 -1
- data/vendor/faiss/faiss/invlists/DirectMap.cpp +1 -1
- data/vendor/faiss/faiss/invlists/InvertedLists.cpp +18 -109
- data/vendor/faiss/faiss/invlists/InvertedLists.h +2 -18
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.cpp +1 -1
- data/vendor/faiss/faiss/invlists/OnDiskInvertedLists.h +1 -1
- data/vendor/faiss/faiss/svs/IndexSVSFaissUtils.h +261 -0
- data/vendor/faiss/faiss/svs/IndexSVSFlat.cpp +117 -0
- data/vendor/faiss/faiss/svs/IndexSVSFlat.h +66 -0
- data/vendor/faiss/faiss/svs/IndexSVSVamana.cpp +245 -0
- data/vendor/faiss/faiss/svs/IndexSVSVamana.h +137 -0
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.cpp +39 -0
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLVQ.h +42 -0
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.cpp +149 -0
- data/vendor/faiss/faiss/svs/IndexSVSVamanaLeanVec.h +58 -0
- data/vendor/faiss/faiss/utils/distances.cpp +0 -3
- data/vendor/faiss/faiss/utils/utils.cpp +4 -0
- metadata +18 -1
|
@@ -48,6 +48,13 @@
|
|
|
48
48
|
#include <faiss/IndexRaBitQFastScan.h>
|
|
49
49
|
#include <faiss/IndexRefine.h>
|
|
50
50
|
#include <faiss/IndexRowwiseMinMax.h>
|
|
51
|
+
#ifdef FAISS_ENABLE_SVS
|
|
52
|
+
#include <faiss/impl/svs_io.h>
|
|
53
|
+
#include <faiss/svs/IndexSVSFlat.h>
|
|
54
|
+
#include <faiss/svs/IndexSVSVamana.h>
|
|
55
|
+
#include <faiss/svs/IndexSVSVamanaLVQ.h>
|
|
56
|
+
#include <faiss/svs/IndexSVSVamanaLeanVec.h>
|
|
57
|
+
#endif
|
|
51
58
|
#include <faiss/IndexScalarQuantizer.h>
|
|
52
59
|
#include <faiss/MetaIndexes.h>
|
|
53
60
|
#include <faiss/VectorTransform.h>
|
|
@@ -607,11 +614,19 @@ ProductQuantizer* read_ProductQuantizer(IOReader* reader) {
|
|
|
607
614
|
return pq;
|
|
608
615
|
}
|
|
609
616
|
|
|
610
|
-
static void read_RaBitQuantizer(
|
|
611
|
-
|
|
617
|
+
static void read_RaBitQuantizer(
|
|
618
|
+
RaBitQuantizer* rabitq,
|
|
619
|
+
IOReader* f,
|
|
620
|
+
bool multi_bit = true) {
|
|
612
621
|
READ1(rabitq->d);
|
|
613
622
|
READ1(rabitq->code_size);
|
|
614
623
|
READ1(rabitq->metric_type);
|
|
624
|
+
|
|
625
|
+
if (multi_bit) {
|
|
626
|
+
READ1(rabitq->nb_bits);
|
|
627
|
+
} else {
|
|
628
|
+
rabitq->nb_bits = 1;
|
|
629
|
+
}
|
|
615
630
|
}
|
|
616
631
|
|
|
617
632
|
void read_direct_map(DirectMap* dm, IOReader* f) {
|
|
@@ -713,6 +728,20 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
713
728
|
if (h == fourcc("null")) {
|
|
714
729
|
// denotes a missing index, useful for some cases
|
|
715
730
|
return nullptr;
|
|
731
|
+
} else if (h == fourcc("IxFP")) {
|
|
732
|
+
int d;
|
|
733
|
+
size_t n_levels, batch_size;
|
|
734
|
+
READ1(d);
|
|
735
|
+
READ1(n_levels);
|
|
736
|
+
READ1(batch_size);
|
|
737
|
+
IndexFlatL2Panorama* idxp =
|
|
738
|
+
new IndexFlatL2Panorama(d, n_levels, batch_size);
|
|
739
|
+
READ1(idxp->ntotal);
|
|
740
|
+
READ1(idxp->is_trained);
|
|
741
|
+
READVECTOR(idxp->codes);
|
|
742
|
+
READVECTOR(idxp->cum_sums);
|
|
743
|
+
idxp->verbose = false;
|
|
744
|
+
idx = idxp;
|
|
716
745
|
} else if (
|
|
717
746
|
h == fourcc("IxFI") || h == fourcc("IxF2") || h == fourcc("IxFl")) {
|
|
718
747
|
IndexFlat* idxf;
|
|
@@ -1097,13 +1126,19 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1097
1126
|
read_index_header(imiq, f);
|
|
1098
1127
|
read_ProductQuantizer(&imiq->pq, f);
|
|
1099
1128
|
idx = imiq;
|
|
1100
|
-
} else if (h == fourcc("IxRF")) {
|
|
1129
|
+
} else if (h == fourcc("IxRF") || h == fourcc("IxRP")) {
|
|
1101
1130
|
IndexRefine* idxrf = new IndexRefine();
|
|
1102
1131
|
read_index_header(idxrf, f);
|
|
1103
1132
|
idxrf->base_index = read_index(f, io_flags);
|
|
1104
1133
|
idxrf->refine_index = read_index(f, io_flags);
|
|
1105
1134
|
READ1(idxrf->k_factor);
|
|
1106
|
-
if (
|
|
1135
|
+
if (h == fourcc("IxRP")) {
|
|
1136
|
+
// then make a RefineFlatPanorama with it
|
|
1137
|
+
IndexRefine* idxrf_old = idxrf;
|
|
1138
|
+
idxrf = new IndexRefinePanorama();
|
|
1139
|
+
*idxrf = *idxrf_old;
|
|
1140
|
+
delete idxrf_old;
|
|
1141
|
+
} else if (dynamic_cast<IndexFlat*>(idxrf->refine_index)) {
|
|
1107
1142
|
// then make a RefineFlat with it
|
|
1108
1143
|
IndexRefine* idxrf_old = idxrf;
|
|
1109
1144
|
idxrf = new IndexRefineFlat();
|
|
@@ -1138,11 +1173,15 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1138
1173
|
idx = idxp;
|
|
1139
1174
|
} else if (
|
|
1140
1175
|
h == fourcc("IHNf") || h == fourcc("IHNp") || h == fourcc("IHNs") ||
|
|
1141
|
-
h == fourcc("IHN2") || h == fourcc("IHNc") || h == fourcc("IHc2")
|
|
1176
|
+
h == fourcc("IHN2") || h == fourcc("IHNc") || h == fourcc("IHc2") ||
|
|
1177
|
+
h == fourcc("IHfP")) {
|
|
1142
1178
|
IndexHNSW* idxhnsw = nullptr;
|
|
1143
1179
|
if (h == fourcc("IHNf")) {
|
|
1144
1180
|
idxhnsw = new IndexHNSWFlat();
|
|
1145
1181
|
}
|
|
1182
|
+
if (h == fourcc("IHfP")) {
|
|
1183
|
+
idxhnsw = new IndexHNSWFlatPanorama();
|
|
1184
|
+
}
|
|
1146
1185
|
if (h == fourcc("IHNp")) {
|
|
1147
1186
|
idxhnsw = new IndexHNSWPQ();
|
|
1148
1187
|
}
|
|
@@ -1159,6 +1198,15 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1159
1198
|
idxhnsw = new IndexHNSWCagra();
|
|
1160
1199
|
}
|
|
1161
1200
|
read_index_header(idxhnsw, f);
|
|
1201
|
+
if (h == fourcc("IHfP")) {
|
|
1202
|
+
auto idx_panorama = dynamic_cast<IndexHNSWFlatPanorama*>(idxhnsw);
|
|
1203
|
+
size_t nlevels;
|
|
1204
|
+
READ1(nlevels);
|
|
1205
|
+
const_cast<size_t&>(idx_panorama->num_panorama_levels) = nlevels;
|
|
1206
|
+
const_cast<size_t&>(idx_panorama->panorama_level_width) =
|
|
1207
|
+
(idx_panorama->d + nlevels - 1) / nlevels;
|
|
1208
|
+
READVECTOR(idx_panorama->cum_sums);
|
|
1209
|
+
}
|
|
1162
1210
|
if (h == fourcc("IHNc") || h == fourcc("IHc2")) {
|
|
1163
1211
|
READ1(idxhnsw->keep_max_size_level0);
|
|
1164
1212
|
auto idx_hnsw_cagra = dynamic_cast<IndexHNSWCagra*>(idxhnsw);
|
|
@@ -1171,6 +1219,7 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1171
1219
|
}
|
|
1172
1220
|
}
|
|
1173
1221
|
read_HNSW(&idxhnsw->hnsw, f);
|
|
1222
|
+
idxhnsw->hnsw.is_panorama = (h == fourcc("IHfP"));
|
|
1174
1223
|
idxhnsw->storage = read_index(f, io_flags);
|
|
1175
1224
|
idxhnsw->own_fields = idxhnsw->storage != nullptr;
|
|
1176
1225
|
if (h == fourcc("IHNp") && !(io_flags & IO_FLAG_PQ_SKIP_SDC_TABLE)) {
|
|
@@ -1266,16 +1315,16 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1266
1315
|
} else if (h == fourcc("Irfs")) {
|
|
1267
1316
|
IndexRaBitQFastScan* idxqfs = new IndexRaBitQFastScan();
|
|
1268
1317
|
read_index_header(idxqfs, f);
|
|
1269
|
-
read_RaBitQuantizer(&idxqfs->rabitq, f);
|
|
1318
|
+
read_RaBitQuantizer(&idxqfs->rabitq, f, true);
|
|
1270
1319
|
READVECTOR(idxqfs->center);
|
|
1271
1320
|
READ1(idxqfs->qb);
|
|
1272
|
-
READVECTOR(idxqfs->
|
|
1321
|
+
READVECTOR(idxqfs->flat_storage);
|
|
1322
|
+
|
|
1273
1323
|
READ1(idxqfs->bbs);
|
|
1274
1324
|
READ1(idxqfs->ntotal2);
|
|
1275
1325
|
READ1(idxqfs->M2);
|
|
1276
1326
|
READ1(idxqfs->code_size);
|
|
1277
1327
|
|
|
1278
|
-
// Need to initialize the FastScan base class fields
|
|
1279
1328
|
const size_t M_fastscan = (idxqfs->d + 3) / 4;
|
|
1280
1329
|
constexpr size_t nbits_fastscan = 4;
|
|
1281
1330
|
idxqfs->M = M_fastscan;
|
|
@@ -1287,22 +1336,115 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1287
1336
|
} else if (h == fourcc("Ixrq")) {
|
|
1288
1337
|
IndexRaBitQ* idxq = new IndexRaBitQ();
|
|
1289
1338
|
read_index_header(idxq, f);
|
|
1290
|
-
read_RaBitQuantizer(&idxq->rabitq, f);
|
|
1339
|
+
read_RaBitQuantizer(&idxq->rabitq, f, false);
|
|
1291
1340
|
READVECTOR(idxq->codes);
|
|
1292
1341
|
READVECTOR(idxq->center);
|
|
1293
1342
|
READ1(idxq->qb);
|
|
1343
|
+
|
|
1344
|
+
// rabitq.nb_bits is already set to 1 by read_RaBitQuantizer
|
|
1345
|
+
idxq->code_size = idxq->rabitq.code_size;
|
|
1346
|
+
idx = idxq;
|
|
1347
|
+
} else if (h == fourcc("Ixrr")) {
|
|
1348
|
+
// Ixrr = multi-bit format (new)
|
|
1349
|
+
IndexRaBitQ* idxq = new IndexRaBitQ();
|
|
1350
|
+
read_index_header(idxq, f);
|
|
1351
|
+
read_RaBitQuantizer(&idxq->rabitq, f, true); // Reads nb_bits from file
|
|
1352
|
+
READVECTOR(idxq->codes);
|
|
1353
|
+
READVECTOR(idxq->center);
|
|
1354
|
+
READ1(idxq->qb);
|
|
1355
|
+
|
|
1294
1356
|
idxq->code_size = idxq->rabitq.code_size;
|
|
1295
1357
|
idx = idxq;
|
|
1296
1358
|
} else if (h == fourcc("Iwrq")) {
|
|
1297
1359
|
IndexIVFRaBitQ* ivrq = new IndexIVFRaBitQ();
|
|
1298
1360
|
read_ivf_header(ivrq, f);
|
|
1299
|
-
read_RaBitQuantizer(&ivrq->rabitq, f);
|
|
1361
|
+
read_RaBitQuantizer(&ivrq->rabitq, f, false);
|
|
1362
|
+
READ1(ivrq->code_size);
|
|
1363
|
+
READ1(ivrq->by_residual);
|
|
1364
|
+
READ1(ivrq->qb);
|
|
1365
|
+
|
|
1366
|
+
// rabitq.nb_bits is already set to 1 by read_RaBitQuantizer
|
|
1367
|
+
// Update rabitq to match nb_bits
|
|
1368
|
+
ivrq->rabitq.code_size =
|
|
1369
|
+
ivrq->rabitq.compute_code_size(ivrq->d, ivrq->rabitq.nb_bits);
|
|
1370
|
+
ivrq->code_size = ivrq->rabitq.code_size;
|
|
1371
|
+
read_InvertedLists(ivrq, f, io_flags);
|
|
1372
|
+
idx = ivrq;
|
|
1373
|
+
} else if (h == fourcc("Iwrr")) {
|
|
1374
|
+
// Iwrr = multi-bit format (new)
|
|
1375
|
+
IndexIVFRaBitQ* ivrq = new IndexIVFRaBitQ();
|
|
1376
|
+
read_ivf_header(ivrq, f);
|
|
1377
|
+
read_RaBitQuantizer(&ivrq->rabitq, f, true); // Reads nb_bits from file
|
|
1300
1378
|
READ1(ivrq->code_size);
|
|
1301
1379
|
READ1(ivrq->by_residual);
|
|
1302
1380
|
READ1(ivrq->qb);
|
|
1381
|
+
|
|
1382
|
+
// Update rabitq to match nb_bits
|
|
1383
|
+
ivrq->rabitq.code_size =
|
|
1384
|
+
ivrq->rabitq.compute_code_size(ivrq->d, ivrq->rabitq.nb_bits);
|
|
1385
|
+
ivrq->code_size = ivrq->rabitq.code_size;
|
|
1303
1386
|
read_InvertedLists(ivrq, f, io_flags);
|
|
1304
1387
|
idx = ivrq;
|
|
1305
|
-
}
|
|
1388
|
+
}
|
|
1389
|
+
#ifdef FAISS_ENABLE_SVS
|
|
1390
|
+
else if (
|
|
1391
|
+
h == fourcc("ILVQ") || h == fourcc("ISVL") || h == fourcc("ISVD")) {
|
|
1392
|
+
IndexSVSVamana* svs;
|
|
1393
|
+
if (h == fourcc("ILVQ")) {
|
|
1394
|
+
svs = new IndexSVSVamanaLVQ();
|
|
1395
|
+
} else if (h == fourcc("ISVL")) {
|
|
1396
|
+
svs = new IndexSVSVamanaLeanVec();
|
|
1397
|
+
} else if (h == fourcc("ISVD")) {
|
|
1398
|
+
svs = new IndexSVSVamana();
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
read_index_header(svs, f);
|
|
1402
|
+
READ1(svs->graph_max_degree);
|
|
1403
|
+
READ1(svs->alpha);
|
|
1404
|
+
READ1(svs->search_window_size);
|
|
1405
|
+
READ1(svs->search_buffer_capacity);
|
|
1406
|
+
READ1(svs->construction_window_size);
|
|
1407
|
+
READ1(svs->max_candidate_pool_size);
|
|
1408
|
+
READ1(svs->prune_to);
|
|
1409
|
+
READ1(svs->use_full_search_history);
|
|
1410
|
+
READ1(svs->storage_kind);
|
|
1411
|
+
if (h == fourcc("ISVL")) {
|
|
1412
|
+
READ1(dynamic_cast<IndexSVSVamanaLeanVec*>(svs)->leanvec_d);
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
bool initialized;
|
|
1416
|
+
READ1(initialized);
|
|
1417
|
+
if (initialized) {
|
|
1418
|
+
faiss::svs_io::ReaderStreambuf rbuf(f);
|
|
1419
|
+
std::istream is(&rbuf);
|
|
1420
|
+
svs->deserialize_impl(is);
|
|
1421
|
+
}
|
|
1422
|
+
if (h == fourcc("ISVL")) {
|
|
1423
|
+
bool trained;
|
|
1424
|
+
READ1(trained);
|
|
1425
|
+
if (trained) {
|
|
1426
|
+
faiss::svs_io::ReaderStreambuf rbuf(f);
|
|
1427
|
+
std::istream is(&rbuf);
|
|
1428
|
+
dynamic_cast<IndexSVSVamanaLeanVec*>(svs)
|
|
1429
|
+
->deserialize_training_data(is);
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
idx = svs;
|
|
1433
|
+
} else if (h == fourcc("ISVF")) {
|
|
1434
|
+
IndexSVSFlat* svs = new IndexSVSFlat();
|
|
1435
|
+
read_index_header(svs, f);
|
|
1436
|
+
|
|
1437
|
+
bool initialized;
|
|
1438
|
+
READ1(initialized);
|
|
1439
|
+
if (initialized) {
|
|
1440
|
+
faiss::svs_io::ReaderStreambuf rbuf(f);
|
|
1441
|
+
std::istream is(&rbuf);
|
|
1442
|
+
svs->deserialize_impl(is);
|
|
1443
|
+
idx = svs;
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
#endif // FAISS_ENABLE_SVS
|
|
1447
|
+
else if (h == fourcc("Iwrf")) {
|
|
1306
1448
|
IndexIVFRaBitQFastScan* ivrqfs = new IndexIVFRaBitQFastScan();
|
|
1307
1449
|
read_ivf_header(ivrqfs, f);
|
|
1308
1450
|
read_RaBitQuantizer(&ivrqfs->rabitq, f);
|
|
@@ -1314,7 +1456,7 @@ Index* read_index(IOReader* f, int io_flags) {
|
|
|
1314
1456
|
READ1(ivrqfs->implem);
|
|
1315
1457
|
READ1(ivrqfs->qb);
|
|
1316
1458
|
READ1(ivrqfs->centered);
|
|
1317
|
-
READVECTOR(ivrqfs->
|
|
1459
|
+
READVECTOR(ivrqfs->flat_storage);
|
|
1318
1460
|
|
|
1319
1461
|
// Initialize FastScan base class fields
|
|
1320
1462
|
const size_t M_fastscan = (ivrqfs->d + 3) / 4;
|
|
@@ -1480,6 +1622,7 @@ IndexBinary* read_index_binary(IOReader* f, int io_flags) {
|
|
|
1480
1622
|
IndexBinaryHNSW* idxhnsw = new IndexBinaryHNSW();
|
|
1481
1623
|
read_index_binary_header(idxhnsw, f);
|
|
1482
1624
|
read_HNSW(&idxhnsw->hnsw, f);
|
|
1625
|
+
idxhnsw->hnsw.is_panorama = false;
|
|
1483
1626
|
idxhnsw->storage = read_index_binary(f, io_flags);
|
|
1484
1627
|
idxhnsw->own_fields = true;
|
|
1485
1628
|
idx = idxhnsw;
|
|
@@ -1490,6 +1633,7 @@ IndexBinary* read_index_binary(IOReader* f, int io_flags) {
|
|
|
1490
1633
|
READ1(idxhnsw->base_level_only);
|
|
1491
1634
|
READ1(idxhnsw->num_base_level_search_entrypoints);
|
|
1492
1635
|
read_HNSW(&idxhnsw->hnsw, f);
|
|
1636
|
+
idxhnsw->hnsw.is_panorama = false;
|
|
1493
1637
|
idxhnsw->storage = read_index_binary(f, io_flags);
|
|
1494
1638
|
idxhnsw->own_fields = true;
|
|
1495
1639
|
idx = idxhnsw;
|
|
@@ -46,6 +46,13 @@
|
|
|
46
46
|
#include <faiss/IndexRaBitQFastScan.h>
|
|
47
47
|
#include <faiss/IndexRefine.h>
|
|
48
48
|
#include <faiss/IndexRowwiseMinMax.h>
|
|
49
|
+
#ifdef FAISS_ENABLE_SVS
|
|
50
|
+
#include <faiss/impl/svs_io.h>
|
|
51
|
+
#include <faiss/svs/IndexSVSFlat.h>
|
|
52
|
+
#include <faiss/svs/IndexSVSVamana.h>
|
|
53
|
+
#include <faiss/svs/IndexSVSVamanaLVQ.h>
|
|
54
|
+
#include <faiss/svs/IndexSVSVamanaLeanVec.h>
|
|
55
|
+
#endif
|
|
49
56
|
#include <faiss/IndexScalarQuantizer.h>
|
|
50
57
|
#include <faiss/MetaIndexes.h>
|
|
51
58
|
#include <faiss/VectorTransform.h>
|
|
@@ -396,11 +403,17 @@ static void write_NNDescent(const NNDescent* nnd, IOWriter* f) {
|
|
|
396
403
|
WRITEVECTOR(nnd->final_graph);
|
|
397
404
|
}
|
|
398
405
|
|
|
399
|
-
|
|
400
|
-
|
|
406
|
+
// Write RaBitQuantizer for 1-bit format (backward compatible)
|
|
407
|
+
static void write_RaBitQuantizer(
|
|
408
|
+
const RaBitQuantizer* rabitq,
|
|
409
|
+
IOWriter* f,
|
|
410
|
+
bool multi_bit = true) {
|
|
401
411
|
WRITE1(rabitq->d);
|
|
402
412
|
WRITE1(rabitq->code_size);
|
|
403
413
|
WRITE1(rabitq->metric_type);
|
|
414
|
+
if (multi_bit) {
|
|
415
|
+
WRITE1(rabitq->nb_bits);
|
|
416
|
+
}
|
|
404
417
|
}
|
|
405
418
|
|
|
406
419
|
static void write_direct_map(const DirectMap* dm, IOWriter* f) {
|
|
@@ -432,6 +445,18 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
|
432
445
|
// eg. for a storage component of HNSW that is set to nullptr
|
|
433
446
|
uint32_t h = fourcc("null");
|
|
434
447
|
WRITE1(h);
|
|
448
|
+
} else if (
|
|
449
|
+
const IndexFlatL2Panorama* idxpan =
|
|
450
|
+
dynamic_cast<const IndexFlatL2Panorama*>(idx)) {
|
|
451
|
+
uint32_t h = fourcc("IxFP");
|
|
452
|
+
WRITE1(h);
|
|
453
|
+
WRITE1(idxpan->d);
|
|
454
|
+
WRITE1(idxpan->n_levels);
|
|
455
|
+
WRITE1(idxpan->batch_size);
|
|
456
|
+
WRITE1(idxpan->ntotal);
|
|
457
|
+
WRITE1(idxpan->is_trained);
|
|
458
|
+
WRITEVECTOR(idxpan->codes);
|
|
459
|
+
WRITEVECTOR(idxpan->cum_sums);
|
|
435
460
|
} else if (const IndexFlat* idxf = dynamic_cast<const IndexFlat*>(idx)) {
|
|
436
461
|
uint32_t h =
|
|
437
462
|
fourcc(idxf->metric_type == METRIC_INNER_PRODUCT ? "IxFI"
|
|
@@ -790,7 +815,9 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
|
790
815
|
write_ProductQuantizer(&imiq->pq, f);
|
|
791
816
|
} else if (
|
|
792
817
|
const IndexRefine* idxrf = dynamic_cast<const IndexRefine*>(idx)) {
|
|
793
|
-
|
|
818
|
+
bool is_pano =
|
|
819
|
+
dynamic_cast<const IndexRefinePanorama*>(idxrf) != nullptr;
|
|
820
|
+
uint32_t h = is_pano ? fourcc("IxRP") : fourcc("IxRF");
|
|
794
821
|
WRITE1(h);
|
|
795
822
|
write_index_header(idxrf, f);
|
|
796
823
|
write_index(idxrf->base_index, f);
|
|
@@ -806,15 +833,23 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
|
806
833
|
write_index(idxmap->index, f);
|
|
807
834
|
WRITEVECTOR(idxmap->id_map);
|
|
808
835
|
} else if (const IndexHNSW* idxhnsw = dynamic_cast<const IndexHNSW*>(idx)) {
|
|
809
|
-
uint32_t h = dynamic_cast<const
|
|
810
|
-
|
|
811
|
-
: dynamic_cast<const
|
|
812
|
-
: dynamic_cast<const
|
|
813
|
-
: dynamic_cast<const
|
|
814
|
-
|
|
836
|
+
uint32_t h = dynamic_cast<const IndexHNSWFlatPanorama*>(idx)
|
|
837
|
+
? fourcc("IHfP")
|
|
838
|
+
: dynamic_cast<const IndexHNSWFlat*>(idx) ? fourcc("IHNf")
|
|
839
|
+
: dynamic_cast<const IndexHNSWPQ*>(idx) ? fourcc("IHNp")
|
|
840
|
+
: dynamic_cast<const IndexHNSWSQ*>(idx) ? fourcc("IHNs")
|
|
841
|
+
: dynamic_cast<const IndexHNSW2Level*>(idx) ? fourcc("IHN2")
|
|
842
|
+
: dynamic_cast<const IndexHNSWCagra*>(idx) ? fourcc("IHc2")
|
|
843
|
+
: 0;
|
|
815
844
|
FAISS_THROW_IF_NOT(h != 0);
|
|
816
845
|
WRITE1(h);
|
|
817
846
|
write_index_header(idxhnsw, f);
|
|
847
|
+
if (h == fourcc("IHfP")) {
|
|
848
|
+
auto idx_panorama =
|
|
849
|
+
dynamic_cast<const IndexHNSWFlatPanorama*>(idxhnsw);
|
|
850
|
+
WRITE1(idx_panorama->num_panorama_levels);
|
|
851
|
+
WRITEVECTOR(idx_panorama->cum_sums);
|
|
852
|
+
}
|
|
818
853
|
if (h == fourcc("IHc2")) {
|
|
819
854
|
WRITE1(idxhnsw->keep_max_size_level0);
|
|
820
855
|
auto idx_hnsw_cagra = dynamic_cast<const IndexHNSWCagra*>(idxhnsw);
|
|
@@ -908,7 +943,7 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
|
908
943
|
write_RaBitQuantizer(&idxqfs->rabitq, f);
|
|
909
944
|
WRITEVECTOR(idxqfs->center);
|
|
910
945
|
WRITE1(idxqfs->qb);
|
|
911
|
-
WRITEVECTOR(idxqfs->
|
|
946
|
+
WRITEVECTOR(idxqfs->flat_storage);
|
|
912
947
|
WRITE1(idxqfs->bbs);
|
|
913
948
|
WRITE1(idxqfs->ntotal2);
|
|
914
949
|
WRITE1(idxqfs->M2);
|
|
@@ -916,25 +951,113 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
|
916
951
|
WRITEVECTOR(idxqfs->codes);
|
|
917
952
|
} else if (
|
|
918
953
|
const IndexRaBitQ* idxq = dynamic_cast<const IndexRaBitQ*>(idx)) {
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
954
|
+
// Use different fourcc codes for 1-bit vs multi-bit
|
|
955
|
+
if (idxq->rabitq.nb_bits == 1) {
|
|
956
|
+
uint32_t h = fourcc("Ixrq"); // 1-bit (backward compatible)
|
|
957
|
+
WRITE1(h);
|
|
958
|
+
write_index_header(idx, f);
|
|
959
|
+
write_RaBitQuantizer(&idxq->rabitq, f, false);
|
|
960
|
+
} else {
|
|
961
|
+
uint32_t h = fourcc("Ixrr"); // multi-bit (new format)
|
|
962
|
+
WRITE1(h);
|
|
963
|
+
write_index_header(idx, f);
|
|
964
|
+
write_RaBitQuantizer(&idxq->rabitq, f, true);
|
|
965
|
+
}
|
|
923
966
|
WRITEVECTOR(idxq->codes);
|
|
924
967
|
WRITEVECTOR(idxq->center);
|
|
925
968
|
WRITE1(idxq->qb);
|
|
926
969
|
} else if (
|
|
927
970
|
const IndexIVFRaBitQ* ivrq =
|
|
928
971
|
dynamic_cast<const IndexIVFRaBitQ*>(idx)) {
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
972
|
+
// Use different fourcc codes for 1-bit vs multi-bit
|
|
973
|
+
if (ivrq->rabitq.nb_bits == 1) {
|
|
974
|
+
uint32_t h = fourcc("Iwrq"); // 1-bit (backward compatible)
|
|
975
|
+
WRITE1(h);
|
|
976
|
+
write_ivf_header(ivrq, f);
|
|
977
|
+
write_RaBitQuantizer(&ivrq->rabitq, f, false);
|
|
978
|
+
} else {
|
|
979
|
+
uint32_t h = fourcc("Iwrr"); // multi-bit (new format)
|
|
980
|
+
WRITE1(h);
|
|
981
|
+
write_ivf_header(ivrq, f);
|
|
982
|
+
write_RaBitQuantizer(&ivrq->rabitq, f, true);
|
|
983
|
+
}
|
|
933
984
|
WRITE1(ivrq->code_size);
|
|
934
985
|
WRITE1(ivrq->by_residual);
|
|
935
986
|
WRITE1(ivrq->qb);
|
|
936
987
|
write_InvertedLists(ivrq->invlists, f);
|
|
988
|
+
}
|
|
989
|
+
#ifdef FAISS_ENABLE_SVS
|
|
990
|
+
else if (
|
|
991
|
+
const IndexSVSVamana* svs =
|
|
992
|
+
dynamic_cast<const IndexSVSVamana*>(idx)) {
|
|
993
|
+
uint32_t h;
|
|
994
|
+
auto* lvq = dynamic_cast<const IndexSVSVamanaLVQ*>(svs);
|
|
995
|
+
auto* lean = dynamic_cast<const IndexSVSVamanaLeanVec*>(svs);
|
|
996
|
+
if (lvq != nullptr) {
|
|
997
|
+
h = fourcc("ILVQ"); // LVQ
|
|
998
|
+
} else if (lean != nullptr) {
|
|
999
|
+
h = fourcc("ISVL"); // LeanVec
|
|
1000
|
+
} else {
|
|
1001
|
+
h = fourcc("ISVD"); // uncompressed
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
WRITE1(h);
|
|
1005
|
+
write_index_header(svs, f);
|
|
1006
|
+
WRITE1(svs->graph_max_degree);
|
|
1007
|
+
WRITE1(svs->alpha);
|
|
1008
|
+
WRITE1(svs->search_window_size);
|
|
1009
|
+
WRITE1(svs->search_buffer_capacity);
|
|
1010
|
+
WRITE1(svs->construction_window_size);
|
|
1011
|
+
WRITE1(svs->max_candidate_pool_size);
|
|
1012
|
+
WRITE1(svs->prune_to);
|
|
1013
|
+
WRITE1(svs->use_full_search_history);
|
|
1014
|
+
WRITE1(svs->storage_kind);
|
|
1015
|
+
|
|
1016
|
+
if (lean != nullptr) {
|
|
1017
|
+
WRITE1(lean->leanvec_d);
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
bool initialized = (svs->impl != nullptr);
|
|
1021
|
+
WRITE1(initialized);
|
|
1022
|
+
if (initialized) {
|
|
1023
|
+
faiss::BufferedIOWriter bwr(f);
|
|
1024
|
+
faiss::svs_io::WriterStreambuf wbuf(&bwr);
|
|
1025
|
+
std::ostream os(&wbuf);
|
|
1026
|
+
svs->serialize_impl(os);
|
|
1027
|
+
os.flush();
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
if (lean != nullptr) {
|
|
1031
|
+
// Store training data info
|
|
1032
|
+
bool trained = (lean->training_data != nullptr);
|
|
1033
|
+
WRITE1(trained);
|
|
1034
|
+
if (trained) {
|
|
1035
|
+
faiss::BufferedIOWriter bwr(f);
|
|
1036
|
+
faiss::svs_io::WriterStreambuf wbuf(&bwr);
|
|
1037
|
+
std::ostream os(&wbuf);
|
|
1038
|
+
lean->serialize_training_data(os);
|
|
1039
|
+
os.flush();
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
937
1042
|
} else if (
|
|
1043
|
+
const IndexSVSFlat* svs = dynamic_cast<const IndexSVSFlat*>(idx)) {
|
|
1044
|
+
uint32_t h = fourcc("ISVF");
|
|
1045
|
+
WRITE1(h);
|
|
1046
|
+
write_index_header(idx, f);
|
|
1047
|
+
|
|
1048
|
+
bool initialized = (svs->impl != nullptr);
|
|
1049
|
+
WRITE1(initialized);
|
|
1050
|
+
if (initialized) {
|
|
1051
|
+
// Wrap SVS I/O and stream to IOWriter
|
|
1052
|
+
faiss::BufferedIOWriter bwr(f);
|
|
1053
|
+
faiss::svs_io::WriterStreambuf wbuf(&bwr);
|
|
1054
|
+
std::ostream os(&wbuf);
|
|
1055
|
+
svs->serialize_impl(os);
|
|
1056
|
+
os.flush();
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
#endif // FAISS_ENABLE_SVS
|
|
1060
|
+
else if (
|
|
938
1061
|
const IndexIVFRaBitQFastScan* ivrqfs =
|
|
939
1062
|
dynamic_cast<const IndexIVFRaBitQFastScan*>(idx)) {
|
|
940
1063
|
uint32_t h = fourcc("Iwrf");
|
|
@@ -949,7 +1072,7 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
|
|
|
949
1072
|
WRITE1(ivrqfs->implem);
|
|
950
1073
|
WRITE1(ivrqfs->qb);
|
|
951
1074
|
WRITE1(ivrqfs->centered);
|
|
952
|
-
WRITEVECTOR(ivrqfs->
|
|
1075
|
+
WRITEVECTOR(ivrqfs->flat_storage);
|
|
953
1076
|
write_InvertedLists(ivrqfs->invlists, f);
|
|
954
1077
|
} else {
|
|
955
1078
|
FAISS_THROW_MSG("don't know how to serialize this type of index");
|
|
@@ -107,6 +107,12 @@ inline int __builtin_clzll(uint64_t x) {
|
|
|
107
107
|
|
|
108
108
|
#define FAISS_ALWAYS_INLINE __forceinline
|
|
109
109
|
|
|
110
|
+
// MSVC uses pragma pack instead of __attribute__((packed))
|
|
111
|
+
// Use FAISS_PACK_STRUCTS_BEGIN/END to wrap packed structure definitions
|
|
112
|
+
#define FAISS_PACKED
|
|
113
|
+
#define FAISS_PACK_STRUCTS_BEGIN __pragma(pack(push, 1))
|
|
114
|
+
#define FAISS_PACK_STRUCTS_END __pragma(pack(pop))
|
|
115
|
+
|
|
110
116
|
#else
|
|
111
117
|
/*******************************************************
|
|
112
118
|
* Linux and OSX
|
|
@@ -119,10 +125,16 @@ inline int __builtin_clzll(uint64_t x) {
|
|
|
119
125
|
// windows
|
|
120
126
|
#ifdef SWIG
|
|
121
127
|
#define ALIGNED(x)
|
|
128
|
+
#define FAISS_PACKED
|
|
122
129
|
#else
|
|
123
130
|
#define ALIGNED(x) __attribute__((aligned(x)))
|
|
131
|
+
#define FAISS_PACKED __attribute__((packed))
|
|
124
132
|
#endif
|
|
125
133
|
|
|
134
|
+
// On non-Windows, FAISS_PACKED handles packing, so these are no-ops
|
|
135
|
+
#define FAISS_PACK_STRUCTS_BEGIN
|
|
136
|
+
#define FAISS_PACK_STRUCTS_END
|
|
137
|
+
|
|
126
138
|
#define FAISS_ALWAYS_INLINE __attribute__((always_inline)) inline
|
|
127
139
|
|
|
128
140
|
#endif
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Portions 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
|
+
/*
|
|
9
|
+
* Portions Copyright 2025 Intel Corporation
|
|
10
|
+
*
|
|
11
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
* you may not use this file except in compliance with the License.
|
|
13
|
+
* You may obtain a copy of the License at
|
|
14
|
+
*
|
|
15
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
*
|
|
17
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
* See the License for the specific language governing permissions and
|
|
21
|
+
* limitations under the License.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
#include <faiss/impl/svs_io.h>
|
|
25
|
+
|
|
26
|
+
#include <algorithm>
|
|
27
|
+
#include <cstdlib>
|
|
28
|
+
|
|
29
|
+
#include <faiss/impl/FaissAssert.h>
|
|
30
|
+
|
|
31
|
+
namespace faiss {
|
|
32
|
+
namespace svs_io {
|
|
33
|
+
|
|
34
|
+
WriterStreambuf::WriterStreambuf(IOWriter* w_) : w(w_) {}
|
|
35
|
+
|
|
36
|
+
WriterStreambuf::~WriterStreambuf() = default;
|
|
37
|
+
|
|
38
|
+
std::streamsize WriterStreambuf::xsputn(const char* s, std::streamsize n) {
|
|
39
|
+
if (n <= 0)
|
|
40
|
+
return 0;
|
|
41
|
+
size_t wrote = (*w)(s, 1, static_cast<size_t>(n));
|
|
42
|
+
return static_cast<std::streamsize>(wrote);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
int WriterStreambuf::overflow(int ch) {
|
|
46
|
+
if (ch == traits_type::eof())
|
|
47
|
+
return 0;
|
|
48
|
+
char c = static_cast<char>(ch);
|
|
49
|
+
size_t wrote = (*w)(&c, 1, 1);
|
|
50
|
+
return wrote == 1 ? ch : traits_type::eof();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
ReaderStreambuf::ReaderStreambuf(IOReader* rr) : r(rr), single_char_buffer(0) {
|
|
54
|
+
// Initialize with empty get area
|
|
55
|
+
setg(nullptr, nullptr, nullptr);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
ReaderStreambuf::~ReaderStreambuf() = default;
|
|
59
|
+
|
|
60
|
+
std::streambuf::int_type ReaderStreambuf::underflow() {
|
|
61
|
+
// Called by std::istream for single-character operations (get, peek, etc.)
|
|
62
|
+
// when the get area is exhausted. Reads one byte from IOReader.
|
|
63
|
+
size_t got = (*r)(&single_char_buffer, 1, 1);
|
|
64
|
+
if (got == 0) {
|
|
65
|
+
return traits_type::eof();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Configure get area to expose the single buffered character
|
|
69
|
+
setg(&single_char_buffer, &single_char_buffer, &single_char_buffer + 1);
|
|
70
|
+
return traits_type::to_int_type(single_char_buffer);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
std::streamsize ReaderStreambuf::xsgetn(char* s, std::streamsize n) {
|
|
74
|
+
// Called by std::istream for bulk reads (read, readsome, etc.).
|
|
75
|
+
// Forwards directly to IOReader without intermediate buffering to avoid
|
|
76
|
+
// advancing IOReader beyond what the stream consumer requested.
|
|
77
|
+
if (n <= 0) {
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
size_t got = (*r)(s, 1, n);
|
|
82
|
+
return static_cast<std::streamsize>(got);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
} // namespace svs_io
|
|
86
|
+
} // namespace faiss
|