Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Faiss Admin & Architecture Guide

Generated June 2026 from facebookresearch/faiss at eb4c1ea

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is for engineers, architects, and operators who build Faiss from source, embed it in a service, tune it for production, or harden it against untrusted input. It documents Faiss v1.14.2 as a system: its architecture, build configuration, runtime dispatch, persistence format, security posture, and internals — at a depth sufficient for an AI or human to reason about, deploy, or extend the library without consulting other sources.

For the end-user API (how to build and query indexes from Python), see the User Guide. This document does not repeat that material; it links to it.


Table of Contents

  1. Executive Summary
  2. Architecture
  3. Repository Structure
  4. System Requirements
  5. Building from Source
  6. Build Configuration Reference
  7. Runtime SIMD Dispatch
  8. The Index Class Hierarchy
  9. Persistence & I/O
  10. Security
  11. GPU & Accelerator Backends
  12. Operations & Scaling
  13. Performance Tuning
  14. The C API
  15. Code Quality & Conventions
  16. Testing
  17. Potential Improvements & Known Issues
  18. Quick Reference

1. Executive Summary

Faiss is a C++17/C++20 library for similarity search and clustering of dense vectors, with complete SWIG-generated Python bindings and an optional C API. Its single architectural abstraction is the Index: an object that stores vectors and answers nearest-neighbor queries. Everything else — inverted files, product quantization, graph indexes, GPU acceleration, preprocessing transforms — is a concrete Index subclass or a wrapper composing other indexes.

Key architectural facts:

  • Language: C++ core (only hard dependency: a BLAS implementation). Python bindings via SWIG over NumPy. Optional C API.
  • Compute backends: CPU (with runtime SIMD dispatch across AVX2/AVX512/AVX512-SPR/SVE/RVV), NVIDIA GPU (CUDA, optionally via NVIDIA cuVS), AMD GPU (ROCm), and Apple Silicon (Metal, IndexFlat only as of v1.14.2).
  • No daemon, no network surface. Faiss is linked into your process. It is not a server; it has no listening sockets, no authentication, and no built-in access control. Security concerns are about the data you feed it (training vectors, queries) and the index files you deserialize.
  • Persistence: any index serializes to a single file via write_index / read_index, with flags for read-only, memory-mapped, and on-disk loading.
  • Build system: CMake. Distributed as conda packages (faiss-cpu, faiss-gpu, faiss-gpu-cuvs) and, as of v1.14.2, pip wheels.

Note

Because Faiss runs in-process, "deployment" means deciding how your service builds, loads, and queries indexes — and how it isolates that work. There is no Faiss service to operate, monitor, or patch independently of your application.


2. Architecture

Layered view

┌──────────────────────────────────────────────────────────────┐
│  Your application (Python or C++)                              │
├──────────────────────────────────────────────────────────────┤
│  Python API layer  (faiss/python/)                             │
│    __init__.py        – Pythonic method replacements           │
│    class_wrappers.py  – numpy<->C++ argument adaptation        │
│    extra_wrappers.py  – Kmeans, ResultHeap, MapInt64ToInt64    │
│    gpu_wrappers.py    – index_cpu_to_gpu, all-GPU helpers      │
│    loader.py          – runtime SIMD-level library selection   │
│    swigfaiss*.swig    – SWIG interface (generates bindings)    │
├──────────────────────────────────────────────────────────────┤
│  C API (optional, c_api/)  – flat C functions over the C++ API │
├──────────────────────────────────────────────────────────────┤
│  C++ core  (faiss/)                                            │
│    Index (abstract)  ── IndexFlat, IndexIVF*, IndexPQ*,        │
│                          IndexHNSW, IndexNSG, IndexLSH, ...     │
│    IndexBinary (abstract) ── IndexBinaryFlat, ...IVF, ...HNSW  │
│    index_factory()   – string → index pipeline builder         │
│    index_io          – write_index / read_index               │
│    Clustering, VectorTransform, InvertedLists                  │
│    impl/   – algorithm internals (HNSW, PQ, ScalarQuantizer…)  │
│    utils/  – distances, heaps, SIMD kernels, random            │
│    gpu/ gpu_metal/ svs/ – accelerator & 3rd-party backends     │
├──────────────────────────────────────────────────────────────┤
│  BLAS (MKL / OpenBLAS)   +   OpenMP   [ + CUDA / ROCm / Metal ] │
└──────────────────────────────────────────────────────────────┘

The Index abstraction

The entire library hangs off faiss::Index (faiss/Index.h). It is an abstract struct with public data members and virtual methods:

Data members: int d (dimension), idx_t ntotal (count; idx_t = int64_t), bool is_trained, bool verbose, MetricType metric_type, float metric_arg.

Pure virtual (every index must implement): add(n, x), search(n, x, k, distances, labels, params), reset().

Virtual with defaults: train, train_with_queries, add_with_ids, range_search, assign, remove_ids, reconstruct, reconstruct_batch, reconstruct_n, search_and_reconstruct, compute_residual(_n), merge_from, check_compatible_for_merge, and the standalone codec interface (sa_code_size, sa_encode, sa_decode, add_sa_codes).

A newer numeric-type family (train_ex, add_ex, search_ex, add_with_ids_ex) accepts a NumericType (Float32, Float16, UInt8, Int8) so indexes can ingest non-float32 data where supported; the base implementations handle Float32 and throw on the rest.

Note

Search accepts an optional SearchParameters*. Subclasses extend it (e.g. IVFSearchParameters with nprobe, IndexRefineSearchParameters with k_factor) so per-query parameters can be passed without mutating the index — important for thread-safe concurrent search with different settings.

Composition over inheritance

Many capabilities are added by wrapping rather than subclassing the algorithm:

  • IndexPreTransform — applies a VectorTransform (PCA, OPQ rotation, L2 normalization) before delegating to an inner index.
  • IndexRefine / IndexRefineFlat — re-ranks an inner index's top k_factor · k candidates with finer distances.
  • IndexIDMap / IndexIDMap2 — adds custom-ID support (and, for IDMap2, reconstruction by ID) to indexes that lack it.
  • IndexIVF* — composes a coarse quantizer (itself an Index, usually IndexFlatL2) with an encoding (Flat, PQ, ScalarQuantizer, additive quantizers, RaBitQ...).

The index_factory string grammar is exactly a serialization of these compositions: OPQ16_64,IVF1000,PQ16 means "OPQ pre-transform → IVF with 1000 cells → PQ16 encoding."


3. Repository Structure

faiss/                  C++ core library (114 files at top level)
  Index.h / Index.cpp       abstract base + version macros (FAISS_VERSION 1.14.2)
  MetricType.h              MetricType enum, idx_t typedef
  index_factory.{h,cpp}     regex-based string → index builder
  index_io.{h,cpp}          serialization + IO flags + deser. hardening
  IndexFlat, IndexIVF*, IndexPQ*, IndexHNSW, IndexNSG, IndexLSH,
  IndexScalarQuantizer, IndexAdditiveQuantizer*, IndexRaBitQ*,
  IndexRefine, IndexPreTransform, IndexIDMap, IndexBinary*  ...
  impl/                 algorithm internals (HNSW, ProductQuantizer,
                        ScalarQuantizer, AdditiveQuantizer, fast_scan,
                        simdlib, AuxIndexStructures, IDSelector, ...)
  utils/                distances, heaps, partitioning, random, SIMD,
                        hamming_distance, transpose, quantization kernels
  invlists/             InvertedLists storage (RAM, on-disk, capped)
  gpu/                  CUDA/ROCm GPU indexes + StandardGpuResources
  gpu_metal/            Apple Silicon Metal backend (IndexFlat)
  svs/                  Intel Scalable Vector Search integration (optional)
  python/               SWIG bindings + Pythonic wrappers + loader
  cppcontrib/           header-only helpers (sa_decode, etc.)
c_api/                  optional flat C API (c_api/, c_api/gpu, impl, utils)
contrib/                Python helper modules (datasets, evaluation, ondisk,
                        torch_utils, clustering, ivf_tools, rpc, ...)
benchs/                 benchmark scripts (bench_fw framework, IVF, HNSW, ...)
demos/                  example programs (offline_ivf, rocksdb_ivf, ...)
perf_tests/             micro-benchmarks
tutorial/cpp, tutorial/python   getting-started examples
tests/                  C++ (GoogleTest) + Python test suites
conda/                  conda recipes for faiss / faiss-gpu / faiss-gpu-cuvs
cmake/                  CMake helpers + toolchains
CMakeLists.txt, INSTALL.md, Doxyfile, pyproject.toml, pyproject-gpu.toml

Note

The benchs/, demos/, and perf_tests/ scripts use argparse and look like CLI tools to automated scanners, but they are not a supported command-line interface — Faiss has no CLI. They are reproducibility harnesses for the research papers and performance regression checks.


4. System Requirements

Runtime (using a prebuilt package)

Requirement Detail
OS Linux (x86-64, aarch64), macOS (arm64), Windows (x86-64) for faiss-cpu
BLAS Bundled by the conda/pip package (MKL on x86-64, OpenBLAS on ARM)
Python 3.x with NumPy (for the Python bindings)
GPU (optional) NVIDIA CUDA 11.4/12.1 (faiss-gpu), CUDA 13.2 + cuVS 26.06 (faiss-gpu-cuvs) — Linux x86-64 only

Build (from source)

Requirement Detail
Compiler C++20 compiler with OpenMP ≥ 2
BLAS Any; Intel MKL strongly recommended on Intel for performance
CMake Recent version
GPU (optional) nvcc + CUDA toolkit (NVIDIA); AMD ROCm (AMD); libcuvs=26.06 (cuVS)
Python bindings (optional) Python 3, NumPy, SWIG

5. Building from Source

Faiss builds with CMake in the standard configure → build → install flow.

Step 1 — configure

cmake -B build .

Step 2 — build the C++ library

make -C build -j faiss

This produces libfaiss.a (or libfaiss.so with -DBUILD_SHARED_LIBS=ON).

Important

If you build with a non-generic SIMD level, build the corresponding optimized target before swigfaiss, e.g. make -C build -j faiss_avx2 (or faiss_avx512, faiss_avx512_spr). The Python loader selects the matching swigfaiss_* extension at import time (see Runtime SIMD Dispatch).

Step 3 — Python bindings (optional)

make -C build -j swigfaiss
(cd build/faiss/python && python setup.py install)

Step 4 — install C++ library & headers (optional)

make -C build install

Step 5 — test (optional)

# C++ (requires -DBUILD_TESTING=ON at configure time)
make -C build test

# Python
(cd build/faiss/python && python setup.py build)
PYTHONPATH="$(ls -d ./build/faiss/python/build/lib*/)" pytest tests/test_*.py

Tip

Pass -j without a number to use all cores, but on memory-constrained machines pin it (-j4) — Faiss translation units, especially GPU and SIMD kernels, are memory-hungry to compile.


6. Build Configuration Reference

All options are passed to the cmake -B build . invocation as -D<OPTION>=<VALUE>.

General

Option Default Effect
FAISS_ENABLE_GPU ON Build GPU indices.
FAISS_ENABLE_PYTHON ON Build the Python bindings.
FAISS_ENABLE_C_API OFF Build the C API.
BUILD_TESTING — Build the C++ test suite.
BUILD_SHARED_LIBS OFF Build a shared library (libfaiss.so) instead of static.

Optimization

Option Values Effect
CMAKE_BUILD_TYPE Release, ... Release enables -O3-class optimization.
FAISS_OPT_LEVEL x86: generic, avx2, avx512, avx512_spr; aarch64: generic, sve SIMD instruction set to compile for (increasing optimization).
FAISS_USE_LTO ON/OFF (OFF) Link-Time Optimization.

BLAS

Option Effect
BLA_VENDOR=Intel10_64_dyn + MKL_LIBRARIES=/path/to/mkl/libs Use Intel MKL (significantly faster than OpenBLAS on Intel).

GPU

Option Effect
FAISS_ENABLE_CUVS=ON Use NVIDIA cuVS implementations for IVF-Flat, IVF-PQ, and CAGRA. Requires FAISS_ENABLE_GPU=ON.
FAISS_ENABLE_ROCM=ON Build GPU indices for AMD GPUs. Requires FAISS_ENABLE_GPU=ON.
CUDAToolkit_ROOT=/path/to/cuda Hint the CUDA toolkit location.
CMAKE_CUDA_ARCHITECTURES="75;72" Target specific GPU architectures.

Optional integrations

Option Effect
FAISS_ENABLE_SVS=ON Enable Intel Scalable Vector Search (Vamana, LVQ, LeanVec). CMake fetches and builds libsvs_runtime.so, copied into the Python package; for C++ usage put it on your library path.
FAISS_ENABLE_METAL Apple Silicon Metal backend (builds Metal tests when combined with BUILD_TESTING).

Python

Option Effect
Python_EXECUTABLE=/path/to/python Build bindings for a specific Python interpreter.

7. Runtime SIMD Dispatch

A subtle but operationally important behavior: the Python package selects the best CPU-optimized extension at import time, based on the CPU it is running on. This is implemented in faiss/python/loader.py.

The loader determines the supported instruction sets (via NumPy's __cpu_features__, plus an SVE probe on aarch64 Linux), then tries to import the most-optimized matching extension first, falling back down the chain:

swigfaiss_avx512_spr  →  swigfaiss_avx512  →  swigfaiss_avx2  →  swigfaiss_sve  →  swigfaiss (generic)

Two environment variables control this:

Variable Effect
FAISS_OPT_LEVEL If set (e.g. avx2, avx512, avx512_spr, sve), forces that level instead of auto-detecting.
FAISS_DISABLE_CPU_FEATURES A whitespace/comma-separated list of features to remove from the detected set (e.g. disable AVX512 to work around a bad path or a CPU that throttles under AVX512).

Warning

If no matching swigfaiss* extension is present (common in incomplete from-source builds), import fails hard with a detailed message telling you which FAISS_OPT_LEVEL your CPU supports and which target to build (swigfaiss, swigfaiss_avx2, swigfaiss_avx512, swigfaiss_avx512_spr, or swigfaiss_sve). This is No module named 'faiss.swigfaiss' — almost always a build, not a usage, problem.

Note

v1.14.2 also adds dynamic dispatch (DD) for several kernel families (hamming, fast_scan) and a build mode where you select a subset of SIMD levels at dispatch time, plus RVV (RISC-V Vector) support with cross-compilation for riscv64.


8. The Index Class Hierarchy

index_factory.cpp includes every index type it can construct; that include list is the authoritative catalog of the C++ index families:

CPU float indexes

Family Classes Notes
Exact IndexFlat, IndexFlatL2, IndexFlatIP Brute force; supports the widest metric set.
Inverted file IndexIVFFlat, IndexIVFFlatPanorama, IndexIVFPQ, IndexIVFPQR, IndexIVFPQFastScan, IndexIVFScalarQuantizer, IndexIVFSpectralHash, IndexIVFAdditiveQuantizer(FastScan), IndexIVFRaBitQ(FastScan) Coarse quantizer + per-cell encoding. nprobe at search.
Product quantization IndexPQ, IndexPQFastScan Compact codes; FastScan uses SIMD LUTs.
Additive quantization IndexAdditiveQuantizer, IndexAdditiveQuantizerFastScan Residual / Local Search quantizers.
Graph IndexHNSW (Flat/PQ/SQ storage), IndexNSG High recall, no training, higher memory.
Compact / hashing IndexLSH, IndexLattice, IndexRaBitQ, IndexScalarQuantizer, IndexRowwiseMinMax Various compression schemes.
Wrappers IndexPreTransform, IndexRefine/IndexRefineFlat, Index2Layer, IndexIDMap/IndexIDMap2 Compose other indexes.

Binary indexes (Hamming distance over bit vectors): IndexBinaryFlat, IndexBinaryIVF, IndexBinaryHNSW, IndexBinaryHash. Built via index_binary_factory.

Intel SVS (compile-time FAISS_ENABLE_SVS): IndexSVSFlat, IndexSVSIVF, IndexSVSIVFLVQ, IndexSVSIVFLeanVec, IndexSVSVamana, IndexSVSVamanaLVQ, IndexSVSVamanaLeanVec. As of v1.14.2 an SVS Vamana index can also serve as an IVF coarse quantizer via the factory.

Pre-processing transforms

VectorTransform subclasses applied through IndexPreTransform: PCA reduction, OPQ rotation (optimized for PQ), random rotation (RR), and L2 normalization (L2norm, the basis for cosine search).


9. Persistence & I/O

faiss/index_io.h defines the serialization API. Any index round-trips through a single file (or FILE*, or a custom IOReader/IOWriter abstraction).

void write_index(const Index* idx, const char* fname, int io_flags = 0);
Index* read_index(const char* fname, int io_flags = 0);
std::unique_ptr<Index> read_index_up(const char* fname, int io_flags = 0); // owning

Parallel functions exist for binary indexes (write_index_binary/read_index_binary), VectorTransform, ProductQuantizer, and InvertedLists.

I/O flags

Flag Value Effect
IO_FLAG_SKIP_STORAGE 1 Skip the raw storage for graph indexes (graph structure only).
IO_FLAG_READ_ONLY 2 Open read-only; no in-place modification.
IO_FLAG_ONDISK_SAME_DIR 4 Strip the directory from an on-disk inverted-list filename and assume it sits beside the index file.
IO_FLAG_SKIP_IVF_DATA 8 Load list sizes only, not the IVF payload.
IO_FLAG_SKIP_PRECOMPUTE_TABLE 16 Don't rebuild the precomputed table after load.
IO_FLAG_PQ_SKIP_SDC_TABLE 32 Skip the PQ symmetric-distance table (blocks some distance computations; blocks HNSWPQ graph building).
IO_FLAG_MMAP (composite) Memory-map the data (loads ArrayInvertedLists as OnDiskInvertedLists).
IO_FLAG_MMAP_IFC 1<<9 Mmap codes for IndexFlatCodes-derived indexes and HNSW (also supported on Darwin as of v1.14.2).

Tip

For indexes larger than RAM, the combination of on-disk inverted lists plus IO_FLAG_MMAP lets the OS page index data in on demand. The faiss.contrib.ondisk helpers and the demos/offline_ivf example show the full merge-to-on-disk workflow.


10. Security

Faiss has no network surface, no authentication, and no access control — it executes in your process. Its security profile is therefore about two inputs you control: index files you deserialize, and the vectors you process.

Untrusted index files are the primary risk

read_index deserializes a binary format that contains size and count fields (number of inverted lists, vector-transform chain length, hash counts, etc.). A malicious or corrupt file can specify enormous values to trigger pathological allocations or compute. Faiss v1.14.x ships explicit hardening knobs in index_io.h:

Control Default Purpose
set_deserialization_loop_limit(n) 0 (no limit) Reject loop-driving fields (nlist, nsplits, VT chain length, nhash, ...) that exceed n.
set_deserialization_vector_byte_limit(n) 1 TB (1<<40) Cap the bytes a single READVECTOR call may allocate.
set_deserialization_lattice_r2_limit(n) 0 (no limit) Reject IndexLattice payloads whose squared radius r2 would build an unboundedly expensive decode cache.

Caution

If your service loads index files supplied by users or fetched from untrusted storage, set these limits before any deserialization and run the load in an isolated process or sandbox. The functions are explicitly not thread-safe: configure them before any concurrent deserialization begins and do not change them mid-flight. There were also recent hardening commits validating HNSW and SVS deserialization read sites and adding format-enum sentinels.

Data-handling notes

  • Faiss does not encrypt index files; stored vectors and PQ codes are recoverable. If your vectors are sensitive (e.g. derived from personal data), protect the files at rest and in transit at the storage layer.
  • Reconstruction (reconstruct, sa_decode) can return approximations of the original vectors from compressed indexes — relevant if you considered the codes "anonymized."
  • The library trusts caller-provided array shapes/dtypes; the Python layer validates dtype and contiguity and throws clear TypeErrors, but C++ callers are responsible for correct sizes.

License & provenance

MIT-licensed, Copyright © Meta Platforms, Inc. Third-party components are listed in THIRD_PARTY_NOTICES. cuVS and SVS integrations pull in their own (Apache-2.0) licensed code.


11. GPU & Accelerator Backends

NVIDIA (CUDA / cuVS)

GPU support lives in faiss/gpu/. The entry object is StandardGpuResources, which manages per-device scratch memory and CUDA streams. Indexes move between host and device with index_cpu_to_gpu(res, device, index), index_cpu_to_all_gpus(index), and back with index_gpu_to_cpu(index). GPU indexes accept input from CPU or GPU memory; staying resident on the GPU avoids copy overhead.

When built with FAISS_ENABLE_CUVS=ON, IVF-Flat, IVF-PQ, and CAGRA can dispatch to NVIDIA cuVS implementations, and v1.14.2 adds filtered search for cuVS indexes and lets cuVS supply default values.

AMD (ROCm)

FAISS_ENABLE_ROCM=ON builds the GPU indices for AMD GPUs through HIP. The same gpu/ code path is compiled for HIP targets.

Apple Silicon (Metal)

faiss/gpu_metal/ adds a Metal backend for Apple Silicon. As of v1.14.2 it covers IndexFlat; the Metal shaders are extracted into standalone .metal files with a kernel wrapper class.

Note

GPU indexes do not implement every CPU index type or every operation. The drop-in story (IndexFlatL2 → GpuIndexFlatL2, or index_cpu_to_gpu) holds for the common Flat/IVF/PQ paths; exotic CPU index types may have no GPU equivalent.


12. Operations & Scaling

Because Faiss is embedded, "operations" is about how your service uses it.

Threading

Faiss parallelizes batch add/search with OpenMP. Control thread count with the standard OMP_NUM_THREADS environment variable or faiss.omp_set_num_threads(n). Search throughput scales with batch size — submit queries in batches rather than one at a time.

Important

A single index is generally safe for concurrent search from multiple threads (search is const), but concurrent add/train/remove with search is not. For IVF, prefer passing per-query SearchParameters over mutating index.nprobe from multiple threads. HNSW gained optional persistent locks in v1.14.2 for safe incremental adds.

Indexes larger than RAM

Three complementary strategies:

  1. Compression — IndexIVFPQ and additive-quantizer indexes shrink each vector to a few bytes, letting billions fit in RAM.
  2. On-disk inverted lists — build per-shard indexes and merge to a single on-disk index (faiss.contrib.ondisk, demos/offline_ivf), then load with IO_FLAG_MMAP.
  3. Sharding / distributed — split the database across machines and query in parallel (contrib/rpc.py, contrib/client_server.py, benchs/distributed_ondisk).

Reproducibility & monitoring

Seed RNGs (np.random.seed, Kmeans(seed=...)). Faiss has no built-in metrics export; instrument query latency and recall in your service. Validate recall against an IndexFlatL2 ground truth in CI when you change index parameters.


13. Performance Tuning

Lever Index family Effect
nprobe IVF More cells scanned → higher recall, lower QPS. The primary recall/speed dial.
nlist IVF (build) More cells → finer partitioning; rule of thumb ~sqrt(N) to 16*sqrt(N). Larger nlist needs more training data.
efSearch HNSW Higher → higher recall, slower search.
efConstruction, M HNSW (build) Higher → better graph quality, slower build, more memory.
m, nbits PQ More sub-quantizers / bits → better accuracy, more memory and compute.
Refine(...) + k_factor any compressed Re-rank more candidates with exact distances → recover recall at modest cost.
OPQ pre-transform PQ-based Rotates space so PQ quantizes better → higher accuracy for free at query time.
FAISS_OPT_LEVEL / SIMD build all CPU AVX512/AVX512-SPR/SVE kernels are substantially faster than generic.
Intel MKL BLAS flat / exact MKL is markedly faster than OpenBLAS on Intel for the BLAS-bound exact path.

Tip

The benchs/bench_fw framework and demos/demo_auto_tune.py automate the recall-vs-speed sweep across index types and parameters, producing Pareto fronts. Use them to pick an operating point rather than guessing.

Note

v1.14.2 adds throughput-oriented features worth knowing: database-parallel flat search for few-query workloads, IVF early-termination, a Kmeans early-stop threshold, TurboQuant (CPU), Panorama optimizations, and SuperKMeans (ADSampling + PDX pruning) for faster clustering.


14. The C API

c_api/ provides a flat C interface over the C++ library, enabled with -DFAISS_ENABLE_C_API=ON. It mirrors the C++ surface — index construction, faiss_Index_train/add/search, index_factory, write_index/read_index — using opaque handles and integer error codes instead of exceptions. Subdirectories: c_api/impl (error handling), c_api/utils, and c_api/gpu (GPU bindings). This is the integration point for languages other than C++/Python (Rust, Go, Java, etc. binders build on it).

Note

The C API is opt-in and not built by the default conda/pip packages. Build it from source if you need it.


15. Code Quality & Conventions

  • Language standard: C++17/20. Header + implementation split (IndexX.h / IndexX.cpp); algorithm internals isolated under impl/, reusable numeric kernels under utils/.
  • Error handling: C++ uses FAISS_THROW_MSG / FAISS_THROW_FMT / FAISS_THROW_IF_NOT_FMT (see impl/FaissAssert.h) to raise FaissException. Recent work replaced FAISS_ASSERT with throwing variants for recoverable conditions (e.g. unsupported SVS storage kinds) and added OpenMP exception-capture helpers so exceptions thrown inside parallel regions propagate correctly.
  • Matrix convention: all vector batches are compact, row-major n × d arrays of float32; element j of vector i is x[i*d + j].
  • SIMD strategy: a simdlib abstraction plus per-level translation units, increasingly via dynamic dispatch so one binary can pick kernels at runtime. Cross-SIMD-level correctness is enforced with bit-exact reference tests (@for_all_simd_levels, NoneSIMDLevel context manager).
  • Python ergonomics: SWIG generates raw bindings; faiss/python/*.py then replaces methods so they accept NumPy arrays and return (D, I) tuples instead of requiring explicit pointers and counts. class_wrappers.py validates dtype/contiguity and raises clear TypeErrors.

16. Testing

  • C++: GoogleTest, fetched via CMake FetchContent (release-1.12.1). The suite (tests/CMakeLists.txt) covers IVF, PQ encoding/codec, HNSW, NSG, scalar quantizer, merge/on-disk/mmap (POSIX-only), heaps, partitioning, fast-scan, SIMD levels, callbacks, and zero-copy paths. x86 AVX2/AVX512 intrinsic tests compile only under FAISS_OPT_LEVEL=dd on x86-64; SVS tests gate on FAISS_ENABLE_SVS. Windows defers gtest discovery to ctest time (the DLL isn't on PATH at build time) and skips POSIX-API tests.
  • Python: pytest tests/test_*.py against the built extension; GPU tests under faiss/gpu/test/, Metal tests under faiss/gpu_metal/test/.
  • Backward compatibility: tests/index_io_backward_compatibility/ verifies that indexes written by older versions still load — important given the serialization format is a public contract.

Important

When changing any serialization code, run the backward-compatibility tests and add a fixture for the new format. Index files in the wild outlive the code that wrote them.


17. Potential Improvements & Known Issues

Drawn from the live issue tracker at the documented commit:

Issue Status Impact
Data race in NNDescent::update() — unlocked read of other.pool.back() before acquiring the lock (#5276) Open bug Potential corruption/crash during concurrent NNDescent graph construction.
fast_scan fails to compile on AMD Zen5 with any FAISS_OPT_LEVEL (#5245) Open bug Blocks from-source builds on Zen5; use prebuilt packages or a different opt level.
Missing musllinux wheels on 1.14.2 (#5272) Open Alpine/musl users cannot pip install; use conda or build from source.
New Python type stubs not included in the conda package (#5261) Open Editor type-checking is degraded under conda installs.
Index.reconstruct_n() stub resolves to torch.Tensor under mypy for default CPU calls returning numpy.ndarray (#5232) Open Type-checker false signal; runtime behavior is correct.
SWIG 4.4 DeprecationWarning: builtin type has no __module__ attribute (#4481) Open feature/upgrade Forward-compat with newer SWIG.
Import failure on Python 3.12 via deprecated numpy.distutils (#3936) Resolved Fixed by NumPy ≥ 2.0 __cpu_features__ path in loader.py.
Windows ARM64 (MSVC) build broken by NEON SIMD templatization (#4993) Resolved —

Architectural opportunities (observed from the source):

  • The serialization hardening limits (Security) default to permissive (0/1 TB). Services accepting untrusted index files should consider whether Faiss should ship safer defaults or a documented "untrusted load" preset.
  • SIMD dispatch is mid-migration from static per-level TUs to dynamic dispatch; consolidating fully would simplify the build matrix and the loader fallback chain.
  • GPU coverage is uneven across index types; a capability matrix in the docs (which IndexX has a GPU/Metal/cuVS equivalent) would reduce surprises.

18. Quick Reference

Build cheat sheet

# CPU, AVX2, shared lib, with Python and C API
cmake -B build . -DCMAKE_BUILD_TYPE=Release -DFAISS_OPT_LEVEL=avx2 \
      -DBUILD_SHARED_LIBS=ON -DFAISS_ENABLE_GPU=OFF \
      -DFAISS_ENABLE_PYTHON=ON -DFAISS_ENABLE_C_API=ON
make -C build -j faiss_avx2 swigfaiss
(cd build/faiss/python && python setup.py install)

# NVIDIA GPU with cuVS
cmake -B build . -DFAISS_ENABLE_GPU=ON -DFAISS_ENABLE_CUVS=ON \
      -DCMAKE_CUDA_ARCHITECTURES="80;90"
make -C build -j faiss swigfaiss

Key environment variables

Variable Scope Effect
FAISS_OPT_LEVEL runtime + build Force SIMD level.
FAISS_DISABLE_CPU_FEATURES runtime Disable specific CPU features at load.
OMP_NUM_THREADS runtime OpenMP thread count for add/search.

Deserialization hardening (untrusted index files)

faiss.set_deserialization_loop_limit(10_000_000)        # cap nlist/nhash/etc.
faiss.set_deserialization_vector_byte_limit(1 << 32)    # cap single-vector alloc to 4 GB
faiss.set_deserialization_lattice_r2_limit(1 << 16)     # cap IndexLattice r2
index = faiss.read_index("untrusted.faiss", faiss.IO_FLAG_READ_ONLY)

Deployment checklist

  • [ ] Install a prebuilt package (conda/pip) unless you need a custom build.
  • [ ] Confirm the SIMD level matches the deployment CPU (or rely on auto-dispatch).
  • [ ] Pin OMP_NUM_THREADS to your CPU allocation in containerized deployments.
  • [ ] Validate recall against an IndexFlatL2 ground truth before shipping parameter changes.
  • [ ] If loading untrusted index files, set deserialization limits and sandbox the load.
  • [ ] Run backward-compatibility tests after any serialization change.
  • [ ] For >RAM datasets, choose compression, on-disk+mmap, or sharding deliberately.

Version & provenance

Fact Value
Version 1.14.2
License MIT (© Meta Platforms, Inc.)
Language C++17/20 + SWIG Python bindings + optional C API
Hard dependency BLAS (MKL / OpenBLAS)
Documented commit eb4c1ea