[Pooling] Report input throughput for batched requests - #53213
[Pooling] Report input throughput for batched requests#53213taneem-ibrahim wants to merge 4 commits into
Conversation
Signed-off-by: Taneem Ibrahim <taneem.ibrahim@gmail.com>
| num_input_sequences: match self.kind { | ||
| BackendKind::OpenaiEmbeddings | BackendKind::VllmPooling => { | ||
| input.prompt_list.as_ref().map_or(1, |list| list.len()) | ||
| } | ||
| BackendKind::OpenaiEmbeddingsChat => 1, | ||
| BackendKind::VllmRerank => { | ||
| input.prompt_list.as_ref().map_or(1, |list| list.len().saturating_sub(1)) | ||
| } | ||
| _ => unreachable!("PoolingBackend with non-pooling kind"), | ||
| }, |
There was a problem hiding this comment.
When prompt_list is None, documents can still come from extra_body, but this always reports one input even if multiple documents are sent?
| result.insert( | ||
| "input_sequence_throughput".into(), | ||
| serde_json::json!(metrics.input_sequence_throughput), | ||
| ); |
There was a problem hiding this comment.
Should we also expose this metric in the Rust compare, multi-run, and sweep summaries?
Signed-off-by: Taneem Ibrahim <taneem.ibrahim@gmail.com>
| def _get_num_input_sequences(prompt: Any) -> int: | ||
| if prompt and isinstance(prompt, list) and isinstance(prompt[0], str): | ||
| return len(prompt) | ||
| return 1 |
There was a problem hiding this comment.
Will list[list[int]] be supported?
There was a problem hiding this comment.
Very good point. The current helper treats list[list[int]] as one input. I’ll count both list[str] and list[list[int]] as batches while preserving list[int] as a single input, and update the type annotations accordingly.
Reproducer to test:
.vent/bin/python - <<'PY'
from vllm.benchmarks.lib.endpoint_request_func import _get_num_input_sequences
cases = [
("text batch", ["a", "b"], 2),
("token-ID batch", [[101, 102], [103, 104]], 2),
("single token-ID input", [101, 102], 1),
("chat content", [{"type": "text", "text": "hello"}], 1),
]
for name, value, expected in cases:
actual = _get_num_input_sequences(value)
print(f"{name}: expected={expected}, actual={actual}")
assert actual == expected
print("All input-shape checks passed")
PYPrior to the latest commit, we get an AssertionError:
text batch: expected=2, actual=2
token-ID batch: expected=2, actual=1
Traceback (most recent call last):
File "<stdin>", line 13, in <module>
AssertionError
After making the changes, it passes:
text batch: expected=2, actual=2
token-ID batch: expected=2, actual=2
single token-ID input: expected=1, actual=1
chat content: expected=1, actual=1
All input-shape checks passed
Thanks for the review!
Signed-off-by: Taneem Ibrahim <taneem.ibrahim@gmail.com>
yewentao256
left a comment
There was a problem hiding this comment.
LGTM, thanks for the work!
|
✅ @taneem-ibrahim, CI is now available for this PR.
|
|
/ci run |
|
✅ Triggered Buildkite CI #85126 for commit |
|
/ci retry |
|
✅ Queued 1 failed job(s) for retry in Buildkite CI #85126. |
Purpose
vllm bench servereports pooling throughput per HTTP request. With batched embedding or reranking inputs, one request can represent several independently processed inputs, so request throughput alone understates useful model throughput and makes batch-size comparisons difficult.The root cause is that pooling metrics increment
completedonce per successful HTTP response and discard the request's logical input cardinality. This change records that cardinality before sending the request and adds two pooling only metrics:total_input_sequencesinput_sequence_throughputExisting request and token metrics are unchanged. Embedding and generic pooling requests count batched inputs; reranking requests count documents. The Python and Rust benchmark clients expose the same console and JSON metrics.
Reproducer
Ten embedding inputs batched as
[4, 4, 2]produce three successful HTTPrequests over a one-second measurement window.
Output on
mainmainexposes the transport rate but not the ten-input processing rate.Output on this branch
The existing
3.0 req/sresult is preserved and the benchmark now also reports10.0 inputs/s.Test plan and results
cd rust cargo fmt --all -- --checkA local
aiohttpsmoke test exercised the embeddings, generic pooling, and reranking request paths against a mock server:End-to-end validation
Validated on an NVIDIA B300 using
BAAI/bge-base-en-v1.5.For the non-divisible batch, ten inputs were correctly represented as three HTTP requests (
4 + 4 + 2). Existing request and token metrics were preserved, andinput_sequence_throughputmatchedtotal_input_sequences / benchmark_duration.AI assistance disclosure
OpenAI Codex (GPT-5) assisted with drafting the implementation and root cause analysis. Before submitting this PR, I reviewed every changed line and independently ran the test commands listed above.