Skip to content

Add initial Lucene backend to cuVS Bench - #2624

Draft
nvzm123 wants to merge 7 commits into
NVIDIA:mainfrom
nvzm123:zackm_initial_pylucene_branch
Draft

nvzm123 wants to merge 7 commits into
NVIDIA:mainfrom
nvzm123:zackm_initial_pylucene_branch

Conversation

@nvzm123

@nvzm123 nvzm123 commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a lazy-loaded lucene cuVS Bench backend for Lucene CPU HNSW and cuvs-lucene CAGRA build/search.
  • Validates PyLucene 10.2, Java, thin/base JAR, and native-runtime prerequisites before initializing the process-global JVM, with actionable failures and fail-closed GPU path checks.
  • Uses JCC-compatible list conversion for float vectors and numeric DocValues for stable dataset IDs. Existing schema-1 indexes must be rebuilt with --force.
  • Adds packaged algorithm configurations, Fern documentation, wheel/conda metadata, and flat pytest coverage for runtime, backend, CLI, artifact, correctness, multi-segment/merge behavior, and live CPU/GPU execution.
  • Keeps Java production and test source out of the Python package; Java codec fixes and additional adapters are tracked separately.

This draft isolates the non-Java integration work previously explored in #2385 and #2475. The external PyLucene and Maven artifacts are runtime prerequisites and are not yet provisioned automatically by the cuVS Bench package.

The live lucene_e2e cases are manual-only in current CI. Automated provisioning and artifact handoff are tracked in #2635.

Validation

  • Ruff check/format and Python compilation: passed.
  • Focused runtime and lifecycle tests: 52 passed.
  • Complete cuVS Bench suite: 322 passed, 41 skipped.
  • Complete live PyLucene CPU/GPU integration module on EC2 A10G: 13 passed.
  • ARM64 discovery was covered with deterministic path-selection tests on x86_64. No real ARM64 hardware execution was performed.
  • Final wheel build and isolated install: passed; imports, Lucene YAML resources, entry-point groups, and the Click dependency floor were verified.

Performance validation

The data-path changes were compared against the preceding commit on the same EC2 A10G, using the same PyLucene 10.2 runtime, JDK, native environment, and exact cuvs-java and cuvs-lucene JAR hashes. Each side built and searched an isolated Deep1B 1M-vector, 96-dimensional index over 10,000 queries.

Route Build time QPS change by top_k
CPU HNSW 210.62 s -> 198.44 s (-5.8%) +3.9% / +27.7% / +44.1% / +46.0% at 10 / 100 / 1000 / 2000
CAGRA-built HNSW 56.70 s -> 46.08 s (-18.7%) +3.5% / +19.0% / +27.9% / +35.9% at 10 / 100 / 1000 / 2000
CAGRA search 57.58 s -> 47.70 s (-17.2%) +1.5% / +22.1% / +46.6% at 10 / 100 / 1000

Recall remained comparable in every paired run. Result materialization decreased by approximately 22-61%, while the separately measured JVM search phase remained broadly unchanged. These are single paired measurements and should be treated as directional rather than a statistical performance claim.

@copy-pr-bot

copy-pr-bot Bot commented Sep 16, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@imotov imotov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good start to me. However, I'd like to be able to run it to check a few things, and I think either the environment is missing some dependencies or the README is skipping over some important steps. It also seems that since these dependencies aren't installed in our cuVS environment, all integration tests are being skipped in CI.

Comment thread fern/pages/cuvs_bench/lucene_backend.md Outdated
The Lucene backend is opt-in because its runtime is not provisioned by the
ordinary cuVS Bench installation. Provisioning the required custom PyLucene
build is currently external to cuVS Bench. Every algorithm requires PyLucene
10.2.0 and JDK 22. CAGRA additionally requires matching `cuvs-java` and thin

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to install PyLucene manually for that to work?


def _java_vector(self, vector: np.ndarray) -> Any:
return self.lucene.JArray("float")(
tuple(float(value) for value in vector)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might skew the benchmark due to tuple conversion and cost of Python -> Java marshaling for all these floats.

)
hits = []
for score_doc in searcher.search(query, k).scoreDocs:
stored_id = stored_fields.document(score_doc.doc).get(_ID_FIELD)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is fair treatment for Lucene. Stored fields are pretty expensive option here. It might be better to at least replace it with doc values.

for prefix in _python_prefixes():
yield (
prefix / "lib",
prefix / "targets" / "x86_64-linux" / "lib",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now support ARM64.

@imotov imotov added improvement Improves an existing functionality non-breaking Introduces a non-breaking change Lucene labels Sep 23, 2026
@imotov

imotov commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

/ok to test 196f888

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Improves an existing functionality Lucene non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants