Commit Graph
16 Commits
Author SHA1 Message Date
lyang24 76978eee4a Fix selector handling for IVF iterator scans (#5592)
Summary:
Iterator-backed IVF scans ignored the configured `IDSelector`, and array-backed
scans applied it. An iterator-backed scan therefore returned IDs that the
selector excludes. `InvertedListScanner::iterate_codes` and
`InvertedListScanner::iterate_codes_range` now test `sel` for every entry.

`search_preassigned` also keeps the selector for an iterable list. The function
clears `sel` when the selector is an `IDSelectorRange` that sets
`assume_sorted`, because an array-backed list bounds a sorted section instead of
testing every entry. An iterable list holds no contiguous section to bound, so
it keeps the selector and takes the generic path. `range_search` holds no
sorted-range shortcut and needs no equivalent change.

The test loops over both values of `assume_sorted`, and it checks the KNN search
and the range search.

Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5592

Test Plan:
`buck2 test fbcode//faiss/tests:test_ivf_index fbcode//faiss/tests:test_custom_result_handler fbcode//faiss/tests:test_hnsw fbcode//faiss/tests:test_rabitq_simd_neon fbcode//faiss/tests:test_params_override fbcode//faiss/tests:test_hnsw_rabitq fbcode//faiss/tests:test_rabitq fbcode//faiss/tests:test_search_params fbcode//faiss/tests:test_io_corrupted fbcode//faiss/tests:test_rabitq_utils`, run at the top of the stack on aarch64: 173 pass, 0 fail, 3 skip.

`buck2 build fbcode//faiss:faiss` succeeds in the static aarch64 build and with `-c faiss.dynamic_dispatch=true`.

Reviewed By: alibeklfc

Differential Revision: D121846696

Pulled By: mnorris11

fbshipit-source-id: 09c8a3673fea6cc53f3370f05f3b6d399dfb4548
2026-10-01 10:36:44 -07:00
lyang24 41023120df Defer IVF list scan setup until needed (#5595)
Summary:
The IVF list scan prepared state that an early return then discarded. This diff
moves `scanner->set_list`, the `ScopedCodes` fetch and the `ScopedIds`
allocation after every check that can return first. A list that an
`IDSelectorRange` excludes no longer builds a lookup table and no longer fetches
its codes. The diff also folds the `jmin` offset into the initial codes pointer,
and it replaces `std::unique_ptr<ScopedIds>` with `std::optional<ScopedIds>`.

The diff also fixes a null-pointer dereference. `search_preassigned` cleared
`sel` for a sorted `IDSelectorRange` before it tested
`!(sel && store_pairs)`. That combination then reached
`IDSelectorRange::find_sorted_ids_bounds`, which reads `ids[0]`. The `ids`
pointer is null when the caller sets `store_pairs`. The test now runs before the
code clears `sel`, so the combination throws.
`IVF.sorted_range_selector_rejects_store_pairs` covers it.

**Microbenchmark.** The host holds 72 Cooper Lake cores. The build is
`mode/opt`. One core is pinned, and the two binaries interleave over 5 rounds.
The table reports the median of the medians. `IndexIVFPQ`, `d=64`,
`nlist=1024`, 100k vectors, `nprobe=1024`, sorted `IDSelectorRange`.

| ids that pass the range | before | after | ratio |
|---|---|---|---|
| 1% | 836 us | 587 us | **1.43x** |
| 10% | 894 us | 926 us | 0.97x |

The gain grows with the number of lists that the range excludes. At 10% the
saving sits inside the noise.

Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5595

Test Plan:
`buck2 test fbcode//faiss/tests:test_ivf_index fbcode//faiss/tests:test_custom_result_handler fbcode//faiss/tests:test_hnsw fbcode//faiss/tests:test_rabitq_simd_neon fbcode//faiss/tests:test_params_override fbcode//faiss/tests:test_hnsw_rabitq fbcode//faiss/tests:test_rabitq fbcode//faiss/tests:test_search_params fbcode//faiss/tests:test_io_corrupted fbcode//faiss/tests:test_rabitq_utils`, run at the top of the stack on aarch64: 173 pass, 0 fail, 3 skip.

`buck2 build fbcode//faiss:faiss` succeeds in the static aarch64 build and with `-c faiss.dynamic_dispatch=true`.

Reviewed By: alibeklfc

Differential Revision: D121846650

Pulled By: mnorris11

fbshipit-source-id: aa3d1d3e6f903ef9e57be5c3dd824a5b1a090228
2026-10-01 10:36:44 -07:00
Jaeyoon Jeong 38460ee969 Fix Faiss fp16 parity tests across architectures (#5695)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5695

Correct GPU tests to decode the exact packed fp16 values passed to `search_ex`; the generic software converter and legacy `roundToHalf` disagree on half-way ties. Keep labels exact while comparing CPU distances with the normal scaled `1e-5` BLAS/SIMD tolerance.

___

Differential Revision: D122785161

fbshipit-source-id: 057ded12bdc018add4bef39e514217b83b59c2cb
2026-10-01 07:33:29 -07:00
Jaeyoon Jeong 430a41ee4c Native fp16 k-means training for Faiss IVF (#5671)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5671

Train IVF coarse quantizers from packed fp16 (IEEE binary16) data without an fp32 copy of the training set, and let the k-means assignment step consume fp16 natively.

**k-means: `Clustering::train_ex(n, x, NumericType, index, weights)`**
Float16 runs k-means directly on the fp16 rows, without a codec:
- NaN/Inf check on the fp16 bit patterns
- subsampling and random initialization copy fp16 rows
- the centroid update accumulates fp16 rows into the fp32 centroids with F16C/NEON (`compute_centroids_fp16`)
- the assignment step passes blocks of at most `decode_block_size` fp16 rows to `Index::search_ex(Float16)`
Only k-means++ / AFK-MC2 initialization still widens the (subsampled) training set.

**Assignment: `Index::search_ex(Float16)`**
- Default for every index: widen bounded blocks and call `search()`.
- `IndexFlat` (L2 / IP): the BLAS kernels take fp16 queries (`knn_L2sqr_fp16`, `knn_inner_product_fp16`). Queries are widened inside the kernel in chunks of at most 16 MiB, each reused for all database tiles; results are bit-identical to the fp32 path on the rounded queries. The AVX2 / AVX512 / SVE top-1 kernels share one templated body. Selectors, small inputs, d <= 32 and database-parallel searches widen chunks and use the fp32 path. `IndexFlat1D` and `IndexFlatPanorama` keep their own search.
- GPU: every `GpuIndex` accepts Float16 (queries are copied to the device as fp16 and widened there); `GpuIndexFlat` with `useFloat16` storage searches fp16 queries directly with the fp16 GEMM.

**IVF**
- `IndexIVF::train_ex(Float16)` and `Level1Quantizer::train_q1_ex` use the native path; only the `train_encoder_num_vectors()` rows sampled for the encoder are widened. `IndexIVFFlat` trains only the coarse quantizer; `IndexIVFFlatDedup` rejects Float16.
- `train_encoded` (IVF and Clustering) remains the generic codec path, e.g. for decode-time normalization.
- `faiss::fp16_to_fp32` (faiss/utils/utils.h) is the shared bulk widening helper.

**Performance** (opt build, AMD Genoa: F16C conversion only, no fp16 arithmetic)
- top-1 knn, d=256, 65536 queries x 1024 centroids: fp32 22.2 ms, fp16 25.3 ms
- k-means, 1024 centroids, 10 iterations: fp32 270 ms, fp16 319 ms, identical centroids
On CPUs without fp16 arithmetic the GEMM still runs in fp32 on widened tiles, so fp16 is not faster than fp32 there. The gains are memory (fp16 data plus a bounded fp32 tile instead of a full fp32 copy) and a single hook (`search_ex`) for fp16-capable backends; GPU `useFloat16` already runs the fp16 GEMM directly.

Reviewed By: mnorris11

Differential Revision: D121848262

fbshipit-source-id: 1400d3eeb7c713359895923dcb86c544570cba69
2026-10-01 04:06:09 -07:00
saime 7437cac4d9 Fix Jaccard heap selection in IVF search (#5408)
Summary:
- Use `is_similarity_metric()` for IVF heap initialization, merging, reordering, and result handling.
- Add Jaccard IVFFlat regression coverage across parallel modes 0-3.

## Why

Jaccard scanners use similarity ordering, but `IndexIVF::search_preassigned` selected distance heaps for every metric except inner product. The resulting `FLT_MAX` threshold rejected all Jaccard candidates, returning `-1` even when the only inverted list was fully scanned.

Fixes https://github.com/facebookresearch/faiss/issues/5399.

## Validation

- [x] `cmake --build build --target faiss_test --config Release -j 8`
- [x] `ctest --test-dir build --output-on-failure -C Release` (251 tests, 5 skipped)
- [x] `clang-format-21 --dry-run --Werror faiss/IndexIVF.cpp tests/test_ivf_index.cpp`

## Notes for reviewers

Python and GPU suites were not run locally; the fix and regression exercise the shared C++ IVF path.

Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5408

Reviewed By: pankajsingh88, mnorris11

Differential Revision: D112830842

Pulled By: bshethmeta

fbshipit-source-id: c6431d2bee1b4fecd2e46cfda397722947a5407a
2026-07-23 10:53:58 -07:00
Saumitr Pathak 82a823513d Add iterator callbacks for distance computation and heap admission (#5082)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5082

Add two virtual callback methods to FAISS's InvertedListsIterator that fire during the iterate_codes hot loop:

- on_distance_computed(vid, distance): called after computing the distance for each scored vector, before the heap comparison. Enables callers to observe every distance computation (e.g. for building a reserve pool of all scored vectors sorted by distance).

- on_heap_changed(new_id, evicted_id): called when a vector displaces the current worst entry in the top-K heap. Enables callers to react to heap admission events (e.g. maintaining an O(K) PK mapping instead of O(N)).

Both methods have default no-op implementations, so existing code is unaffected. The callbacks are invoked in both the min-heap (L2) and max-heap (IP) branches of iterate_codes.

Zero overhead for non-users: the callbacks are guarded by a boolean flag (has_search_callbacks_, default false) that iterate_codes checks before each virtual dispatch. A correctly-predicted branch on modern x86 costs ~0 cycles due to speculative execution, compared to ~3-5 cycles per virtual call through a vtable. Since the flag is always false for non-callback users, the branch
predictor learns it immediately and never mispredicts.

Alternative approaches considered and why this design was chosen:
- CRTP / templated iterate_codes: would achieve true zero overhead via static dispatch and if-constexpr elimination, but requires changing FAISS's public API and template-instantiating iterate_codes — too invasive for upstream.
- Marking derived classes `final`: only enables devirtualization when the compiler sees the concrete type, which it cannot through InvertedListsIterator base pointers in iterate_codes.
- Raw function pointers with null checks: equivalent performance to the guard flag approach, but less clean API semantics for FAISS's object-oriented design. The guard flag achieves the best tradeoff: zero overhead for non-users, clean virtual override semantics for users, minimal code change, backward compatible.

Reviewed By: mnorris11

Differential Revision: D100352032

fbshipit-source-id: 42cfd24b4fbca1af9ccf07a2bb29528f35173659
2026-04-11 01:04:37 -07:00
Justin Gibbs c1e48a2ce1 Add search-path bounds checking to IndexIVF::search1 (#5040)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5040

Add the missing `key < nlist` upper-bound check in
`IndexIVF::search1()`, which was the only IVF search entry point
lacking this validation. The other two paths —
`search_preassigned()` and `range_search_preassigned()` — already
had this check.

Also add deserialization acceptance tests verifying that IVF indexes
with various quantizer states deserialize correctly:

1. **Surplus centroids** (`ntotal > nlist`):
   Produced by `shard_ivf_index_centroids()`, which distributes
   all of the original quantizer's centroids across shards without
   adjusting `nlist`. The search-time `key < nlist` bounds check
   prevents OOB access if the quantizer returns out-of-range keys.

2. **Trained quantizer** (`ntotal == nlist`):
   The normal trained IVF state.

3. **Sharded quantizer** (`0 < ntotal < nlist`):
   Also produced by `shard_ivf_index_centroids()`, when the
   original quantizer has `ntotal == nlist` and centroids are
   split across shards.

4. **Untrained quantizer** (`ntotal == 0`):
   Legitimate for custom inverted list management.

Reviewed By: mnorris11

Differential Revision: D99494237

fbshipit-source-id: 6a76b55f104b9c233dfdd2625bb0336ed8061463
2026-04-09 21:52:26 -07:00
Justin Gibbs 06ef481afa Fix uncaught exceptions in IndexIVF::range_search_preassigned OpenMP region (#5053)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5053

C++ exceptions thrown inside `#pragma omp parallel` regions that are not
caught within the region call `std::terminate` — they cannot propagate
across thread boundaries.

`IndexIVF::range_search_preassigned` had the same class of bugs fixed in
`search_preassigned` by D99455250:

1. **`scan_list_func` lambda**:
   `FAISS_THROW_IF_NOT_FMT(key < nlist)` was above the try-catch block,
   so a corrupt key >= nlist would throw uncaught and call
   `std::terminate`.

2. **Outer parallel region**:
   `get_InvertedListScanner()`, `scanner->set_query()`, and
   `FAISS_THROW_IF_NOT(scanner.get())` had no try-catch at all.

Fixes:

1. Moved the existing try-catch in `scan_list_func` up to also cover the
   key validation.

2. Wrapped the entire `#pragma omp parallel` body in a try-catch that
   uses the existing `interrupt`/`exception_string`/`exception_mutex`
   pattern to safely propagate exceptions out of the parallel region.

Reviewed By: mnorris11

Differential Revision: D99879998

fbshipit-source-id: e768372cbaf8a22a9459fc3fd9b9df6e019897a6
2026-04-09 15:30:20 -07:00
Justin Gibbs ef28c6beb0 Fix uncaught exceptions in IndexIVF::search_preassigned OpenMP region (#5037)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5037

C++ exceptions thrown inside `#pragma omp parallel` regions that are not
caught within the region call `std::terminate` — they cannot propagate
across thread boundaries.

`IndexIVF::search_preassigned` had multiple unguarded throw sites inside
its OpenMP parallel region:

1. **`scan_one_list` lambda**:
   `FAISS_THROW_IF_NOT_FMT(key < nlist)` and `scanner->set_list()` were
   above the try-catch block, so a corrupt key >= nlist would throw
   uncaught and call `std::terminate`.

2. **Outer parallel region**:
   `get_InvertedListScanner()` and `scanner->set_query()` had no
   try-catch at all.

Fixes:

1. Moved the existing try-catch in `scan_one_list` up to also cover the
   key validation and `set_list` calls.

2. Wrapped the entire `#pragma omp parallel` body in a try-catch that
   uses the existing `interrupt`/`exception_string`/`exception_mutex`
   pattern to safely propagate exceptions out of the parallel region.

Reviewed By: mnorris11

Differential Revision: D99455250

fbshipit-source-id: 41e8816d71c031b1e8526f76bd5a8936f4d4f160
2026-04-05 14:34:44 -07:00
Max BuckleyandClaude Opus 4.6 b3a2914982 fix: resolve compiler warnings in test files (#4944)
Summary:
- Fix compiler warnings in all 20 FAISS C++ test files
- Fixes include `-Wshadow`, `-Wunused-parameter`, and signed/unsigned comparisons

All changes are mechanical. No functional changes.

Part 13/13 of the compiler warnings cleanup (split from https://github.com/facebookresearch/faiss/issues/4810 per maintainer request).

Pull Request resolved: https://github.com/facebookresearch/faiss/pull/4944

Test Plan:
- [x] No functional changes — all fixes are mechanical renames and annotations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

Reviewed By: mnorris11

Differential Revision: D96996609

Pulled By: alibeklfc

fbshipit-source-id: 72555246a4ccf540eb5422e64018c8d5e2660dce
2026-03-20 10:21:55 -07:00
Subhadeep Karan 3a43e35292 Fix typos in tests and contrib directories (#4672)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/4672

Fixed typos in test files and contrib utilities:

tests/:
- Fixed 20 typos across test files (C++ and Python)
- Fixed function/class name typos in Python tests:
  * test_result_order_miltihash → test_result_order_multihash
  * TestOrthognalReconstruct → TestOrthogonalReconstruct
  * test_recons_orthogona_impossible → test_recons_orthogonal_impossible
- Fixed comment typos and error messages in C++ tests

contrib/:
- Fixed 9 typos in Python contrib utilities
- Fixed string literal typos in client_server.py and rpc.py
- Fixed documentation typos in evaluation.py and big_batch_search.py

All changes maintain backward compatibility - no API changes.

Reviewed By: mnorris11

Differential Revision: D86571375

fbshipit-source-id: bd0edf7ca2e004f78e0ccba7f4aac7db6621781a
2025-11-12 11:39:51 -08:00
Satyendra Mishra 3ff8a24282 Test sa_decode methd on IndexIVFFlat (#4098)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/4098

Increase test coverage: Test sa_decode methd on IndexIVFFlat

Reviewed By: mnorris11

Differential Revision: D67345048

fbshipit-source-id: 533e090a690ffc855091a4f95642446f93b93a3f
2024-12-17 14:17:43 -08:00
Nicholas Ormrod eb5e7341a6 facebook-unused-include-check in fbcode/faiss (#4029)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/4029

Remove headers flagged by facebook-unused-include-check over fbcode.faiss.

+ format and autodeps

This is a codemod. It was automatically generated and will be landed once it is approved and tests are passing in sandcastle.
You have been added as a reviewer by Sentinel or Butterfly.

Autodiff project: uif
Autodiff partition: fbcode.faiss
Autodiff bookmark: ad.uif.fbcode.faiss

Reviewed By: dtolnay

Differential Revision: D65957849

fbshipit-source-id: f6199250db595defd56f5e7b2828f838702e9a16
2024-11-15 13:53:46 -08:00
Michael Norris eff0898a13 Enable linting: lint config changes plus arc lint command (#3966)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/3966

This actually enables the linting.

Manual changes:
- tools/arcanist/lint/fbsource-licenselint-config.toml
- tools/arcanist/lint/fbsource-lint-engine.toml

Automated changes:
`arc lint --apply-patches --take LICENSELINT --paths-cmd 'hg files faiss'`

Reviewed By: asadoughi

Differential Revision: D64484165

fbshipit-source-id: 4f2f6e953c94ef6ebfea8a5ae035ccfbea65ed04
2024-10-22 09:46:48 -07:00
Junjie Qi db251e2778 Adding missing includes which are necessary for building (#3609)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/3609

The current version of Faiss cannot be built due to missing #includes on a test file tests/test_ivf_index.cpp. This is better described in issue #3532.

https://github.com/facebookresearch/faiss/pull/3533

Reviewed By: ramilbakhshyiev

Differential Revision: D59314273

fbshipit-source-id: 6ec8bfa973760d0a44bc94ae751b4fc55c4784ef
2024-07-03 10:58:40 -07:00
Xiaozhong Pan ebb5f8401b add a context parameter to InvertedLists and InvertedListsIterator (#3247)
Summary:
Pull Request resolved: https://github.com/facebookresearch/faiss/pull/3247

add a context parameter to be passed to InvertedLists and InvertedListsIterator.
- add a context field in `SearchParametersIVF`, the context will be passed to `InvertedLists::get_iterator`. The user can create `InvertedListsIterator` with the context object
- add a context parameter in `IndexIVF::add_core` method. the context will be passed to `InvertedLists::add_entry`.

The user can use the context object to pass storage handlers, store error codes from storage layer, logging information, etc.

Reviewed By: mdouze

Differential Revision: D53113911

fbshipit-source-id: ff31d247d3dc949d0bb50bcaffc3142efd027089
2024-02-09 09:14:38 -08:00