Faiss: Similarity Search and Clustering for Dense Vectors
GitHub Repo
MIT
November 13, 2026 at 03:38 PM
0 views

Faiss: Similarity Search and Clustering for Dense Vectors

@facebookresearchProject Author

What Faiss is

Faiss is a C++ library for similarity search and clustering of dense vectors, with complete wrappers for Python and numpy. The README describes it as containing "algorithms that search in sets of vectors of any size, up to ones that possibly do not fit in RAM", together with supporting code for evaluation and parameter tuning. Some of the most useful algorithms are also implemented on the GPU. The project is developed primarily at Meta's Fundamental AI Research group.

The problem it addresses is nearest-neighbour search. The wiki's home page puts it plainly: given a set of vectors of fixed dimension d, Faiss builds a data structure in RAM, and when given a new vector it efficiently finds the stored vector closest to it. In Faiss terms that data structure is an index, an object with an add method for inserting vectors and a search method for querying them. "This is all what Faiss is about," the wiki says, before listing extensions such as k-nearest-neighbour and range search, batch queries, trading precision for speed or memory, maximum inner product search, binary vectors and ignoring vectors by id.

Faiss assumes each item is represented as a vector and identified by an integer. Vectors are compared with L2 (Euclidean) distance or dot product, and cosine similarity is supported as a dot product on normalized vectors. It is aimed at developers and researchers who need to search or cluster large collections of embeddings or descriptors from code. It is a library you link or import, not a server you deploy.

How Faiss works

Everything in Faiss is built around the Index object. The README explains that some index types are simple baselines such as exact search, while most correspond to trade-offs between search time, search quality, memory per vector, training time, adding time and the need for training data.

The life cycle is the same for all of them. An index is constructed with the vector dimension, many types then need a training phase to analyse the distribution of the vectors, and after that vectors are added and searched. Re-training a populated index is not supported; the FAQ recommends constructing a new one. Search returns two nq-by-k matrices: neighbour ids sorted by increasing distance, and the corresponding distances. For METRIC_L2 Faiss reports squared Euclidean distances.

Flat indexes and exact search

IndexFlatL2 and IndexFlatIP perform brute-force search and are, according to the index selection guide, "the only index that can guarantee exact results". They store vectors uncompressed at 4*d bytes each, need no training and have no parameters. They do not store ids, so add_with_ids needs an IndexIDMap wrapper. They are the baseline for every approximate index.

Inverted files (IVF)

The main way Faiss avoids scanning every vector is the inverted file, which the wiki traces back to Sivic and Zisserman's "Video Google" paper. The feature space is partitioned into nlist cells, typically with k-means. A coarse quantizer, itself an index, assigns each database vector to a cell, and vectors are stored in nlist inverted lists. At query time only nprobe lists are scanned. The failure case is when the cell holding the true nearest neighbour is not selected. The default nprobe is 1, which the FAQ calls "on the low side".

The selection guide suggests 4*sqrt(N) to 16*sqrt(N) centroids below one million vectors, and an HNSW-based coarse quantizer above that, from 65,536 cells for 1M–10M vectors up to 1,048,576 for 100M–1B, noting that training gets slow and can be moved to a GPU.

Quantization and compression

Storing full vectors is the limit at scale. The README notes that methods based on binary vectors and compact quantization codes use only the compressed representation, which costs some precision but lets them "scale to billions of vectors in main memory on a single server". The encodings listed in the wiki include:

  • Scalar quantization (SQ8, SQ6, SQ4, SQfp16), which quantizes each component to 8, 6 or 4 bits or to 16-bit floats.
  • Product quantization (PQ), which splits vectors into sub-vectors and quantizes each to a few bits, allowing distances to be computed in the compressed domain. IndexIVFPQ combines it with an inverted file, and the wiki calls it "probably the most useful indexing structure for large-scale search".
  • OPQ, a linear transformation that makes vectors easier to compress with PQ, often combined with dimensionality reduction.
  • Additive quantizers such as the residual quantizer (RQ), local search quantizer (LSQ) and their product variants, which refine residuals in stages.
  • RaBitQ, which the selection guide recommends when maximum compression is required: 1 bit per dimension plus a small overhead, or multi-bit variants with 2 to 9 bits, usable flat or behind an IVF, with a fast-scan version.
  • Binary codes compared with Hamming distance, through IndexLSH and dedicated binary indexes.

Graph-based indexes: HNSW, NSG and others

The other family adds a graph on top of the vectors. IndexHNSW implements Hierarchical Navigable Small World graphs, controlled by M (neighbours per node), efConstruction and efSearch (exploration depth when adding and searching). The selection guide says that with plenty of RAM or a small dataset "HNSW is the best option", and gives its memory use as (d * 4 + M * 2 * 4) bytes per vector. HNSW needs no training but does not support removing vectors, because removal "would destroy the graph structure".

NSG (Navigating Spreading-out Graph) is also available, and an SVSVamana index comes from the optional Intel Scalable Vector Search integration. The 1.16.0 changelog adds IndexPiPNN, described as "a PiPNN graph index with beam search".

The index factory

Real indexes are composites of preprocessing, a coarse quantizer, an encoding and optional re-ranking, so index_factory builds them from a comma-separated string. The wiki's examples include "PCA80,Flat", which reduces 128-dimensional vectors to 80 dimensions with PCA and then searches exhaustively, and "OPQ16_64,IMI2x8,PQ8+16", which chains OPQ, an inverted multi-index and PQ refinement. A ParameterSpace object sets runtime parameters like nprobe or efSearch by name and can auto-tune them.

GPU support

According to the README, GPU indexes can be used as a drop-in replacement for CPU indexes (for example GpuIndexFlatL2 in place of IndexFlatL2), with copies handled automatically, though results are faster when inputs and outputs stay on the GPU. The GPU wiki page lists flat, IVF-Flat, IVF scalar quantizer and IVFPQ GPU indexes. For multiple GPUs, IndexReplicas copies the dataset to parallelize queries and IndexShards splits it to fit larger datasets.

Beyond the native CUDA kernels, INSTALL.md describes optional NVIDIA cuVS implementations of IVF-Flat, IVF-PQ and the CAGRA graph index, and support for AMD GPUs through ROCm. The changelog also records a Metal backend for Apple Silicon, added in 1.14.2 and enabled by default on Apple machines in 1.14.3.

Key features

  • Several distance metrics. L2 and inner product are the primary metrics. The metrics page says IndexFlat, IndexHNSW and GpuIndexFlat also support L1, Linf, Lp, Canberra, BrayCurtis and Jensen-Shannon.
  • GPU acceleration. CUDA GPU indexes with optional cuVS backends, ROCm support for AMD GPUs and a Metal backend on Apple Silicon.
  • k-means and clustering. Lloyd's k-means runs on CPU or GPU, and 1.16.0 adds an "e-means" training family with distributed and reduced-precision variants.
  • Serialization. write_index and read_index store indexes to files, and serialize_index converts them to numpy byte arrays.
  • Range search, id filtering and removal. Indexes can return all neighbours within a radius, skip vectors through an IDSelector, and remove vectors with remove_ids where the index type supports it.
  • CPU SIMD targets. INSTALL.md lists generic, avx2, avx512 and avx512_spr on x86-64 and generic and sve on aarch64, and 1.16.0 adds RISC-V vector (RVV) kernels.
  • Interoperability. The GPU page notes that PyTorch tensors can be passed directly to search() and add(), and a C API can be built with -DFAISS_ENABLE_C_API=ON.

Getting started

Installing with conda

INSTALL.md states that "the supported way to install Faiss is through conda", with stable releases and nightly builds pushed to the pytorch channel. The CPU-only faiss-cpu package is available on Linux (x86-64 and aarch64), macOS (arm64 only) and Windows (x86-64); faiss-gpu, containing both CPU and GPU indexes, is available on Linux x86-64 for CUDA 11.4 and 12.1; and faiss-gpu-cuvs is available on Linux x86-64 for CUDA 13.2. The commands for the latest stable release are:

# CPU-only version
$ conda install -c pytorch -c conda-forge faiss-cpu=1.16.0

# GPU(+CPU) version
$ conda install -c pytorch -c nvidia -c conda-forge faiss-gpu=1.16.0

# GPU(+CPU) version with NVIDIA cuVS
$ conda install -c pytorch -c nvidia -c rapidsai -c conda-forge libnvjitlink faiss-gpu-cuvs=1.16.0

# GPU(+CPU) version using AMD ROCm not yet available

The conda-forge channel is required for up-to-date dependencies (MKL on x86-64, OpenBLAS on ARM), and the nvidia channel supplies CUDA for the GPU packages. Pixi and nightly commands are also given.

Building from source

Faiss builds with CMake. The basic requirements are a C++20 compiler with OpenMP 2 or later and a BLAS implementation, with Intel MKL strongly recommended on Intel machines. GPU builds need nvcc and the CUDA toolkit, AMD builds need ROCm, and the Python bindings need Python 3, numpy and SWIG. The core steps from INSTALL.md are:

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

CMake options such as -DFAISS_ENABLE_GPU, -DFAISS_ENABLE_CUVS, -DFAISS_ENABLE_ROCM and -DFAISS_OPT_LEVEL select features and SIMD level.

A first search

The tutorial in tutorial/python starts with brute-force search over 100,000 random 64-dimensional vectors. Inputs are numpy arrays of type float32:

import numpy as np

d = 64  # dimension
nb = 100000  # database size
nq = 10000  # nb of queries
np.random.seed(1234)  # make reproducible
xb = np.random.random((nb, d)).astype("float32")
xb[:, 0] += np.arange(nb) / 1000.0
xq = np.random.random((nq, d)).astype("float32")
xq[:, 0] += np.arange(nq) / 1000.0

import faiss  # make faiss available

index = faiss.IndexFlatL2(d)  # build the index
print(index.is_trained)
index.add(xb)  # add vectors to the index
print(index.ntotal)

k = 4  # we want to see 4 nearest neighbors
D, I = index.search(xb[:5], k)  # sanity check
print(I)
print(D)
D, I = index.search(xq, k)  # actual search
print(I[:5])  # neighbors of the 5 first queries
print(I[-5:])  # neighbors of the 5 last queries

The first search is a sanity check: each of the first five database vectors should find itself at distance 0. The Getting Started page says the full search "takes about 3.3s on a 2016 machine".

Moving to an inverted file

The second tutorial swaps in an inverted file. Note the training step and the nprobe setting:

import faiss

nlist = 100
k = 4
quantizer = faiss.IndexFlatL2(d)  # the other index
index = faiss.IndexIVFFlat(quantizer, d, nlist, faiss.METRIC_L2)
# here we specify METRIC_L2, by default it performs inner-product search

assert not index.is_trained
index.train(xb)
assert index.is_trained

index.add(xb)  # add may be a bit slower as well
D, I = index.search(xq, k)  # actual search
print(I[-5:])  # neighbors of the 5 last queries
index.nprobe = 10  # default nprobe is 1, try a few more
D, I = index.search(xq, k)
print(I[-5:])  # neighbors of the 5 last queries

With a GPU build, 4-GPU.py shows the same flat and IVF indexes cloned to a device with faiss.index_cpu_to_gpu(res, 0, index_flat) after creating faiss.StandardGpuResources(), and 5-Multiple-GPUs.py uses faiss.index_cpu_to_all_gpus(cpu_index) to spread an index over every GPU.

Use cases

  • Embedding retrieval. Searching collections of vectors produced by neural networks, such as the 96-dimensional Deep1B activations used in the wiki's billion-scale benchmarks, for the nearest items to a query vector.
  • Recommendation. The metrics page says the inner product metric "is typically used for maximum inner product search in recommendation systems".
  • Image and descriptor search. Much of the research Faiss implements comes from image retrieval, and the benchmarks use SIFT descriptor datasets such as SIFT1M and BIGANN.
  • Large-scale clustering. k-means on CPU or GPU, with FAQ guidance on how many training points are useful.
  • Deduplication and data analysis. IndexFlatDedup removes duplicate vectors, and MatrixStats reports NaNs, duplicates, constant dimensions and normalization in a dataset.
  • Distributed index building. The FAQ describes training an IVF index on a sample, populating copies on several machines and merging them on a central node, or combining per-node indexes in an IndexShards.

How Faiss compares

Faiss sits at the library layer. Its documentation describes building, searching and serializing indexes from C++ or Python; nothing in it describes a network service, replication, access control or storage of metadata alongside vectors. Dedicated vector databases and search engines cover that ground. The real question is whether you want to own persistence, concurrency, updates and filtering in your own code.

The sources name a few other tools directly. For 2D or 3D data, the FAQ says low-dimensional indexing "is not addressed well in Faiss" and points to tree structures such as scikit-learn's KDTree, which give exact results in logarithmic time. NVIDIA cuVS and Intel SVS are not positioned as competitors but as optional backends: building with cuVS lets users choose between Faiss's own GPU implementations and cuVS ones for specific algorithms, and SVS supplies the Vamana graph index.

On performance, the README states that the GPU implementation provides what was "likely (as of March 2017) the fastest exact and approximate (compressed-domain) nearest neighbor search implementation for high-dimensional vectors", and the GPU wiki page claims GPU Faiss is 5–10 times faster than the corresponding CPU implementation on a single GPU, with 6–7 times speedup from replicating over 8 GPUs. These are the project's own claims, the first dated to 2017; the benchmarks README itself warns that timings change with implementation and hardware.

Things to know before adopting

  • Conda is the supported channel. INSTALL.md describes conda as the supported install method and gives no pip command. The wiki explains that Anaconda provides a controlled environment the team can be confident about, which "is not the case with pip". Recent changelogs do record pip wheel packaging work (pip install support via scikit-build-core in 1.14.2, and faiss-gpu and faiss-gpu-cuvs wheel packaging in later releases), but the install documentation has not been updated to describe it.
  • Platform coverage is limited. Source builds are supported on x86-64 Linux, macOS and Windows, with other platforms reported to work. Conda packages differ by variant: the GPU packages are Linux x86-64 only, macOS packages are arm64 only, and the ROCm GPU package is listed as "not yet available".
  • GPU requirements and limits. The GPU wiki page requires a CUDA device of compute capability 3.5 or higher. k and nprobe must be at most 2,048 on GPU, GpuIndexIVFPQ accepts only certain code sizes, and StandardGpuResources reserves up to 1,536 MiB of GPU memory for scratch space by default. GPU indexes cannot be written to disk directly; convert them to CPU first.
  • Everything lives in RAM. The selection guide says "all Faiss indexes are stored in RAM". Capacity planning starts from bytes per vector; the factory page puts HNSW32 links alone at 256 bytes per vector.
  • Integer ids only. The FAQ says Faiss does not support string ids or any datatype other than 64-bit integers, and "it is unlikely that this will change".
  • Filtering is limited. There is "limited support for filtering vectors at search time", based on vector ids only, and it slows down scanning. The FAQ suggests over-fetching, or one index per attribute value.
  • Concurrency is your responsibility. Concurrent searches work on CPU but not GPU, concurrent adds are not supported, and there is no locking.
  • Updates vary by index. HNSW cannot remove vectors, removal from flat indexes renumbers vectors, and IVF needs a direct map for reconstruction or updates.
  • Batch, not single-query, optimized. The FAQ explains that Faiss parallelizes over queries and relies on matrix-matrix products, so single-vector searches are comparatively slow.
  • Untrusted index files. The I/O page warns that no attempt is made to validate loaded data, and that a malicious file loaded with read_index could trigger out-of-memory errors or, "when crafted expertly", code execution. Only load index files you control.
  • Contribution model. CONTRIBUTING.md says Faiss is mainly developed inside Facebook and synced to GitHub, changes run through an internal test suite, and a Contributor License Agreement is required. Security bugs go through Facebook's bounty program.
  • Licence. Faiss is MIT licensed, with copyright held by Meta Platforms.

Project activity

As of November 2026 the repository has about 41,600 stars and 4,600 forks. It was created on 7 February 2017, is written primarily in C++, and its most recent push was on 13 November 2026. The latest release in CHANGELOG.md is 1.16.0, dated 9 November 2026, following 1.15.1 in September and 1.15.0 in July. The 1.16.0 entry covers e-means, IndexPiPNN, caller-owned Dataset APIs for CAGRA, quantizer kernel work, Metal additions and an upgrade to cuVS 26.10. The project is released under the MIT licence.

For academic use, the README asks users to cite "The Faiss library" (arXiv 2401.08281) and, for the GPU version, "Billion-scale similarity search with GPUs" (IEEE Transactions on Big Data, 2019).

Enjoying this project?

Discover more amazing open-source projects on TechLogHub. We curate the best developer tools and projects.

Project
faiss
Created
November 13
Last Updated
November 13, 2026 at 03:38 PM

Maintain Faiss: Similarity Search and Clustering for Dense Vectors? Add the badge to your README

Show that the project is featured on TechLogHub and send readers to this write-up.

Featured on TechLogHub
[![Featured on TechLogHub](https://techloghub.com/badge-neutral.svg)](https://techloghub.com/open-source/faiss?utm_source=techloghub_badge&utm_medium=referral&utm_campaign=readme)

Find more projects like this

One email a week: new and trending developer tools, fresh comparisons, and what shipped. Unsubscribe in one click.