[None][perf] optimize encoder-decoder PyTorch performance - #16706
[None][perf] optimize encoder-decoder PyTorch performance#16706cascade812 wants to merge 19 commits into
Conversation
Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com>
Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com>
Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com>
Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com>
Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com>
Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com>
Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com>
Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com>
Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com>
|
/bot run |
|
PR_Github #63565 [ run ] triggered by Bot. Commit: |
|
PR_Github #63565 [ run ] completed with state
|
|
/bot run |
|
PR_Github #63639 [ run ] triggered by Bot. Commit: |
|
PR_Github #63639 [ run ] completed with state
|
Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com>
|
/bot run |
|
PR_Github #63824 [ run ] triggered by Bot. Commit: |
|
PR_Github #63824 [ run ] completed with state
|
Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com>
|
/bot run |
|
PR_Github #63867 [ run ] triggered by Bot. Commit: |
|
PR_Github #63867 [ run ] completed with state
|
|
/bot run |
|
PR_Github #63967 [ run ] triggered by Bot. Commit: |
pengbowang-nv
left a comment
There was a problem hiding this comment.
Attention part change LGTM
|
PR_Github #63967 [ run ] completed with state
|
Shixiaowei02
left a comment
There was a problem hiding this comment.
The greedy fast path doesn't screen out requests carrying penalties, so the penalty step is skipped for them. Disaggregated generation servers run almost entirely single-beam greedy decode, so they'd hit this on nearly every step.
mikeiovine
left a comment
There was a problem hiding this comment.
Mostly looks good, the penalty issue is the only blocker
Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com>
…-perf Signed-off-by: Guiju Zhang <7135567+cascade812@users.noreply.github.com> # Conflicts: # tensorrt_llm/_torch/pyexecutor/cuda_graph_runner.py
|
/bot run --disable-fail-fast |
|
PR_Github #64122 [ run ] triggered by Bot. Commit: |
Summary
Why
BART continuous-admission serving repeatedly mixes replacement encoder requests with active decoder requests. The existing path launched small encoder batches, rebuilt mixed decoder metadata in Python, and reconstructed sampling/finish metadata on every greedy decode step. It also ran eligible encoder and mixed decoder work eagerly instead of replaying fixed-shape CUDA graphs.
These changes reduce per-iteration CPU launch and device-to-host overhead while keeping decoder generation active during encoder admission. The CUDA-graph capture layout is derived from the encoder runner's effective capture keys so padding and runtime replay use the same buckets.
User interface
For encoder-decoder models,
encoder_cuda_graph_config=EncodeCudaGraphConfig(...)enables encoder-forward CUDA graphs and defines batch-size, total packed-token, and maximum sequence-length buckets.encoder_max_batch_sizeremains the hard encoder capacity and admission limit.enable_encoder_decoder_mixed_cuda_graphcontrols the mixed-batch decoder optimization. It defaults toTruebut becomes effective only when both the encoder and decoder graph configurations produce usable capture shapes. Set it toFalseto retain separate encoder and decoder CUDA graphs while disabling mixed-batch graphs.Performance
BART-large-CNN
This comparison uses the same deterministic natural-length CNN/DailyMail workload on both backends: 1,024 unique validation articles sampled without replacement using seed 0, encoder lengths of 93–1,022 tokens, and no truncation.
PyTorch improves throughput by 12.7–20.9% and reduces mean latency by 11.0–17.2% compared with legacy TensorRT.
More BART workload, latency, distribution, and configuration details
Detailed latency percentiles
Encoder input-length distribution
Lengths include the tokenizer's special tokens.
Configuration
PyTorch configuration:
encoder_max_batch_size=2at concurrency 8 and8at concurrency 32/64[1, 2]at concurrency 8 and[1, 2, 4, 8]at concurrency 32/64[512, 1024]Legacy TensorRT configuration:
Generated outputs were not bit-identical: PyTorch averaged approximately 73.37 output tokens per request, while legacy TensorRT averaged 72.32–72.41. Latency and throughput are end-to-end request measurements and are not normalized to identical output-token counts.
FLAN-T5 Large
This comparison uses
google/flan-t5-largeand a deterministic 1,024-request Super-NaturalInstructions workload derived from the officialallenai/natural-instructionsdefault/testsplit. Inputs longer than 512 tokens and reference outputs longer than 128 tokens are rejected rather than truncated.With encoder and mixed encoder-decoder CUDA graphs enabled, PyTorch improves request throughput by 11.8–57.8% and reduces mean latency by 9.4–36.6% compared with legacy TensorRT.
More T5 workload, latency, output-check, and configuration details
Each result is one clean run of 1,024 requests after an untimed warmup of one concurrency-sized request window. Timing covers closed-loop request submission through receipt of the final output.
Detailed throughput and latency measurements
Output checks
Both APIs used greedy decoding with a maximum of 128 generated tokens. The benchmark normalizes the legacy decoder-start and EOS conventions before counting or hashing outputs.
An eight-request encoder-graph smoke test produced exactly the same greedy token sequences as eager execution. Full-run cross-backend token counts differ by at most 34 tokens (0.36%) because BF16 execution and batching change a small number of near-tie decoding decisions. This is a performance benchmark, not a task-accuracy evaluation.
Workload
Prompts use the following form:
Selection is deterministic with seed 0:
google/flan-t5-largetokenizerThe final workload covers 116 test tasks and 12 task categories. During selection, 7,086 candidate instances were rejected for exceeding 512 input tokens and five were rejected for exceeding 128 reference-output tokens.
Encoder input-length distribution
Reference output-length distribution
Configuration
google/flan-t5-large, TP=1, PP=1PyTorch decoder CUDA graph batch sizes:
PyTorch encoder CUDA graph buckets:
Mixed encoder-decoder CUDA graphs are enabled, with encoder-token buckets derived from the encoder runner's captured keys. At concurrency 64, the encoder batch-eight capture bucket is omitted because the full relative-attention layout set exceeds the 80 GB GPU during capture; encoder admission therefore uses batch-four microbatches.
The legacy TensorRT path reuses one BF16 encoder/decoder engine pair built with maximum batch size 64:
Both legacy engines use BF16 BERT-attention, GPT-attention, and GEMM plugins with input-padding removal enabled. Context FMHA is disabled because the legacy T5 implementation does not support T5 relative attention bias through that path.
Encoder CUDA graph correctness validation
Before the relative-position correction, graph replay reused relative-position bias from capture instead of rebuilding it for replayed sequence lengths. For the same eight greedy requests, that produced 158 tokens, seven EOS stops, and one 128-token length stop, versus the eager reference's 32 tokens, eight EOS stops, and no length stops.
After the fix, the graph-enabled smoke run exactly matches eager execution: 32 generated tokens, eight EOS stops, and no length stops. All three full graph-enabled runs also have the expected 1,021 natural EOS stops and three length stops.
Validation
Dev Engineer Review
encoder_cuda_graph_configandenable_encoder_decoder_mixed_cuda_graph.QA Engineer Review
TorchLlmArgstests for encoder graph configuration validation and mixed-graph settings.l0_h100.yml: adds BART and T5 continuous-admission tests.l0_dgx_h100.yml: adds the two-GPU BART continuous-admission test.l0_l40s.yml: removes the superseded T5 mixed-context test.