Skip to content

Commit ab1e5e9

Browse files
committed
Lucene: correct MAX_ITOPK docs, reference native hang issue
The javadoc and README claimed native CAGRA rejects any oversized itopk_size/searchWidth combination with a clear exception. Measurement shows that only holds below a threshold: above roughly iTopK 1e9 the native hash-table sizing loop fails to terminate and the search hangs instead of erroring. Correct that claim, stop implying MAX_ITOPK is a usable maximum, and point at #2523 which tracks the native defect. Documentation only; no behaviour change. Signed-off-by: Shaunak Kapur <shaunakk@nvidia.com>
1 parent ca57d3b commit ab1e5e9

3 files changed

Lines changed: 34 additions & 22 deletions

File tree

‎java/cuvs-lucene/README.md‎

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,21 @@ and the rest of the build parameters are derived from the heuristic's output.
107107
**Only the lower bound of 1 and the `SINGLE_CTA` `iTopK` maximum of 512 are genuine native
108108
limits.** `MAX_ITOPK` (`Integer.MAX_VALUE`) is simply the largest value representable by the
109109
public Java API, and `MAX_SEARCH_WIDTH` (4,194,303) only keeps CAGRA's result buffer within its
110-
unsigned 32-bit indexing limit — neither is a promise that native CAGRA supports every value up
111-
to that ceiling. The true upper limit for a given search depends on the resolved CAGRA algorithm,
112-
`max_iterations`, graph degree, filtering, and available GPU memory. In particular, `MULTI_CTA`
113-
(which a normal one-query `AUTO` search resolves to) sizes an internal traversal hash table from
114-
`search_width`, `iTopK`, `max_iterations`, and the graph degree, and native CAGRA rejects
115-
combinations that exceed that table's capacity with a clear exception. This class does not
116-
replicate that check — `max_iterations` is itself auto-derived from the graph degree and dataset
117-
size, values not known at query-construction time — so out-of-range combinations under `MULTI_CTA`
118-
(and other non-`SINGLE_CTA` algorithms) are caught by native CAGRA at search time, not by this API.
110+
unsigned 32-bit indexing limit. Neither is a promise that native CAGRA supports every value up
111+
to that ceiling, and in practice values anywhere near `MAX_ITOPK` are not usable. The true upper
112+
limit for a given search depends on the resolved CAGRA algorithm, `max_iterations`, graph degree,
113+
filtering, and available GPU memory. In particular, `MULTI_CTA` (which a normal one-query `AUTO`
114+
search resolves to) sizes an internal traversal hash table from `search_width`, `iTopK`,
115+
`max_iterations`, and the graph degree. This API does not replicate that calculation, since
116+
`max_iterations` is itself auto-derived from the graph degree and dataset size, values not known
117+
at query-construction time, so out-of-range combinations are caught by native CAGRA at search
118+
time rather than here.
119+
120+
Note that native CAGRA only reports some of those combinations cleanly. Moderately oversized
121+
values raise a clear exception, but above roughly `iTopK` 1e9 the native hash-table sizing loop
122+
fails to terminate and the search hangs instead of returning an error
123+
([#2523](https://github.com/NVIDIA/cuvs/issues/2523)). Treat these constants as representational
124+
ceilings only, and size `iTopK`/`searchWidth` to what the workload actually needs.
119125

120126
The query uses an effective `iTopK` equal to the greater of the configured value and the requested
121127
Lucene `k`; for `SINGLE_CTA`, this effective value is re-validated against the 512 limit again once

‎java/cuvs-lucene/src/main/java/com/nvidia/cuvs/lucene/GPUKnnFloatVectorQuery.java‎

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,19 @@ public class GPUKnnFloatVectorQuery extends KnnFloatVectorQuery {
7777
/**
7878
* Largest intermediate-result count representable by the public Java API.
7979
*
80-
* <p>This is a representational limit only, not a guarantee that every value up to this bound
81-
* is supported for every search. Native CAGRA sizes internal traversal hash tables from a
82-
* combination of itopk_size, search_width, max_iterations, and (for MULTI_CTA, which a normal
83-
* one-query {@code AUTO} search resolves to) the graph degree and dataset size — none of which
84-
* are all known at query-construction time. Combinations that exceed native CAGRA's hash-table
85-
* capacity are rejected by native CAGRA itself with a clear exception (see {@link
86-
* Utils#handleThrowable}); this class does not attempt to replicate that dataset- and
87-
* algorithm-dependent sizing logic.
80+
* <p>This is a representational limit only. It is emphatically not a supported maximum: values
81+
* anywhere near it are rejected by native CAGRA in practice. Native CAGRA sizes internal
82+
* traversal hash tables from a combination of itopk_size, search_width, max_iterations, and
83+
* (for MULTI_CTA, which a normal one-query {@code AUTO} search resolves to) the graph degree
84+
* and dataset size, none of which are all known at query-construction time, so this class does
85+
* not attempt to replicate that sizing logic.
86+
*
87+
* <p>Moderately oversized combinations are rejected by native CAGRA with a clear exception (see
88+
* {@link Utils#handleThrowable}). Very large values are not: above roughly 1e9, native CAGRA's
89+
* hash-table sizing loop fails to terminate and the search hangs instead of returning an error.
90+
* See <a href="https://github.com/NVIDIA/cuvs/issues/2523">#2523</a>. Callers should treat
91+
* itopk_size as bounded by what their algorithm and dataset actually support, not by this
92+
* constant.
8893
*/
8994
public static final int MAX_ITOPK = Integer.MAX_VALUE;
9095

‎java/cuvs-lucene/src/test/java/com/nvidia/cuvs/lucene/TestNativeSearchPlanBoundaryRejection.java‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,12 @@
4040
* dataset size -- so this test does not need to reproduce native CAGRA's {@code max_iterations}
4141
* auto-derivation to reliably trigger the rejection.
4242
*
43-
* <p>This class does not cover an oversized {@link GPUKnnFloatVectorQuery#MAX_ITOPK} the same
44-
* way: empirically, {@code iTopK = Integer.MAX_VALUE} does not fail fast like an oversized {@code
45-
* searchWidth} does -- it hangs inside the native call indefinitely instead of returning an
46-
* error, which would make a test asserting on it unsafe to run in CI (no bounded timeout reliably
47-
* recovers a thread stuck in native code). That hang is itself worth separate investigation.
43+
* <p>This class deliberately does not cover an oversized {@link GPUKnnFloatVectorQuery#MAX_ITOPK}
44+
* the same way. Above roughly 1e9, native CAGRA's hash-table sizing loop fails to terminate and
45+
* the search hangs rather than returning an error, so a test asserting on it would not be safe to
46+
* run in CI (no bounded timeout reliably recovers a thread stuck in native code). That is tracked
47+
* as a native bug in <a href="https://github.com/NVIDIA/cuvs/issues/2523">#2523</a>; the clean
48+
* rejection exercised here is the behaviour for the range below that threshold.
4849
*/
4950
@SuppressSysoutChecks(bugUrl = "")
5051
public class TestNativeSearchPlanBoundaryRejection extends LuceneTestCase {

0 commit comments

Comments
 (0)