Skip to content

Commit fa19d6e

Browse files
Michael Norrisfacebook-github-bot
authored andcommitted
Fold multi-GPU CAGRA build into train(), delete trainMultiGpu
Summary: `GpuIndexCagra` had two multi-GPU build entry points totalling 16 positional arguments, neither of which fits the `Index` API. This removes one and folds the other into `train()`. **Delete `trainMultiGpu` (approaches B and C).** Sharded SNMG CAGRA produces per-shard graphs with zero cross-shard edges by construction, so it needs post-hoc stitching (GPU brute-force or CPU HNSW) just to be usable, and it lost to the `all_neighbors` path on both build time and recall. It had no callers outside the benchmark and one test. The benchmark's approaches B and C go with it; approach A (`IndexShards`) stays, since it does not use `trainMultiGpu` and is still a useful baseline. **Fold `trainAllNeighbors` into `train()`.** It was a 9-argument method with 6 trailing bare scalars: ``` index.trainAllNeighbors(n, ptr, devices, 0, 0, True, 2, 2.0, 8192) ``` `train_ex()` now dispatches to the private `trainAllNeighbors_()` when `GpuIndexCagraConfig::devices` names more than one device, which is the established Faiss GPU convention (build knobs live in the constructor-time config struct). The six scalars resolve as: | Old argument | Now | | --- | --- | | `devices` | `GpuIndexCagraConfig::devices`, also the dispatch predicate | | `build_algo` (0/1/2) | `GpuIndexCagraConfig::build_algo` | | `refinement_rate` | `GpuIndexCagraConfig::refine_rate` | | `n_clusters`, `overlap_factor`, `multi_gpu_optimize`, `ivfpq_search_batch` | new `AllNeighborsCagraConfig` | This also kills a live footgun: `trainAllNeighbors` took an `int build_algo` whose encoding (0=NN-descent, 1=brute-force, 2=IVF-PQ) disagreed with the `graph_build_algo` enum in the same header (0=IVF_PQ, 1=NN_DESCENT). Both callers set `config.build_algo` and then passed an unrelated int, and the config field was silently dead on that path. `BRUTE_FORCE` is appended to `graph_build_algo` (at the end, so existing values do not renumber) and the config field is now the single source of truth. Notes on what deliberately did NOT get merged into the config: - `ivf_pq_params` / `ivf_pq_search_params` are still not consulted on this path. cuVS derives `n_lists`, `pq_dim` and the kmeans trainset fraction from the dataset shape (`n_lists = n/2000`, i.e. 50000 at 100M, versus the static default of 1024). Applying `IVFPQ*CagraConfig` wholesale would discard that tuning. The IVF-PQ search batch cap therefore keeps its own field, with 0 meaning "leave cuVS's dataset-derived default". - `faiss::cagra_build_algo` only has `{IVF_PQ, NN_DESCENT}`, so a `BRUTE_FORCE` config would silently degrade to NN-descent on the single-GPU path; `train_ex()` now rejects it there. `GpuIndexBinaryCagra` shares this config struct and has no multi-GPU build, so it rejects `devices.size() > 1` rather than silently building on one device. Behavior change: the default `build_algo` on the multi-GPU path is now `IVF_PQ` (the config default) rather than NN-descent (the old argument default). That matches the single-GPU path and the recommended 100M config. Differential Revision: D114685755
1 parent 76c67b7 commit fa19d6e

5 files changed

Lines changed: 239 additions & 754 deletions

File tree

faiss/gpu/GpuIndexBinaryCagra.cu

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ std::shared_ptr<GpuResources> GpuIndexBinaryCagra::getResources() {
7878
}
7979

8080
void GpuIndexBinaryCagra::train(idx_t n, const uint8_t* x) {
81+
// GpuIndexCagraConfig is shared with the float index, whose multi-GPU
82+
// build path has no binary equivalent. Reject rather than silently
83+
// building on one device.
84+
FAISS_THROW_IF_MSG(
85+
cagraConfig_.devices.size() > 1,
86+
"binary CAGRA has no multi-GPU build; "
87+
"GpuIndexCagraConfig::devices must name at most one device");
88+
8189
DeviceScope scope(cagraConfig_.device);
8290
if (this->is_trained) {
8391
FAISS_ASSERT(index_);

0 commit comments

Comments
 (0)