- Faster clustering of vector embeddings (Cohere, OpenAI, MXBAI, CLIP, MiniLM) than FAISS.
- Index 10M embeddings of 1024 dimensions in less than a minute on a single CPU.
- Faster without compromising clustering quality.
- Support for quantized clustering (8-bit Scalar Quantization, LVQ, and RaBitQ)
- Efficient on CPUs (ARM and x86) and GPUs.
- Lightweight: no external dependencies.
- Portable: Linux (x86, ARM), macOS, Windows (x86, ARM), Wasm.
- Carefully interleaving GEMM routines and pruning kernels that prune dimensions efficiently
- In the benchmarks you see in the cover image, all algorithms are clustering the same data: No dimensionality reduction, no sampling, no early-termination.
from superkmeans import SuperKMeans
data = ... # Numpy 2D matrix
k = 1000
d = 768
kmeans = SuperKMeans(
n_clusters=k,
dimensionality=d
)
# Run the clustering
centroids = kmeans.train(data) # 2D array with centroids (k x d)
# Get assignments
assignments = kmeans.assign(data)Then, you can use the centroids to create an IVF index for Vector Search, for example, in FAISS.
Usage in C++
#include <vector>
#include <cstddef>
#include "superkmeans/superkmeans.h"
#include "superkmeans/hierarchical_superkmeans.h"
int main(int argc, char* argv[]) {
std::vector<float> data; // Fill
size_t n = 1000000;
size_t k = 10000;
size_t d = 768;
auto kmeans = skmeans::SuperKMeans(k, d);
// Or Hierarchical Super K-Means for extreme performance:
// auto kmeans = skmeans::HierarchicalSuperKMeans(k, d);
// Run the clustering
std::vector<float> centroids = kmeans.Train(data.data(), n);
// Assign points
std::vector<uint32_t> assignments = kmeans.Assign(data.data(), centroids.data(), n, k);
}
Check our examples for fully working examples in Python and C++.
SuperKMeans supports clustering quantized vectors, substantially accelerating clustering and barely affecting clustering quality. We support 8-bit scalar quantization, LVQ, and RabitQ. You give us float32 vectors and we handle the rest:
kmeans = SuperKMeans(
n_clusters=k,
dimensionality=d,
quantizer='rabitq' # or: sq8, lvq4
)
centroids = kmeans.train(data) # We return float32 centroids
assignments = kmeans.quantized_assign(data, centroids)Tip
Does quantized clustering hurt the index quality? Usually, NO: in most embedding datasets, quantized clustering will get you right where full precision will (+ faster indexing). Read our research paper for the full analysis.
Check our fully working examples in Python or C++.
Check our wiki for advanced usage and API reference.
pip install superkmeansWith CMake FetchContent. There are no dependencies to install: CMake fetches and builds everything it needs.
FetchContent_Declare(
superkmeans
GIT_REPOSITORY https://github.com/cwida/superkmeans
)
FetchContent_MakeAvailable(superkmeans)
target_link_libraries(myapp PRIVATE superkmeans)Compiling Python Bindings from source
- Clang 17 or GCC 13
- CMake 3.26
- Python 3 (only for Python bindings)
git clone https://github.com/cwida/SuperKMeans.git
cd SuperKMeans
pip install .
# Run plug-and-play example
python ./examples/simple_clustering.py
# Set a value for n, d and k
python ./examples/simple_clustering.py 200000 1536 1000Compiling C++ library from source
- Clang 17 or GCC 13
- CMake 3.26
git clone https://github.com/cwida/SuperKMeans.git
cd SuperKMeans
# Set proper path to clang if needed
export CXX="/usr/bin/clang++-18"
# Compile
cmake .
make examples
# Run plug-and-play example
cd examples
./simple_clustering.out
# Set a value for n, d and k
./simple_clustering.out 100000 1536 1000For a more comprehensive installation and compilation guide, check INSTALL.md.
We are actively developing Super K-Means and accepting contributions! Check CONTRIBUTING.md.
To run our benchmark suite in C++, refer to BENCHMARKING.md.
SuperKMeans uses ForkUnion for threading (also when doing GEMM). You can plug in OpenMP or your own threading library by inheriting our ParallelExecutor class and passing it in our config.
You can inject your own memory allocator by inheriting our MemoryAllocator class and passing it in our config. Your memory allocator must be thread-safe and outlive the SuperKMeans object.
An efficient GEMM is key for performance. We use Eigen by default. In our benchmarks, Eigen is on par with OpenBLAS and BLIS, and 5–10% slower than Intel MKL end to end. You can also use your own BLAS (see INSTALL.md). However, it must be single-threaded and thread-safe.
SuperKMeans' ideas have been adopted in:
- FAISS
- Zilliz
- Elastic
- ParadeDB | Rust implementation
- RaBitQ-Library
- DuckIR: DuckDB extension for vector search
A Super Fast K-means for Indexing Vector Embeddings
@article{kuffo2026super,
title={A Super Fast K-means for Indexing Vector Embeddings},
author={Kuffo, Leonardo and Hepkema, Sven and Boncz, Peter},
journal={arXiv preprint arXiv:2603.20009},
year={2026}
}Stop Indexing at Full Precision: Revisiting Clustering for Vector Embeddings
@article{kuffo2026superquantized,
title={Stop Indexing at Full Precision: Revisiting Clustering for Vector Embeddings},
author={Kuffo, Leonardo and Boncz, Peter},
journal={VLDB 2026 Workshop: The 2nd Workshop on Vector Databases},
year={2026}
}