Skip to content
Open
Show file tree
Hide file tree
Changes from 147 commits
Commits
Show all changes
174 commits
Select commit Hold shift + click to select a range
8fd27d6
init SVS uncompressed data support
Jul 3, 2025
c499b93
Merge branch 'facebookresearch:main' into svs-init
Jul 3, 2025
0bd1fdd
initial naive additional of SVS i/o
ahuber21 Jul 21, 2025
6885f30
use Tempfilename
ahuber21 Jul 21, 2025
0215940
Add I/O to example
ahuber21 Jul 21, 2025
d4d1226
revise, add LVQ, and python bindings
Jul 22, 2025
48904f3
on going work
Jul 22, 2025
b4c768a
cleanup after cherry-picking aaron's latest commits
ahuber21 Jul 23, 2025
5cf26a9
First implementation of IndexSVSFlat
ahuber21 Jul 25, 2025
11b44f7
implement first feedback
ahuber21 Jul 29, 2025
9854e82
Merge remote-tracking branch 'origin/main' into svs-io
ahuber21 Jul 29, 2025
0df0771
Fix tests for LVQ4x4
ahuber21 Jul 30, 2025
014960d
add LVQ4x8
ahuber21 Jul 30, 2025
09c0db5
initial set of SVS python tests
ahuber21 Jul 30, 2025
969d595
fix some tests
ahuber21 Jul 30, 2025
9e3c48e
support LVQ/LeanVec runtime quantization level
Jul 31, 2025
a585e9d
Merge pull request #2 from ahuber21/svs-lvq-leanvec-run-params
ahuber21 Jul 31, 2025
7eb6289
Fix LVQ in test_svs.cpp
ahuber21 Jul 31, 2025
6dbb96f
clang-format
ahuber21 Jul 31, 2025
90b15b6
fix impl cleanup in destructor
ahuber21 Jul 31, 2025
38b7eea
continue work on C++ & py tests
ahuber21 Jul 31, 2025
4f36df5
enable SVS LeanVec
Aug 1, 2025
713cc36
Merge pull request #3 from ahuber21/svs-leanvec
ahuber21 Aug 1, 2025
8f16863
I/O support for LeanVec
ahuber21 Aug 1, 2025
034320b
support SVS index factory
Aug 7, 2025
c7c3577
enable clang format
Aug 8, 2025
9ff7b53
Merge pull request #4 from ahuber21/svs-factory
ahuber21 Aug 11, 2025
b2b9819
streaming write to disk
ahuber21 Aug 11, 2025
d31bcb1
change how files are streamed
ahuber21 Aug 12, 2025
483193a
Update SVS version
ahuber21 Aug 13, 2025
caf1f90
Add FAISS_USE_SVS flag
ahuber21 Aug 13, 2025
38ef801
fixup
ahuber21 Aug 13, 2025
42b2208
fix FAISS_USE_SVS
ahuber21 Aug 13, 2025
6873aa3
add LeanVec load test
ahuber21 Aug 13, 2025
b51ce17
add I/O to IndexSVSFlat
ahuber21 Aug 14, 2025
c7fb7df
Refactor I/O functions into svs_io
ahuber21 Aug 14, 2025
42adb07
cleanup includes and fwd decl
ahuber21 Aug 14, 2025
3378077
rename FAISS_USE_SVS -> FAISS_ENABLE_SVS
ahuber21 Aug 14, 2025
363ec05
Swith SVS threading to OpenMP
Aug 15, 2025
250b74f
Merge pull request #5 from ahuber21/svs-omp
ahuber21 Aug 18, 2025
00dd505
fix tests
ahuber21 Aug 18, 2025
4f83fd0
fix avx and sve builds
ahuber21 Aug 19, 2025
d264256
update svs version for omp bug fix
Aug 20, 2025
d7ad33f
Merge pull request #6 from ahuber21/svs-omp-fix
ahuber21 Aug 21, 2025
32d5063
support svs factory format
Aug 21, 2025
0a62dee
Merge pull request #7 from ahuber21/svs-factory-format
ahuber21 Aug 22, 2025
95bf6bd
fix tests after renaming classes
ahuber21 Aug 27, 2025
0542ed7
Merge remote-tracking branch 'origin/main' into svs-io
ahuber21 Aug 27, 2025
021c558
fix typo
ahuber21 Aug 27, 2025
19c9181
cleanup
ahuber21 Aug 27, 2025
ff37171
fixup merge error
ahuber21 Aug 27, 2025
4f5dc9a
support svs remove_ids
Aug 27, 2025
d61d1cb
update ts
Sep 2, 2025
2e19a56
Merge pull request #8 from ahuber21/svs-remove-ids
ahuber21 Sep 3, 2025
a28c1ee
support fallback for non-intel hardware
Sep 3, 2025
87e85c4
enable clang format
Sep 3, 2025
b634f6a
Merge pull request #9 from ahuber21/svs-fallback
ahuber21 Sep 4, 2025
da72c1a
svs factory format update
Sep 4, 2025
fd52aa1
Merge pull request #10 from ahuber21/svs-factory-format-update
ahuber21 Sep 5, 2025
26023b0
Add Float16 and SQ I8 support to `IndexSVSVamana` class
rfsaliev Sep 5, 2025
741d0ed
delete accidentally added file
ahuber21 Sep 9, 2025
4da3db8
Merge pull request #13 from ahuber21/chore/rm-file
ahuber21 Sep 10, 2025
53bd413
Merge pull request #12 from ahuber21/rfsaliev/fp16-sq
ahuber21 Sep 17, 2025
7a7931c
fix(svs-io): Don't rely on EOF when loading SVS indices
ahuber21 Sep 19, 2025
9e05e00
Merge pull request #21 from ahuber21/dev/ahuber/improve-io
ahuber21 Sep 19, 2025
d7009fc
chore(test-svs): remove need for temp files
ahuber21 Sep 19, 2025
d5ccad6
chore(test-svs): remove need for temp files
ahuber21 Sep 19, 2025
8cb7a7e
chore(test-svs): skip tests if compiled without SVS
ahuber21 Sep 19, 2025
40dc90d
Merge pull request #23 from ahuber21/dev/ahuber/skip-svs-if-not-compiled
ahuber21 Sep 19, 2025
c45d09a
[SVS] Add support for IDSelecttor and range_search()
rfsaliev Sep 11, 2025
278e9ba
Fix distance comparison in
rfsaliev Sep 15, 2025
734e5f3
Define SearchParametersSVSVamana
rfsaliev Sep 15, 2025
baa42c9
Add python tests
rfsaliev Sep 16, 2025
38fe2ea
Fix iterator batch size in range_search()
rfsaliev Sep 17, 2025
dce50d9
Parallelize batch iterators
rfsaliev Sep 17, 2025
c74b659
Code review fixes and range search refactoring
rfsaliev Sep 23, 2025
21f8bf4
Code review s1e2
rfsaliev Sep 23, 2025
2a8bac7
basic testing idselector & range_search (#24)
ahuber21 Sep 25, 2025
421e582
Fix-update CPP SVS tests
rfsaliev Sep 26, 2025
009e135
Merge pull request #17 from ahuber21/rfsaliev/filered-search
Sep 29, 2025
1fcbc1e
Merge branch 'facebookresearch:main' into svs-io
Sep 29, 2025
a9e5235
update intel license/copyright
Sep 29, 2025
d7b276f
Merge pull request #27 from ahuber21/svs-license-copyright
Sep 29, 2025
972818c
revise based on comments and enable clang format
Sep 30, 2025
ba0e52a
Merge pull request #28 from ahuber21/svs-revise
Sep 30, 2025
38cc069
refactor
Oct 1, 2025
2469976
Merge pull request #29 from ahuber21/svs-refactor
Oct 1, 2025
96ba302
Merge branch 'facebookresearch:main' into svs-io
Oct 1, 2025
be5560c
Use new SVS Vamana streaming capabilities
rfsaliev Oct 3, 2025
22600e3
Update IndexSVSFlat serialization and remove SVSTempDirectory
rfsaliev Oct 7, 2025
5811cde
update SVS package
Oct 7, 2025
f5fb356
Merge pull request #30 from ahuber21/rfsaliev/save-load-stream
Oct 7, 2025
3ce665a
Merge branch 'facebookresearch:main' into svs-io
Oct 7, 2025
c85c538
enable clang format
Oct 9, 2025
13e3897
clang format for conecpt
Oct 9, 2025
3537df7
Merge pull request #32 from ahuber21/svs-clang-format
Oct 9, 2025
4c3c82e
update submodule to support gcc14
Oct 15, 2025
c14ab71
Merge pull request #33 from ahuber21/svs-update
Oct 15, 2025
6da649f
Merge branch 'main' into svs-io
Oct 15, 2025
b9ef77f
Initial commit for FAISS bindings in SVS
rfsaliev Oct 16, 2025
8c80f6a
Reflect SVS Flat implementation cahnges.
rfsaliev Oct 20, 2025
95e8f66
fix(io): don't read too many bytes from IOReader
ahuber21 Oct 21, 2025
63ba062
Merge pull request #36 from ahuber21/svs-io-fix-buffering
ahuber21 Oct 21, 2025
2dce7f4
fix(svsio): allow writing/reading of non-initialized index
ahuber21 Oct 23, 2025
a5800d4
Merge pull request #38 from ahuber21/svs-io-fix-noninit-serialization
ahuber21 Oct 23, 2025
074f645
Restore SVS integration files but based in the new API.
rfsaliev Oct 24, 2025
01ab8df
fix nulllptr return
ahuber21 Oct 27, 2025
2414431
LVQ nad LeanVec enums redefinition to fix swigfaiss build
rfsaliev Oct 27, 2025
f71cf1e
add test cases for saving/loading uninitialized index & trained index…
ahuber21 Oct 28, 2025
230d202
store leanvec matrix
ahuber21 Oct 28, 2025
27b1b9d
store leanvec matrix
ahuber21 Oct 29, 2025
edbe9cd
update svs release
ahuber21 Oct 29, 2025
b709fa1
Merge pull request #39 from ahuber21/svs-io-fix-noninit-serialization…
ahuber21 Oct 30, 2025
06a1f31
runtime namespace updates
ethanglaser Oct 31, 2025
d4c0557
Update SVS_URL to GH releases bindings tarball
ethanglaser Oct 31, 2025
6539d5e
Merge pull request #40 from ethanglaser/rfsaliev/svs-faiss-bindings
ahuber21 Oct 31, 2025
d6ab3f1
Merge branch 'svs-io' into rfsaliev/svs-faiss-bindings
ahuber21 Oct 31, 2025
3cedda6
fix: is_trained logic and serializing members
ahuber21 Oct 31, 2025
a20d2a7
fixup: remove redundant semicolon
ahuber21 Oct 31, 2025
d895b99
Use training info
ahuber21 Nov 4, 2025
9fdd2f6
updates for new interface version
ahuber21 Nov 6, 2025
6b42374
update flat to new runtime; use v0 api
ahuber21 Nov 7, 2025
e6f2c9a
fix python tests
ahuber21 Nov 7, 2025
29086ae
Remove unused enum
ahuber21 Nov 7, 2025
211832f
rename SVS_RUNTIME_VERSION -> FAISS_SVS_RUNTIME_VERSION
ahuber21 Nov 7, 2025
056cb8c
Merge pull request #41 from ahuber21/ahuber/svs-faiss-bindings
ahuber21 Nov 7, 2025
bef9914
Update svs runtime usage according to latest changes
rfsaliev Nov 7, 2025
0a63ff9
Update library URL
ahuber21 Nov 10, 2025
203760c
Merge pull request #34 from ahuber21/rfsaliev/svs-faiss-bindings
ahuber21 Nov 10, 2025
82ebccf
clean up removed class
ahuber21 Nov 10, 2025
63542b1
update svs defaults
ahuber21 Nov 10, 2025
34b0dfa
inline v0
ahuber21 Nov 10, 2025
e755372
Merge pull request #42 from ahuber21/svs-io-cleanup
ahuber21 Nov 10, 2025
26c404e
Merge remote-tracking branch 'origin/main' into svs-io-pull-main
ahuber21 Nov 10, 2025
3871583
Merge pull request #43 from ahuber21/svs-io-pull-main
ahuber21 Nov 10, 2025
64c6910
set FAISS_SVS_RUNTIME_VERSION as string instead of bool
ethanglaser Nov 10, 2025
6650142
Merge pull request #44 from ethanglaser/eglaser/runtime-version-revision
mihaic Nov 10, 2025
83b39e0
Merge branch 'main' into svs-io
mnorris11 Nov 14, 2025
4abda24
fix test skip if SVS not compiled in
ahuber21 Nov 17, 2025
f715931
Merge pull request #45 from ahuber21/dev/svs-io/fix-test-skip
ahuber21 Nov 17, 2025
268eaca
Merge branch 'facebookresearch:main' into svs-io
ahuber21 Nov 17, 2025
3e25e2b
check supported storage kind in constructor
ahuber21 Nov 17, 2025
0e043e2
add comment explaining behavior
ahuber21 Nov 18, 2025
a184486
formatting fix
ahuber21 Nov 18, 2025
9a0fa75
add tests for lvq/leanvec enabled
ahuber21 Nov 18, 2025
a2f33f2
renamed SQ8 -> SQI8
ahuber21 Nov 18, 2025
e9c76cd
split tests
ahuber21 Nov 18, 2025
462908d
change is_lvq_leanvec_enabled() implementation
ahuber21 Nov 18, 2025
952563d
add portions copyright
ahuber21 Nov 18, 2025
34a411f
missing newline
ahuber21 Nov 18, 2025
7dbdd60
clean up comments
ahuber21 Nov 18, 2025
ea50f11
add_ref_in_constructor for new classes
ahuber21 Nov 18, 2025
7a342f4
cleanup swigfaiss.swig
ahuber21 Nov 18, 2025
faeb765
Merge pull request #47 from ahuber21/dev/svs-io/review-2
ahuber21 Nov 18, 2025
5d5d464
Merge branch 'main' into svs-io
ahuber21 Nov 18, 2025
8c838a4
Apply output buffer converter to FaissResultsAllocator
rfsaliev Nov 19, 2025
bf7c9f2
Merge pull request #46 from ahuber21/dev/svs-io/check-storage-kind
ahuber21 Nov 20, 2025
0cf8c2a
fix double free
ahuber21 Nov 20, 2025
6d5ad77
Merge pull request #48 from ahuber21/dev/svs-io/fix-double-free
ahuber21 Nov 20, 2025
4b6c644
fix errorcode check
ahuber21 Nov 20, 2025
3831e8e
add svs workflows
ahuber21 Nov 20, 2025
33b0cd3
Merge pull request #49 from ahuber21/dev/svs-io/tests-and-ci
ahuber21 Nov 20, 2025
e672cf5
Merge branch 'main' into svs-io
ahuber21 Nov 20, 2025
2af4cf1
update SVS lib
ahuber21 Nov 20, 2025
d81dc00
test fixes
ahuber21 Nov 20, 2025
f82831a
Update SVS_URL to latest binary
ethanglaser Nov 21, 2025
7bf2b62
Merge pull request #50 from ethanglaser/eglaser/svs-binary-update
ahuber21 Nov 21, 2025
2f5bae6
fix no lvq/leanvec test
ahuber21 Nov 21, 2025
d06d2fb
harmonize exception behavior if storage is not supported
ahuber21 Nov 21, 2025
a4edce0
fix leanvec fallback test
ahuber21 Nov 24, 2025
4bbf61e
Merge branch 'main' into svs-io
mnorris11 Nov 24, 2025
2a14910
fix: artifact name with svs enabled
ahuber21 Nov 27, 2025
ca7f66b
add FAISS_ENABLE_SVS
ahuber21 Nov 27, 2025
7346953
copy/install svs runtime if available
ahuber21 Nov 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ option(FAISS_ENABLE_PYTHON "Build Python extension." ON)
option(FAISS_ENABLE_C_API "Build C API." OFF)
option(FAISS_ENABLE_EXTRAS "Build extras like benchmarks and demos" ON)
option(FAISS_USE_LTO "Enable Link-Time optimization" OFF)
option(FAISS_ENABLE_SVS "Enable SVS (Intel(R) Scalable Vector Search) integration." OFF)
set(FAISS_SVS_RUNTIME_VERSION "v0" CACHE STRING "Version of the SVS runtime API to use")
set_property(CACHE FAISS_SVS_RUNTIME_VERSION PROPERTY STRINGS "v0")

if(FAISS_ENABLE_GPU)
if(FAISS_ENABLE_ROCM)
Expand Down
46 changes: 46 additions & 0 deletions faiss/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ set(FAISS_SRC
utils/distances_fused/simdlib_based.cpp
)

if(FAISS_ENABLE_SVS)
list(APPEND FAISS_SRC
svs/IndexSVSFlat.cpp
svs/IndexSVSVamana.cpp
svs/IndexSVSVamanaLVQ.cpp
svs/IndexSVSVamanaLeanVec.cpp
impl/svs_io.cpp
)
endif()

set(FAISS_HEADERS
AutoTune.h
Clustering.h
Expand Down Expand Up @@ -252,6 +262,15 @@ set(FAISS_HEADERS
utils/hamming_distance/avx512-inl.h
)

if(FAISS_ENABLE_SVS)
list(APPEND FAISS_HEADERS
svs/IndexSVSFlat.h
svs/IndexSVSVamana.h
svs/IndexSVSVamanaLVQ.h
svs/IndexSVSVamanaLeanVec.h
)
endif()

if(NOT WIN32)
list(APPEND FAISS_SRC invlists/OnDiskInvertedLists.cpp)
list(APPEND FAISS_HEADERS invlists/OnDiskInvertedLists.h)
Expand Down Expand Up @@ -331,6 +350,25 @@ if(NOT WIN32)
endif()
endif()

if(FAISS_ENABLE_SVS)
include(FetchContent)
set(SVS_URL "https://github.com/intel/ScalableVectorSearch/releases/download/v1.0.0-dev/svs-cpp-runtime-bindings-1.0.0-NIGHTLY-20251107-41.tar.gz")
FetchContent_Declare(
svs
URL "${SVS_URL}"
)
FetchContent_MakeAvailable(svs)
list(APPEND CMAKE_PREFIX_PATH "${svs_SOURCE_DIR}")
find_package(svs_runtime REQUIRED)
#target_compile_options(svs::svs INTERFACE "-DSVS_ENABLE_OMP=1")

target_link_libraries(faiss PUBLIC svs::svs_runtime)
target_link_libraries(faiss_avx2 PUBLIC svs::svs_runtime)
target_link_libraries(faiss_avx512 PUBLIC svs::svs_runtime)
target_link_libraries(faiss_avx512_spr PUBLIC svs::svs_runtime)
target_link_libraries(faiss_sve PUBLIC svs::svs_runtime)
endif()

# Handle `#include <faiss/foo.h>`.
target_include_directories(faiss PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>)
Expand Down Expand Up @@ -360,6 +398,14 @@ if(WIN32)
target_compile_definitions(faiss_sve PRIVATE FAISS_MAIN_LIB)
endif()

if(FAISS_ENABLE_SVS)
target_compile_definitions(faiss PRIVATE FAISS_ENABLE_SVS FAISS_SVS_RUNTIME_VERSION=${FAISS_SVS_RUNTIME_VERSION})
target_compile_definitions(faiss_avx2 PRIVATE FAISS_ENABLE_SVS FAISS_SVS_RUNTIME_VERSION=${FAISS_SVS_RUNTIME_VERSION})
target_compile_definitions(faiss_avx512 PRIVATE FAISS_ENABLE_SVS FAISS_SVS_RUNTIME_VERSION=${FAISS_SVS_RUNTIME_VERSION})
target_compile_definitions(faiss_avx512_spr PRIVATE FAISS_ENABLE_SVS FAISS_SVS_RUNTIME_VERSION=${FAISS_SVS_RUNTIME_VERSION})
target_compile_definitions(faiss_sve PRIVATE FAISS_ENABLE_SVS FAISS_SVS_RUNTIME_VERSION=${FAISS_SVS_RUNTIME_VERSION})
endif()

if(WIN32)
set_target_properties(faiss PROPERTIES LINK_FLAGS "-Wl,--export-all-symbols")
endif()
Expand Down
68 changes: 67 additions & 1 deletion faiss/impl/index_read.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@
#include <faiss/IndexRaBitQFastScan.h>
#include <faiss/IndexRefine.h>
#include <faiss/IndexRowwiseMinMax.h>
#ifdef FAISS_ENABLE_SVS
#include <faiss/impl/svs_io.h>
#include <faiss/svs/IndexSVSFlat.h>
#include <faiss/svs/IndexSVSVamana.h>
#include <faiss/svs/IndexSVSVamanaLVQ.h>
#include <faiss/svs/IndexSVSVamanaLeanVec.h>
#endif
#include <faiss/IndexScalarQuantizer.h>
#include <faiss/MetaIndexes.h>
#include <faiss/VectorTransform.h>
Expand Down Expand Up @@ -1302,7 +1309,66 @@ Index* read_index(IOReader* f, int io_flags) {
READ1(ivrq->qb);
read_InvertedLists(ivrq, f, io_flags);
idx = ivrq;
} else if (h == fourcc("Iwrf")) {
}
#ifdef FAISS_ENABLE_SVS
else if (
h == fourcc("ILVQ") || h == fourcc("ISVL") || h == fourcc("ISVD")) {
IndexSVSVamana* svs;
if (h == fourcc("ILVQ")) {
svs = new IndexSVSVamanaLVQ();
} else if (h == fourcc("ISVL")) {
svs = new IndexSVSVamanaLeanVec();
} else if (h == fourcc("ISVD")) {
svs = new IndexSVSVamana();
}

read_index_header(svs, f);
READ1(svs->graph_max_degree);
READ1(svs->alpha);
READ1(svs->search_window_size);
READ1(svs->search_buffer_capacity);
READ1(svs->construction_window_size);
READ1(svs->max_candidate_pool_size);
READ1(svs->prune_to);
READ1(svs->use_full_search_history);
READ1(svs->storage_kind);
if (h == fourcc("ISVL")) {
READ1(dynamic_cast<IndexSVSVamanaLeanVec*>(svs)->leanvec_d);
}

bool initialized;
READ1(initialized);
if (initialized) {
faiss::svs_io::ReaderStreambuf rbuf(f);
std::istream is(&rbuf);
svs->deserialize_impl(is);
}
if (h == fourcc("ISVL")) {
bool trained;
READ1(trained);
if (trained) {
faiss::svs_io::ReaderStreambuf rbuf(f);
std::istream is(&rbuf);
dynamic_cast<IndexSVSVamanaLeanVec*>(svs)
->deserialize_training_data(is);
}
}
idx = svs;
} else if (h == fourcc("ISVF")) {
IndexSVSFlat* svs = new IndexSVSFlat();
read_index_header(svs, f);

bool initialized;
READ1(initialized);
if (initialized) {
faiss::svs_io::ReaderStreambuf rbuf(f);
std::istream is(&rbuf);
svs->deserialize_impl(is);
idx = svs;
}
}
#endif // FAISS_ENABLE_SVS
else if (h == fourcc("Iwrf")) {
IndexIVFRaBitQFastScan* ivrqfs = new IndexIVFRaBitQFastScan();
read_ivf_header(ivrqfs, f);
read_RaBitQuantizer(&ivrqfs->rabitq, f);
Expand Down
79 changes: 79 additions & 0 deletions faiss/impl/index_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@
#include <faiss/IndexRaBitQFastScan.h>
#include <faiss/IndexRefine.h>
#include <faiss/IndexRowwiseMinMax.h>
#ifdef FAISS_ENABLE_SVS
#include <faiss/impl/svs_io.h>
#include <faiss/svs/IndexSVSFlat.h>
#include <faiss/svs/IndexSVSVamana.h>
#include <faiss/svs/IndexSVSVamanaLVQ.h>
#include <faiss/svs/IndexSVSVamanaLeanVec.h>
#endif
#include <faiss/IndexScalarQuantizer.h>
#include <faiss/MetaIndexes.h>
#include <faiss/VectorTransform.h>
Expand Down Expand Up @@ -934,7 +941,79 @@ void write_index(const Index* idx, IOWriter* f, int io_flags) {
WRITE1(ivrq->by_residual);
WRITE1(ivrq->qb);
write_InvertedLists(ivrq->invlists, f);
}
#ifdef FAISS_ENABLE_SVS
else if (
const IndexSVSVamana* svs =
dynamic_cast<const IndexSVSVamana*>(idx)) {
uint32_t h;
auto* lvq = dynamic_cast<const IndexSVSVamanaLVQ*>(svs);
auto* lean = dynamic_cast<const IndexSVSVamanaLeanVec*>(svs);
if (lvq != nullptr) {
h = fourcc("ILVQ"); // LVQ
} else if (lean != nullptr) {
h = fourcc("ISVL"); // LeanVec
} else {
h = fourcc("ISVD"); // uncompressed
}

WRITE1(h);
write_index_header(svs, f);
WRITE1(svs->graph_max_degree);
WRITE1(svs->alpha);
WRITE1(svs->search_window_size);
WRITE1(svs->search_buffer_capacity);
WRITE1(svs->construction_window_size);
WRITE1(svs->max_candidate_pool_size);
WRITE1(svs->prune_to);
WRITE1(svs->use_full_search_history);
WRITE1(svs->storage_kind);

if (lean != nullptr) {
WRITE1(lean->leanvec_d);
}

bool initialized = (svs->impl != nullptr);
WRITE1(initialized);
if (initialized) {
faiss::BufferedIOWriter bwr(f);
faiss::svs_io::WriterStreambuf wbuf(&bwr);
std::ostream os(&wbuf);
svs->serialize_impl(os);
os.flush();
}

if (lean != nullptr) {
// Store training data info
bool trained = (lean->training_data != nullptr);
WRITE1(trained);
if (trained) {
faiss::BufferedIOWriter bwr(f);
faiss::svs_io::WriterStreambuf wbuf(&bwr);
std::ostream os(&wbuf);
lean->serialize_training_data(os);
os.flush();
}
}
} else if (
const IndexSVSFlat* svs = dynamic_cast<const IndexSVSFlat*>(idx)) {
uint32_t h = fourcc("ISVF");
WRITE1(h);
write_index_header(idx, f);

bool initialized = (svs->impl != nullptr);
WRITE1(initialized);
if (initialized) {
// Wrap SVS I/O and stream to IOWriter
faiss::BufferedIOWriter bwr(f);
faiss::svs_io::WriterStreambuf wbuf(&bwr);
std::ostream os(&wbuf);
svs->serialize_impl(os);
os.flush();
}
}
#endif // FAISS_ENABLE_SVS
else if (
const IndexIVFRaBitQFastScan* ivrqfs =
dynamic_cast<const IndexIVFRaBitQFastScan*>(idx)) {
uint32_t h = fourcc("Iwrf");
Expand Down
85 changes: 85 additions & 0 deletions faiss/impl/svs_io.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Portions Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/*
* Portions Copyright 2025 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about directly implementing the I/O with the Faiss routines?
It seems that the amount of extra code needed to wrap the SVS I/O routines is about as large as just rewriting the I/O.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We plan to provide a cleaner interface for exactly this at a later point. For now, while this is quite some code, it's still a lot simpler than re-implementing SVS I/O entirely. Also, it gives us full flexibility to align with FAISS expectations.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the update, this file now only provides a small utility to convert IOReader/IOWriter objects to std streams, which are now accepted in SVS.

#include <faiss/impl/svs_io.h>

#include <algorithm>
#include <cstdlib>

#include <faiss/impl/FaissAssert.h>

namespace faiss {
namespace svs_io {

WriterStreambuf::WriterStreambuf(IOWriter* w_) : w(w_) {}

WriterStreambuf::~WriterStreambuf() = default;

std::streamsize WriterStreambuf::xsputn(const char* s, std::streamsize n) {
if (n <= 0)
return 0;
size_t wrote = (*w)(s, 1, static_cast<size_t>(n));
return static_cast<std::streamsize>(wrote);
}

int WriterStreambuf::overflow(int ch) {
if (ch == traits_type::eof())
return 0;
char c = static_cast<char>(ch);
size_t wrote = (*w)(&c, 1, 1);
return wrote == 1 ? ch : traits_type::eof();
}

ReaderStreambuf::ReaderStreambuf(IOReader* rr) : r(rr), single_char_buffer(0) {
// Initialize with empty get area
setg(nullptr, nullptr, nullptr);
}

ReaderStreambuf::~ReaderStreambuf() = default;

std::streambuf::int_type ReaderStreambuf::underflow() {
// Called by std::istream for single-character operations (get, peek, etc.)
// when the get area is exhausted. Reads one byte from IOReader.
size_t got = (*r)(&single_char_buffer, 1, 1);
if (got == 0) {
return traits_type::eof();
}

// Configure get area to expose the single buffered character
setg(&single_char_buffer, &single_char_buffer, &single_char_buffer + 1);
return traits_type::to_int_type(single_char_buffer);
}

std::streamsize ReaderStreambuf::xsgetn(char* s, std::streamsize n) {
// Called by std::istream for bulk reads (read, readsome, etc.).
// Forwards directly to IOReader without intermediate buffering to avoid
// advancing IOReader beyond what the stream consumer requested.
if (n <= 0) {
return 0;
}

size_t got = (*r)(s, 1, n);
return static_cast<std::streamsize>(got);
}

} // namespace svs_io
} // namespace faiss
Loading
Loading