[TRTLLM-14660][feat] Early reused cache transfer in Transceiver V2 - #18688
[TRTLLM-14660][feat] Early reused cache transfer in Transceiver V2#18688athena-nv wants to merge 2 commits into
Conversation
Signed-off-by: Athena Cai <athenac@nvidia.com>
Signed-off-by: Athena Cai <athenac@nvidia.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (5)
Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review. WalkthroughThe change adds early KV-cache prefix transfer for eligible pipelined context requests. It tracks transfer state on each request and prevents already-transferred prefixes from appearing in the first prefill chunk. ChangesKV-cache prefix transfer
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to Eligible pipelined context requests can now transfer complete reused KV-cache prefix blocks before prefill while avoiding duplicate prefix transfer. The implemented gating and coverage indicate no actionable merge-blocking risk remains. Sequence Diagram(s)sequenceDiagram
participant py_executor
participant LlmRequest
participant transceiver
py_executor->>LlmRequest: inspect reusable prefix
py_executor->>transceiver: start asynchronous prefix transfer
py_executor->>LlmRequest: set py_kv_prefix_sent
transceiver-->>py_executor: transfer completes
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Comment |
TRTLLM-14660 Early Reused Cache Transfer
Motivation
Agentic workloads commonly have:
cached ISL >> current-turn ISL >> OSLThe reused prefix therefore accounts for most of the KV cache transferred from
the context worker to the generation worker. Previously, that transfer started
after the current turn's prefill completed, placing both the large cached-prefix
transfer and the current-turn KV transfer on the critical path before decode.
This change starts transferring complete KV blocks from the reused prefix before
the first context forward. The cached-prefix transfer can then overlap with
prefill compute for the current turn. Only the KV produced by the current turn,
plus any partial boundary block, remains to be transferred after prefill.
Transfer timeline
Baseline:
sequenceDiagram participant C as Context worker participant G as Generation worker C->>C: Prefill current-turn tokens C->>G: Transfer cached-prefix KV C->>G: Transfer current-turn KV G->>G: Decode output tokensWith early reused-cache transfer:
sequenceDiagram participant C as Context worker participant G as Generation worker par Transfer reused prefix C->>G: Transfer complete cached-prefix blocks and Compute current turn C->>C: Prefill current-turn tokens end C->>G: Transfer current-turn and boundary-block KV G->>G: Decode output tokensImplementation
Before each context forward,
_send_kv_cache_earlyselects context-only,non-cancelled requests that are on their first context chunk and have a reused
prefix. It rounds
prepopulated_prompt_lendown to a KV block boundary so thatonly fully populated blocks are sent. Partial boundary blocks remain owned by
the normal prefill path because the current forward may still update them.
The request records
py_kv_prefix_sentafter dispatching the early slice. Whenthe normal first prefill chunk is later built, the transceiver checks that flag
and starts the chunk at the reuse boundary instead of block zero, preventing the
early prefix from being sent twice.
The early send is inserted into both executor scheduling paths immediately
before the context forward.
Limitation: We skip early reused cache transfer if blocks have been evicted to host memory.
We can handle this in a future PR by synchronizing the CPU Sender worker with CUDA onboard stream's onboardDone event. We did not add this synchronization because for overlap scheduler, the kv transfer of the previous batch will be blocked by waiting on onboardDone of the current batch. Benchmarking is required to understand the perf characteristics of this added synchronization.
Changes
tensorrt_llm/_torch/disaggregation/transceiver.py: first-chunk range selectionextends_to_prefix = is_first_chunk and not req.py_kv_prefix_sent; block zero is included only when the prefix was not sent early.tensorrt_llm/_torch/pyexecutor/llm_request.py: request transfer statepy_kv_prefix_sent, initialized toFalse.tensorrt_llm/_torch/pyexecutor/py_executor.py: non-overlap scheduling path_send_kv_cache_earlybefore collecting batch statistics and running the context forward.tensorrt_llm/_torch/pyexecutor/py_executor.py: overlap scheduling path_send_kv_cache_earlywhen the scheduled batch can be queued.tensorrt_llm/_torch/pyexecutor/py_executor.py:_send_kv_cache_early_send_kv_async.tests/unittest/disaggregated/test_chunked_transfer.py: early-send teststests/unittest/disaggregated/test_chunked_transfer.py: multi-chunk request fixturepy_kv_prefix_sent=False.tests/unittest/disaggregated/test_chunked_transfer.py: token-coordinate helperprefix_sentinput and assigns it to the mocked request.tests/unittest/disaggregated/test_chunked_transfer.py: block-coordinate helperprefix_sentto the token-coordinate helper.tests/unittest/disaggregated/test_chunked_transfer.py: first regular chunk after early transfertests/unittest/disaggregated/test_kv_transfer.py:_send_prefill_chunksfixturepy_kv_prefix_sent=False.tests/unittest/disaggregated/test_kv_transfer.py: whole-prompt slicing testpy_kv_prefix_sent=False.tests/unittest/disaggregated/test_kv_transfer.py: partial-SWA testpy_kv_prefix_sent=False.Added test coverage
test_send_kv_cache_early_only_sends_reused_prefixestest_send_kv_cache_early_requires_pipelined_transfertest_first_chunk_skips_prefix_already_sent_earlyValidation
c2647ec0f6.tensorrt_llm/libs/libth_common.sofailed to load; a compatible TensorRT-LLMbuild is required.
Dev Engineer Review
py_kv_prefix_sentto prevent duplicate prefix transfer.libth_common.sofailed to load.QA Engineer Review
py_kv_prefix_sent.tests/integration/test_lists/,test-db/, orqa/.libth_common.soloads successfully.Description
Test Coverage
PR Checklist
Please review the following before submitting your PR:
PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.
PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.
Test cases are provided for new code paths (see test instructions)
If PR introduces API changes, an appropriate PR label is added - either
api-compatibleorapi-breaking. Forapi-breaking, includeBREAKINGin the PR title.Any new dependencies have been scanned for license and vulnerabilities
CODEOWNERS updated if ownership changes
Documentation updated as needed
Update tava architecture diagram if there is a significant design change in PR.
The reviewers assigned automatically/manually are appropriate for the PR.
Please check this after reviewing the above items as appropriate for this PR.
GitHub Bot Help
To see a list of available CI bot commands, please comment
/bot help.