VRAM · GDDR & HBM
8 GB–2.3 TB
≈ 256 GB/s–64 TB/s
From 1x laptop GPU to 8x B300s with NVLink and HBM3e
- Strength
- Massive parallelism and aggregate HBM bandwidth
- Tradeoff
- Smaller capacity; irregular work needs new algorithms
Building AI infra · Since 2015 · Unum
Six assumptions worth revisiting, and what changes when you do.
And the open-source engines we built around each answer.
Capacity scales. Distance doesn’t.
Separating storage from compute is the most repeated lesson of the last decade of systems design, and it earned the repetition: storage scales on its own invoice, compute comes and goes, and durability becomes somebody else’s problem. For bulk scans it holds. A column store streaming a terabyte barely notices whether the bytes came from a bucket or a drive.
It stops holding where one read decides the next. A transaction commit, a graph walk and a nearest-neighbor search each issue hundreds of dependent reads, each waiting for the last, so a round trip of milliseconds becomes seconds per query. Those workloads belong beside the compute, with one copy of the data on local drives, in RAM or in VRAM, reached through direct I/O and not over a network. Once the bytes are local, the bottleneck moves into the core.
Random 4 KiB reads in one second on one linear axis · KIOXIA CM9 15.36 TB, PCIe 5.0, rated
Sources KIOXIA CM9 · S3 performance guidelines · S3 Express One Zone
Scroll horizontally to explore →
| Workload | Dependent reads per op | Local NVMe | Object storage | Verdict |
|---|---|---|---|---|
| Bulk scan of 1 TB | streamed | ≈ 5 s | ≈ 80 s | tolerable |
| Transaction commit | ≈ 2 + a write | ≈ 0.2 ms | ≈ 100 ms | prohibitive |
| Vector search, 1 B | ≈ 250 hops | ≈ 20 ms | ≈ 7.5 s | impractical |
| Vector search, 100 B | ≈ 400 hops | ≈ 32 ms | ≈ 12 s | impractical |
Sources Durner, Leis & Neumann, VLDB 2023 · DiskANN, NeurIPS 2019
Cores got wider. Compilers still use a fraction of what they know.
Trusting the compiler is the right default, and it won for good reasons: for scalar control flow, clang and GCC schedule better than any hand, and portable source outlives any one chip. Two decades of flat clocks were absorbed mostly by compilers and runtimes getting smarter.
Auto-vectorization stops at the loop it can prove. Mixed-precision dot products, masked substring search, AES-based hashing and predicated edit distances are different algorithms, not differently scheduled ones, and every extension spells them out as one intrinsic per type, width and mask. Those kernels are written by hand, one per ISA generation, and chosen at runtime. The same gap repeats across the PCIe bus, where most of the box’s compute now sits.
Sources riscv-opcodes · instruction popularity in Ubuntu, SYSTOR 2019 · Intel Intrinsics Guide · Arm intrinsics · RVV intrinsics
Layer and library Most software settles for What we built
Byte & string primitives StringZilla
Most softwarememmem · std::hash · std::sortGeneric string routines and hashing
We builtsz_find · sz_hash · sz_levenshtein_*Vectorized search, hashes and edit distances
Mixed-precision numerics NumKong
Most softwarefor (…) · cblas_sgemmAuto-vectorized loops or vendor BLAS
We builtnk_dot_* · nk_dots_* · nk_attention_*Typed products, attention and matrix tiles
Parallelism & scheduling ForkUnion
Most softwarestd::async · #pragma omp parallelGeneral-purpose tasks and thread pools
We builtforkunion_t · extended_atomic_refNUMA-aware fork-join and extended atomics
Atomics & collections SmashTable
Most softwarestd::mutex · std::unordered_mapA lock around each shared container
We builtatomic_hash_table · transaction_group::commitAtomic slots and commits across containers
A GPU brings compute. An SSD brings capacity. Neither helps an application that can’t reach it.
Keeping the engine on the CPU and the dataset in RAM was right for a long time: GPUs were for training, VRAM was small, PCIe was slow, and a pointer-chasing index wanted a general-purpose core. Most storage engines and vector indexes still assume it.
In a current node most of the rated watts are in the accelerators and most of the capacity is in the drives, with the CPU and its RAM between them as the narrowest tier. A CPU-only engine idles the compute; a RAM-only engine caps the data at terabytes. So the graph walk belongs in VRAM, the merge of sorted runs on the GPU, and the kernels on NVIDIA, AMD and Apple devices beside six CPU families. The problem is no longer the number of devices but the copies between them.
8 GB–2.3 TB
≈ 256 GB/s–64 TB/s
From 1x laptop GPU to 8x B300s with NVLink and HBM3e
4 GiB–32 TB
≈ 40 GB/s–2.3 TB/s
From 32-bit WASM sandboxes to 8x-socket Xeon Platinum systems
1.92 TB–2.46 PB
≈ 14–540 GB/s
From 1x to 40x PCIe 5.0 ×4 drives on dual-socket AMD Zen 5
Beyond one nodeNVLink, InfiniBand and Ethernet connect the next tier. Scale locally first; cross the network when the workload needs it.
Sources Xeon 8490H · DGX B300 · DGX B300 user guide · Xeon 6776P · CM9 SSDs
Scroll horizontally to explore →
| Kernel family | x86 | Arm | Others | NVIDIA | AMD | Apple | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Haswell | Skylake | Ice Lake | Sapphire | Granite | Sierra | Milan | Genoa | Turin | Diamond | NEON | SVE | SVE2 | SME | RVV | LoongArch | Power | WASM SIMD | WASM Relaxed | Ampere | Ada | Hopper | Blackwell | Blackwell RTX | CDNA 4 | CDNA 5 | Metal 9 | Metal 10 | |
| NumKong | ||||||||||||||||||||||||||||
| Vector Products | dedicated | dedicated | dedicated | compatible | compatible | dedicated | compatible | dedicated | compatible | dedicated | dedicated | dedicated | compatible | compatible | dedicated | dedicated | dedicated | dedicated | dedicated | compatible | compatible | compatible | compatible | compatible | compatible | compatible | compatible | compatible |
| Matrix Products | dedicated | dedicated | dedicated | dedicated | dedicated | dedicated | compatible | dedicated | compatible | dedicated | dedicated | compatible | compatible | dedicated | dedicated | dedicated | dedicated | dedicated | dedicated | dedicated | compatible | dedicated | dedicated | dedicated | dedicated | dedicated | dedicated | dedicated |
| Dense Attention | dedicated | dedicated | dedicated | dedicated | compatible | compatible | compatible | dedicated | compatible | dedicated | dedicated | compatible | compatible | dedicated | dedicated | ← fallback | ← fallback | ← fallback | dedicated | dedicated | compatible | dedicated | dedicated | dedicated | dedicated | dedicated | dedicated | dedicated |
| Late Interaction | dedicated | compatible | dedicated | dedicated | compatible | compatible | compatible | dedicated | compatible | compatible | dedicated | compatible | compatible | dedicated | ← fallback | ← fallback | ← fallback | ← fallback | dedicated | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable |
| Geodesic Metrics | dedicated | dedicated | compatible | compatible | compatible | compatible | compatible | compatible | compatible | compatible | dedicated | compatible | compatible | compatible | dedicated | ← fallback | ← fallback | ← fallback | dedicated | dedicated | compatible | compatible | compatible | compatible | – unavailable | – unavailable | – unavailable | – unavailable |
| StringZilla | ||||||||||||||||||||||||||||
| Hashes & Overlaps | dedicated | dedicated | dedicated | compatible | compatible | compatible | compatible | compatible | compatible | compatible | dedicated | dedicated | dedicated | compatible | dedicated | dedicated | dedicated | dedicated | dedicated | dedicated | compatible | compatible | dedicated | compatible | dedicated | compatible | dedicated | compatible |
| Unicode Matching | dedicated | compatible | dedicated | compatible | compatible | compatible | compatible | compatible | compatible | compatible | dedicated | compatible | dedicated | compatible | dedicated | dedicated | dedicated | dedicated | compatible | dedicated | compatible | compatible | compatible | compatible | dedicated | compatible | dedicated | compatible |
| Edit Distances | dedicated | dedicated | dedicated | compatible | compatible | compatible | compatible | compatible | compatible | compatible | dedicated | compatible | compatible | compatible | ← fallback | ← fallback | ← fallback | ← fallback | ← fallback | dedicated | compatible | compatible | dedicated | compatible | dedicated | compatible | dedicated | compatible |
| Regex & Lookarounds | dedicated | compatible | dedicated | compatible | compatible | compatible | compatible | compatible | compatible | compatible | dedicated | compatible | compatible | compatible | ← fallback | ← fallback | ← fallback | ← fallback | ← fallback | dedicated | compatible | compatible | compatible | compatible | dedicated | compatible | dedicated | compatible |
| JSONPath & XPath | dedicated | compatible | dedicated | compatible | compatible | compatible | compatible | compatible | compatible | compatible | dedicated | compatible | dedicated | compatible | dedicated | dedicated | dedicated | dedicated | compatible | dedicated | compatible | compatible | compatible | compatible | dedicated | compatible | dedicated | compatible |
| ForkUnion | ||||||||||||||||||||||||||||
| Extended Atomics | ← fallback | ← fallback | ← fallback | ← fallback | ← fallback | dedicated | ← fallback | ← fallback | ← fallback | dedicated | ← fallback | dedicated | dedicated | dedicated | dedicated | ← fallback | ← fallback | dedicated | compatible | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable |
| SmashTable | ||||||||||||||||||||||||||||
| Collections | dedicated | dedicated | dedicated | compatible | compatible | compatible | compatible | compatible | compatible | compatible | dedicated | dedicated | compatible | compatible | dedicated | ← fallback | ← fallback | dedicated | compatible | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable | – unavailable |
Sources NumKong dispatch lists · StringZilla dispatch lists · ForkUnion atomics · SmashTable row kits
The fastest byte is the one that never moves.
When a profile shows malloc, swapping in jemalloc or mimalloc is the right first move, and for allocation-heavy services it pays. Rewriting the hot loop is the right second. Both act on the compute third of the profile.
The other two thirds are memcpy, page faults, cross-socket stalls and waiting, and a faster allocator only makes the next copy cheaper to start. We design the path so the bytes stop moving: io_uring and SPDK read into registered buffers, threads and memory stay on one NUMA node, and pinned buffers or GPUDirect Storage land drive reads in VRAM without a staging copy. A path this direct also removes the safety nets that catch mistakes, which is where testing has to change.
Scroll horizontally to explore →
We test at nanosecond resolution and petabyte scale.
Memory safety is worth the rewrite: a borrow checker retires a whole class of crashes and exploits, and for most services that is the class that pages someone at night. It is the right floor.
It says nothing about the bugs that survive it. A safe program can still leave a graph region no search reaches, accumulate numerical error, publish half a commit, or wrap an address past 2⁶⁴ and keep running. Each needs its own proof: audit reachability from landmarks, check every kernel against extended-precision references, model-check rings and commits in Spin, and schedule with miniature index types to hit every boundary. Those races are decided in nanoseconds, six orders below where a cluster test suite looks.
Deleting a bridge can leave valid nodes unreachable. Average recall can hide the lost neighborhood.
Audit connectivityAudit reachability after every graph refinement, including deletions and merges.
Small rounding errors accumulate over long sequences. Wider sums keep that drift within bounds.
Bound numerical errorCompare every numeric type with extended-precision references and enforce ULP bounds.
Memory-safe threads can still publish the wrong result. The order of operations decides correctness.
Explore every interleavingModel-check protocol interleavings in Spin and GenMC, beyond the schedules ordinary tests encounter.
Valid operands can overflow an address. A petabyte offset times a wide stride reaches beyond 64 bits.
Check arithmetic boundariesCheck arithmetic at the boundary and return an explicit error, without allocating a petabyte.
The world is increasingly multimodal… one tastefully crafted framework is much more pleasant than buying from 10 different vendors.
Building this far down is rare, and the next section says why we do it anyway.
Writers and GPU indexes need a lock
On-disk IVF, apart from GPU indexes
C++ and Python bindings, plus a thin C API
Parallel writes, compaction on the CPU
Built for flash, db_paths spans drives
C++, C and Java in tree, others third-party
Only one writer at any instant, and no GPUs
One file per database, up to 281 TB in size
Self-contained C, in every phone and Mac
CPUs and GPUs from NVIDIA, AMD and Apple
Sources Faiss on the GPU · Faiss threads · Faiss beyond RAM · Faiss README · RocksDB README · RocksDB compaction · RocksDB thread pool · RocksDB options.h · RocksDB bindings · SQLite self-contained · SQLite most deployed · SQLite limits · When to use SQLite
Talk is cheap.
Linus Torvalds
Show me the code.
from usearch import Arena, DenseIndex
index = DenseIndex.init_ram(768)
index.insert(keys, vectors)
arena = Arena()
matches = index.search(queries, 10, arena)use usearch::*;
let index = DenseIndex::init_ram(&DenseOptions { dimensions: 768, ..Default::default() }, &[])?;
index.insert(&keys, &rows(&vectors, 768)?)?;
let mut arena = Arena::new()?;
let matches = index.search(&rows(&queries, 768)?, 10, &mut arena)?;const usearch = require('usearch');
const index = usearch.DenseIndex.initRam({ dimensions: 768 });
index.insert(keys, vectors);
const arena = new usearch.Arena();
const matches = index.search(queries, 10, arena);import USearch
let index = try DenseIndex.initRam(DenseOptions(dimensions: 768))
try index.insert(keys: keys, vectors: vectors)
let arena = try Arena()
let matches = try index.search(queries, wanted: 10, arena: arena)Google and Meta build their own engines because they have to. We build ours because we can’t stop.
The symptoms so far: four engines and four libraries.
We’ve stopped pretending we can quit.
Government agencies
Petabyte-scale search on hardware they own
Frontier AI labs
Retrieval and data pipelines at GPU speed
Search companies
Billions of vectors, one box before a cluster
Built with Unum building blocks
Open source
From our blog
Benchmarks, kernels and the reasoning behind them.

Apr 20, 2026IO · AI
GPUs moved to FP8. CPUs didn't. 200'000 lines of SIMD kernels later, USearch bridges both worlds — native Float8 Vector Search and KV Caching for the upcoming Arm-based NVIDIA Vera racks, Intel Xeons, open-source RISC-V chips, IBM Mainframes, Chinese LoongArch, and even WebAssembly in the browser — for higher throughput at 99% recall and half the memory cost

Nov 7, 2023IO · AI
Scaling Retrieval Augmented Generation with the USearch vector search engine on Intel Sapphire Rapids CPUs on Gcore, outperforming Meta's FAISS library by 10x - 100x on a scale of 100M to 1B vectors.

Jun 8, 2023IO · News
Partnering with Gcore and Intel to deploy the world most efficient data-processing infrastructure at the edge, powered by Unum assembly-optimized engines.