feat: add optional cuVS training and construction for IVF-SQ - #101
Open
TheR1sing3un wants to merge 1 commit into
Open
TheR1sing3un wants to merge 1 commit into
TheR1sing3un wants to merge 1 commit into
Conversation
Expose prepared training and validated external assignment/encoding interfaces without adding CUDA dependencies to the native library or changing index files. Add reusable Python GPU workers, numerical and lifecycle tests, and a stage benchmark. Leave CPU SQ calibration optimization as a follow-up TODO.
Member
Author
|
@JingsongLi Hi, this is the first pr about cuda acceleration. Could you review it for me? |
JunRuiLee
approved these changes
Sep 13, 2026
JunRuiLee
left a comment
Contributor
There was a problem hiding this comment.
LGTM. The cuVS integration is optional and well isolated, preserves CPU compatibility and the existing index format, and shows strong real-GPU performance improvements without recall regression.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #100
This adds optional cuVS/CuPy acceleration for IVF-SQ training and construction, with CPU-readable v1 output and no mandatory CUDA dependency.
Performance at a glance
2.63× faster fixed-center index builds and 6.80× faster full-vector addition on real GIST1M, with unchanged Recall@10.
10M GIST-derived synthetic workload: 4.63× faster fixed-center builds (78.4% less time) and 9.25× faster full-vector addition.
One NVIDIA L20Z vs. 8 CPU threads; 1M vectors × 960 dimensions, L2, batch 8,192. Three-run medians on this PR's source:
The fixed-center build includes sampling, CPU SQ calibration, full-vector addition, and buffered serialization; it excludes center fitting. GPU builder setup is included. Training rows come from a separate experiment with a reused GPU worker; its first setup costs 0.639 s. Total training compares CPU Auto with cuVS, which use different clustering strategies; the fitting-only comparison uses CPU Lloyd and identical initial centers.
Scaling to 10M vectors (GIST-derived synthetic)
At 10M vectors, fixed-center build time drops from 217.444 s to 47.002 s, saving 170.442 s per build.
One L20Z vs. 8 Rayon threads; 960 dimensions, L2, 4,096 fixed centers, exact assignment, batch 8,192. Three fresh-process repeats per case with rotated CPU/GPU order. Each CPU/GPU pair uses identical input and the same SQ encoding model. Times below are medians in seconds.
At 10M, build time is 78.4% lower and add time is 89.2% lower. GPU add throughput reaches approximately 484K vectors/s.
.npymatrix. The first 1M rows are unchanged GIST1M; subsequent rows are independently perturbed copies (Gaussian noise stddev 0.0001, seed 20260911). This measures scale/capacity on a GIST-derived workload. The 1M row is this experiment's own matched baseline, measured separately from the.fvecsexperiment above. The GPU adapter source matches this PR.Changes
CuvsKMeansandCuvsIvfSqWritercontext managers. The builder supports GPU assignment with either CPU or GPU SQ8 encoding and borrows the caller's native writer.train_sq_from_processed.GPU construction requires a model calibrated with exact assignment (
ivf.coarse-assignment=exact). Default CPU paths, native dependencies, serialization, and readers remain unchanged. GPU execution is exposed through Python; native extension points are backend-independent.Detailed measurements
Construction ablations: CPU vs. GPU assignment vs. GPU assignment + encoding (18 builds)
Measured on the submitted source: real GIST1M (1M × 960, L2), one L20Z, 8 Rayon threads, batch 8,192, cuVS 26.08.01 / CuPy 14.2.0. These are workload-specific observations against an 8-thread CPU baseline, not the host's full-core maximum.
For construction, all modes use identical sampled rows and fixed centers per nlist. Each case runs in a fresh process; three repetitions rotate mode order (18 builds). Values are medians, with min–max add times in parentheses.
At nlist=4,096, GPU assignment alone reduces add time from 19.289 to 3.597 s. GPU encoding further reduces it by 21.1%, to 2.837 s. Combined add speedup is 6.80×; fixed-center total speedup is 2.63×. At nlist=1,024, GPU encoding independently reduces add time by 26.4%.
The add timer includes builder initialization/close, validation, transfers, and native append. Fixed-center total additionally includes sampling, CPU SQ calibration, and buffered serialization; centroid fitting is excluded. Source opening, diagnostics, and query evaluation are outside these timers; writes do not call fsync. Recall uses 1,000 held-out queries, nprobe=64/256 respectively. With the same GPU assignments, CPU and GPU encoding produce byte-identical whole-index files in every repeat; independent CPU/GPU assignments may differ near ties.
Training ablations: CPU Auto, CPU Lloyd, and cuVS (9 runs)
The separate training ablation uses nlist=1,024, the same 65,536-row sample, 25-iteration limit, seed 1234, and three rotated repetitions:
CPU Lloyd and cuVS start from identical centers, but numerical convergence can differ. Center fitting is 35.1× faster than CPU Lloyd. CPU Auto uses hierarchical clustering; the 2.20× total-training comparison against Auto is a comparison of available strategies. GPU-fitted centers can change partition balance and CPU query latency; deployment should validate recall and query cost. Training reuses the GPU worker and reports its first initialization (0.639 s) separately. Fitting timings include required sample export and transfers.
Reproduction
Run
tools/benchmark_gpu_training.py --preset baseline --base "$BASE" --backends cpu-auto cpu-lloyd cuvs --coarse-assignment exact --threads 8 --batch-rows 8192 --repeats 3 --output-dir "$NEW_DIR"for training.For construction, use
--backends external --centroids "$CENTERS" --build-index --build-backend MODE --queries "$QUERIES" --neighbors "$TRUTH"with the same remaining settings. Usebaseline/mediumfor nlist 1,024/4,096 and nprobe 64/256. Rotatecpu,cuvs-assign, andcuvs-encodeacross fresh processes with--repeats 1, collecting three runs of each. Every output directory must be new. The tool records stage timings, sample/center hashes, native-library hash, versions, and recall.Validation and limits