By the end of this tutorial you’ll have a working FAISS index running locally – faiss.IndexFlatL2 loaded, vectors added, search() returning nearest neighbors. The install itself takes about three minutes. The rest of the time goes toward avoiding the two or three traps that turn a clean install into a segfault at import.
FAISS is MIT-licensed and built at Meta’s Fundamental AI Research group for efficient similarity search and clustering of dense vectors. If you’re building RAG pipelines, semantic search, or deduplication, it’s still the reference implementation – the algorithms are described in Douze et al., 2024 (arXiv:2401.08281).
Which package you actually want
Three conda packages exist. Most tutorials collapse them into two – or just mention faiss-cpu and faiss-gpu and move on. That omission causes real problems once you’re on CUDA 13.2.
Per the official INSTALL.md: faiss-cpu works on Linux (x86-64 and aarch64), macOS (arm64 only), and Windows (x86-64). faiss-gpu – which includes both CPU and GPU indices – is Linux x86-64 only and targets CUDA 11.4 or 12.1. The third package, faiss-gpu-cuvs, brings NVIDIA’s cuVS 26.06 backend and requires CUDA 13.2, also Linux x86-64 only.
| Package | Use when | Platform |
|---|---|---|
| faiss-cpu | Dev machines, macOS, small-to-medium indexes | Linux / macOS / Windows |
| faiss-gpu | Existing CUDA 11.4 or 12.1 stack | Linux x86-64 |
| faiss-gpu-cuvs | New builds on CUDA 13.2 – fastest IVF-Flat, IVF-PQ, CAGRA | Linux x86-64 |
Version snapshot (as of late 2025): v1.13.0 was announced November 12, 2025 via GitHub discussion #4675. PyPI wheels for faiss-cpu 1.13.2 were uploaded December 24, 2025, targeting CPython 3.10+ and macOS 14.0+. The conda pytorch channel currently pins 1.14.3. That mismatch is normal – conda tends to ship slightly newer builds than PyPI.
System requirements
Pre-built wheel path: Python 3.10+, x86-64 CPU with SSE4 at minimum (AVX2 for full speed). That’s it.
Source builds are a different story. You need a C++20 compiler with OpenMP, a BLAS implementation (Intel MKL is the right call for x86-64), CUDA Toolkit plus nvcc for GPU support, and SWIG with Python 3 and NumPy for the Python bindings (per the official INSTALL.md). Most people don’t need this path.
- Minimum: 4 GB RAM, x86-64 CPU with SSE4, Python 3.10
- Recommended: 16 GB RAM, AVX2-capable CPU, Python 3.11+, MKL-linked BLAS
- GPU path: NVIDIA GPU, CUDA 12.1 (faiss-gpu) or CUDA 13.2 (faiss-gpu-cuvs)
Install commands
Pick one. faiss-gpu already includes CPU indices, so installing faiss-cpu alongside it wastes space and can create confusing import conflicts.
# Option A - CPU only, pip (fastest, cross-platform)
pip install faiss-cpu
# Option B - CPU only, conda (Meta's recommended path)
conda install -c pytorch -c conda-forge faiss-cpu=1.14.3
# Option C - GPU with CUDA 11.4/12.1
conda install -c pytorch -c nvidia -c conda-forge faiss-gpu=1.14.3
# Option D - GPU with cuVS backend, CUDA 13.2
conda install -c pytorch -c nvidia -c rapidsai -c conda-forge
libnvjitlink faiss-gpu-cuvs=1.14.3
The catch: GPU wheels don’t exist on PyPI. The reason is unglamorous – GPU binaries exceed PyPI’s file size limit (per the faiss-wheels README). So pip install faiss-gpu pulls a community-maintained artifact of uncertain vintage. Use conda for any GPU path.
Verify it works
No config file. FAISS is a library, not a service. The SIMD extension loads automatically – or it should.
import faiss
import numpy as np
print(faiss.__version__) # 1.13.2 or 1.14.3
print(faiss.get_num_gpus()) # 0 for CPU builds
d = 128
xb = np.random.random((1000, d)).astype('float32')
xq = np.random.random((5, d)).astype('float32')
index = faiss.IndexFlatL2(d)
index.add(xb)
D, I = index.search(xq, k=4)
print(I[:2]) # nearest 4 neighbors for 2 queries
Integer arrays in I and no exception? You’re done. But if Python prints Loading faiss with AVX2 support and then Could not load library with AVX2 support before falling back to generic – that silent fallback carries a real performance cost. More on that below.
The SIMD trap
Here’s the thing that bites people who move indices between machines: FAISS uses a multi-binary SIMD loader. At import time, faiss/loader.py detects the CPU instruction set and picks the most optimized variant – generic, avx2, avx512, avx512_spr, or sve. So far so good.
The problem is index portability. According to the faiss-cpu PyPI docs: indices built and saved in the x86_64 architecture are not always compatible in the arm64 environment, and indices built in the AVX2 extension are not compatible in the generic extension. This is common in containers, where CPU features aren’t correctly detected due to driver issues.
Think of it like this: the index file isn’t just data – it bakes in assumptions about the instruction set that built it. Move that file to a different SIMD world and it either refuses to load or, worse, loads and segfaults mid-search with no helpful message.
Docker rule: Build the index inside the same container image you’ll serve from. Never build on the host and mount the file in. Container CPU detection frequently misfires.
When you can’t rebuild: set FAISS_OPT_LEVEL=generic in the environment before importing faiss. Slower, but it travels.
Common errors
ModuleNotFoundError: No module named 'faiss.swigfaiss_avx2'– The loader falls back to plain faiss (per GitHub issue #2872). Harmless on Windows pip installs where AVX2 isn’t shipped. Want the speed? Switch to conda.- Segfault inside
index.search()– Almost always a CPU/SIMD mismatch in a container. Rebuild the index inside the same environment, or pinFAISS_OPT_LEVEL=generic. - Conda solver hangs on faiss-gpu-cuvs – Missing the
rapidsaiornvidiachannel. All four channels (pytorch, nvidia, rapidsai, conda-forge) are required for the cuVS build. - NumPy ABI errors – Older FAISS builds don’t play well with NumPy 2.x. Upgrade FAISS first; if the error persists, pin
numpy<2as a workaround (community-reported behavior, not a confirmed spec change). ImportError: libblas.so.3: cannot open shared object fileon slim Linux images –apt-get install libopenblas-dev libomp-devand retry.
Most of these errors share a common pattern: FAISS assumes a fairly complete system environment and fails quietly when something’s missing. The error message rarely points at the real cause. When in doubt, try the conda path – it pulls more of those system dependencies automatically.
Upgrade and uninstall
Upgrade: pip install -U faiss-cpu or conda update -c pytorch faiss-cpu. Index file formats are stable across recent minor versions, so saved indices generally survive an upgrade – provided the SIMD level on the new install matches what built them.
Uninstall: pip uninstall faiss-cpu or conda remove faiss-cpu faiss-gpu faiss-gpu-cuvs. No daemon, no config directory, no cache. FAISS lives entirely inside site-packages and leaves nothing behind.
FAQ
Is FAISS still maintained in 2026?
Yes – v1.13.0 shipped November 2025, and as of that same month the repo had 40.3k stars and 4.4k forks. Active.
Can I run FAISS on an Apple Silicon Mac?
CPU build only. Conda ships faiss-cpu for macOS arm64, and pip wheels cover macOS 14+. GPU is Linux x86-64 only – no Metal path. One practical note: an index built on your Mac won’t necessarily load on a Linux x86-64 server (the x86_64↔arm64 portability trap covered above). Rebuild on the target platform before deploying.
Should I use FAISS or a managed vector database?
FAISS is a library – you own the file, the process, the scaling. Managed services like Pinecone or Weaviate handle replication, high availability, and hybrid search, but add latency and cost. Under roughly 10M vectors on a single machine, FAISS is typically faster and cheaper. Past that point, the operational overhead usually makes a database worth it. A reasonable rule: start with FAISS, migrate when you hit a real operational problem – not because a blog post told you to future-proof.
Next step: pull 10,000 embeddings from a sentence-transformer, load them into IndexIVFFlat with 100 centroids, and time the search. That’s where the interesting tradeoffs start.