You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix filtered CAGRA bench: incorrect recall due to kHostMmap filter bitset
Root cause: cuvs_cagra::get_preference() returned kHostMmap for the filter
bitset. GPU kernels (bitset_view::count, bitset_view::test) cannot read
file-backed lazy mmap pages:
- Non-ATS GPUs (H100, A100): no host memory access at all -> garbage filter
- ATS GPUs (GH200): hardware reaches host memory but un-faulted file pages
return zeros -> wrong filtering_rate -> incorrect recall
In both cases recall collapsed to approximately the filter pass rate.
Fix 1 (filter memory type): Add filter_memory_type to algo_property
(ann_types.hpp) so the filter bitset memory type can be set independently
of the dataset. cuvs_cagra sets filter_memory_type = kDevice so the
framework cudaMemcpy's the filter to GPU before passing it to CAGRA, while
dataset_memory_type stays kHostMmap to support datasets larger than GPU
memory (e.g. deep-100M at 38.4 GB on a 40 GB GPU).
Fix 2 (OOM prevention): set_search_param() unconditionally called
copy_with_padding(), doubling device memory usage for the dataset. Skip
copy_with_padding() when the data is already on device and no 16-byte
alignment padding is needed.
Fix 3 (copy() crash): sub_indices_ accumulated corrupted state when the
kDevice dataset update path ran. Reset it via placement new in copy() for
single-index CAGRA to prevent bad_array_new_length.
Fix 4 (filter_bitset_file): conf.hpp only supported filtering_rate (random
bitset generation). Pre-computed filter files specified via filter_bitset_file
in the JSON config were silently ignored, so filter_bitset was always null
and CAGRA ran unfiltered searches. Added filter_bitset_file to dataset_conf
(conf.hpp), parse it from the JSON dataset block, pass it to the dataset
constructor (benchmark.hpp), and load it from disk (dataset.hpp).
Fix 5 (recall calculation): benchmark.hpp called non-existent gt_set() API.
Restored the correct parallel gt_maps()-based recall computation from main.
Fix 6 (include): composite/merge.hpp does not exist in the pre-built
libcuvs.so; changed to composite/index.hpp.
Tested on GH200 480GB (ATS) with deep-1M, 5% filter, inner product, k=10:
Unpatched: Recall=0.0495 for all itopk (filter not applied)
Patched: itopk=64->0.45, 128->0.73, 256->0.92, 512->0.94, 1024->0.9999
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
0 commit comments