Skip to content

GH-1391: Cap the token positions of one SentenceVectorsDL.embedAll inference - #1468

Draft
krickert wants to merge 2 commits into
mainfrom
feat/GH-1391-embed-batch-cap
Draft

krickert wants to merge 2 commits into
mainfrom
feat/GH-1391-embed-batch-cap

Conversation

@krickert

@krickert krickert commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Draft until #1462 is merged

TextEmbedder.embedAll and the manual say the implementation forms its own batches, so a caller may pass a list of any size. SentenceVectorsDL.embedAll groups texts by tokenized length and splits each group so that no inference takes more than 16384 token positions (rows times row length), which is 32 rows at the BERT length of 512. An input longer than 16384 tokens runs in a batch of its own.

Vectors do not change: batches are not padded, so every row is computed from the same tensors as its single-input call.

The grouping is in a package-private batches(Tokens[]) that returns the index lists embedAll runs, so the tests can check the inference plan directly. MAX_BATCH_TOKEN_POSITIONS is a package-private constant, not an option.

AI assisted test description:

Tests, in SentenceVectorsDLBatchLimitTest: row count boundaries computed from the cap (exact fit, one over, one under, lengths that do and do not divide it), a length at and over the cap, an empty call, groups in call order, a mix where only one group splits (checked through the session at the batch boundaries), an input at the cap next to short inputs, and every pooling path through split groups of alternating lengths. The GPU parity test of #1462 also runs a split group. The tiny model texts and expected vectors are shared in TinyVectorModels.

Fixes #1391

@rzo1 rzo1 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.

Hi @krickert, thanks for the PR. The splitting in batches(...) looks correct to me. Some remarks inline, and two on the process:

  • This PR contains the commit of #1462, which currently has changes requested. Please mark it as draft until #1462 is merged and rebase it afterwards; the review points on the shared test fixtures of #1462 apply here as well.
  • The description mentions new tests in SentenceVectorsDLEmbedderTest, but the commit only adds SentenceVectorsDLBatchLimitTest. Please also set the milestone and labels.

No eval build is needed, since no model and no default behaviour changes.

@krickert
krickert marked this pull request as draft October 11, 2026 20:07
@krickert
krickert force-pushed the feat/GH-1391-embed-batch-cap branch 3 times, most recently from e540ab2 to 8517809 Compare October 13, 2026 19:36
@krickert

Copy link
Copy Markdown
Contributor Author

Thanks. We'll keep in draft until #1462 happens, and rebased on the updated #1462 with its fixture changes. The description now lists only the tests the commit adds.

This helps the performance a lot, highly recommend keeping it in if we have the throughput.

krickert and others added 2 commits October 15, 2026 09:28
…t CUDA request in a fresh JVM

SentenceVectorsDL always created default session options, so it ran on
the CPU even with opennlp-dl-gpu. A new constructor takes
InferenceOptions, like NameFinderDL and DocumentCategorizerDL, and uses
the GPU settings and the lower case setting from them; a lower case
setting in the options takes precedence over the lowerCase argument. The
existing constructors keep their behavior.

AbstractDL.sessionOptions added the CUDA provider before any
OrtEnvironment existed. Loading the provider needs ONNX Runtime's default
logger, which only exists once an environment does, so the first GPU
request in a fresh JVM failed with "Attempt to use DefaultLogger but none
has been registered". The environment is now created first. This affects
NameFinderDL and DocumentCategorizerDL as well. When the provider cannot
be added, the session options created for the request are closed before
the exception is thrown.

A test makes the first CUDA request of a child JVM and requires that the
provider is added or rejected for a reason other than the missing
default logger; it runs in opennlp-dl-gpu and fails with the AbstractDL
of main. Other tests request a device id no machine has and check that ONNX
Runtime rejects it for SentenceVectorsDL, NameFinderDL and
DocumentCategorizerDL, and compare vectors on CUDA device 0 with the CPU
session (skipped without a CUDA provider or device). The tiny model test
fixtures are shared in TinyVectorModels.

The opennlp-dl-gpu test classpath no longer has the CPU onnxruntime next
to onnxruntime_gpu. Since onnxruntime_gpu has native libraries for
linux-x64 and win-x64 only, the opennlp-dl-gpu tests are skipped on
macOS and aarch64. The machine learning chapter documents the GPU
setup and the supported platforms.

Fixes #1389
Fixes #1390

Co-authored-by: Richard Zowalla <rzo1@apache.org>
Co-authored-by: Martin Wiesner <mawiesne@apache.org>
Signed-off-by: Kristian Rickert <kristian@apache.org>
Co-authored-by: Claude Code 2.1.296 (Opus 5.5) <noreply@anthropic.com>
…ference

TextEmbedder.embedAll and the manual say the implementation forms its
own batches, so a caller may pass a list of any size. SentenceVectorsDL
grouped the texts by tokenized length and ran each group as one
inference, however many texts it had. Each group is now split so that no
inference takes more than 16384 token positions (rows times row length),
32 rows at the BERT length of 512. An input longer than that runs in a batch of its own. Groups run in the
order their length first appears in the call.

Vectors do not change: batches are not padded, so every row is computed
from the same tensors as its single-input call.

The grouping moved into a package-private batches method so tests can
check the inference plan. SentenceVectorsDLBatchLimitTest covers row
count boundaries (exact fit, one over, one under, lengths that do and do
not divide the cap), a length at and over the cap, an empty call, a mix
where only one group splits, input order with alternating lengths, CLS
and mean pooling, the pooled-output model and unit length scaling
through a split group. The GPU parity test also runs a split group, and
the tiny model texts and expected vectors are shared in TinyVectorModels.

Fixes #1391

Signed-off-by: Kristian Rickert <kristian@apache.org>
Co-authored-by: Claude Code 2.1.296 (Opus 5.5) <noreply@anthropic.com>
@krickert
krickert force-pushed the feat/GH-1391-embed-batch-cap branch from 8517809 to 72f83f4 Compare October 15, 2026 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SentenceVectorsDL.embedAll builds one unbounded tensor per length group

2 participants