turbovec
A Rust vector index with Python bindings, implementing Google Research's TurboQuant quantizer (arXiv:2504.19874) and scoring it with hand-written SIMD kernels. MIT, on PyPI and crates.io. 16,771★ / 1,444 forks / 16 open issues, created 2026-03-26, last pushed 2026-08-21 — figures read 2026-09-10 from the GitHub API. By a distance the largest project this spoke holds.
Its headline is a memory claim: a 10M-document corpus at 31 GB in float32 fits in 4 GB, and searches faster than FAISS while doing it.
Why this spoke and not a database one
The compression is the product; the kernels are the reason it wins, and they are this spoke's subject at full scale:
- ARM — NEON
SDOTandSMMLAdot-product instructions scoring a vector-major layout directly. - x86 — AVX-512 VNNI for the 4-bit dot product, and
vpermbdriving the LUT scan that carries the short 2-bit accumulate loop. AVX2 and scalar fallbacks below that. - Filtering happens inside the kernel at 32-vector block granularity: blocks with no allowed slot are short-circuited before any LUT lookup, so a selective allowlist skips the SIMD cost instead of paying it and discarding the result.
That is data-parallel work done with real SIMD rather than within a register, on the exact question this spoke's open questions have been asking: where does hand-written low-level code still beat the alternative?
The measurements
All cells: 100K vectors, 1K queries, k=64, median of 5 runs, against FAISS IndexPQFastScan with
sub-quantizer counts matched to the same bit rate.
| 4-bit | 2-bit | |
|---|---|---|
| ARM (GCP c4a-standard-8, Google Axion) | 3.5× avg (3.4–3.7 across cells) | +26% (22–29) |
| x86 (Xeon Platinum 8481C, Sapphire Rapids) | 3.4× avg (3.2–3.5) | +20% (5–32) |
It wins every measured config on both architectures — and the gap between 4-bit and 2-bit is the interesting part: 3.4–3.5× where the dot-product instructions (SDOT/SMMLA, VNNI) do the work, and 20–26% where the 2-bit path falls back to a LUT scan. The advantage tracks which instruction the width can reach, not the compression ratio.
Mutation is where the difference is structural, not incremental. A single add() lands at
6.3–19.7 µs (7.6–13.9× faster than FAISS's); remove(id) is an O(1) swap-and-pop at 0.44–1.22 µs
against FAISS's remove_ids at 0.19–1.02 seconds, because FAISS repacks its stored codes on every
call. Six orders of magnitude, and it is a data-structure decision rather than a kernel one.
Recall is roughly a wash: calibrated TurboQuant beats FAISS IndexPQ at R@1 on three of four
OpenAI cells by 0.9–2.9 points, trails by 0.7 on one, and both reach 1.0 by k=8. On GloVe d=200 — low
dimension, where the method's asymptotic assumption is loosest — FAISS keeps an edge at deeper k.
Why T2 rather than T3
The author is benchmarking his own project against the incumbent, which is the shape this spoke
usually tiers T3 (valyu-billion-scale-vector-index). Three things separate it: the benchmark
scripts and the raw result JSONs are published, the hardware is named for every number, and the
README flags an artifact in its own harness — round-trip timings that come in below the isolated
dirty write, attributed to a standalone fsync inflating the separate step rather than claimed as a
win. It also argues against itself on baseline choice, deliberately comparing to a stronger
FAISS configuration than the TurboQuant paper used. Reproducible in principle, unreplicated in fact.
How the quantizer works
Data-oblivious, with no training phase — which is what makes online ingest possible at all.
Normalize each vector to a direction and store the norm; apply one shared random rotation, after which
every coordinate follows a Beta distribution converging to N(0, 1/d) regardless of the input
data; then quantize with a Lloyd-Max codebook computed from that known distribution rather than from
the corpus. TQ+ adds two scalars per coordinate (shift and scale) fitted once from ~1024 sampled
rows, recovering up to +2.2pp R@1 where finite dimension makes the asymptotic assumption drift.
The bit-level point: 2-bit means four buckets per coordinate, 4-bit sixteen, and the codebook is mathematics rather than k-means over the data — so the expensive part of a PQ index disappears and what remains is scoring, which is where the SIMD lives.
Connections
swar · population-count · hamming-distance · valyu-billion-scale-vector-index · uops-info · cortex-a76-optimization-guide · bit-manipulation · synthesis
- cross-spoke: RAG and embedding retrieval as an application belong to
../research-wikiand../agentic-tooling-wiki(the LangChain / LlamaIndex / Haystack / Agno drop-ins); the kernel is here