Repository navigation
Conversation
_get_buffers keeps the prefill scratch for at most _BUF_CACHE_MAX_ENTRIES token-count shapes and evicts the oldest entry on a new shape. The K123 and akk_inv launches wrapped that scratch with _ct_cached, whose id-keyed _input_wrap_cache holds each wrapper until the wrapped tensor is garbage collected. The wrapper's DLPack capsule keeps the tensor alive, so that never happens: every evicted entry's scratch stayed allocated. A server whose prefill batches keep changing token count grows by one entry's scratch per eviction (GSM8K on Kimi K3: about 500 MiB per 200 requests on every rank). Cache the scratch wrappers in the scratch's own _buf_cache entry instead (_scratch_ct), so evicting the entry releases the scratch and its wrappers together; the per-call from_dlpack savings stay. _ct_cached and _input_wrap_cache have no other users and are removed. Test: test_evicted_prefill_scratch_is_released runs cyclic passes over more token-count shapes than the cache holds. After every later pass the cache holds at most _BUF_CACHE_MAX_ENTRIES entries, the allocated bytes are back at their value after the first pass, and the tensors of an entry cached at the end of the first pass, which the next pass evicts, are freed. Signed-off-by: Vasanth Sabavat <vsabavat@nvidia.com>
1 task done
Collaborator
Author
|
Superseded by the consolidated draft PR: #19988. Source commits and follow-ups are retained; prior reviews remain historical evidence, not approval of the replacement heads. |
1 task done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The Kimi K3 KDA prefill op (
tensorrt_llm/_torch/custom_ops/cute_dsl_kimi_k3_custom_ops.py) caches its intermediatebuffers per token-count shape in
_buf_cache. That is an LRU of at most_BUF_CACHE_MAX_ENTRIES(8) entries; a newshape evicts the oldest entry. In serving, most prefill batches bring a new token count, so entries are evicted all
the time.
The K123 and
akk_invlaunches wrapped seven of those buffers (k_scaled,kg,q_scaled,beta_activated,gk_last_exp,A_qk,A_kk) with_ct_cached._ct_cachedkept each CuTe wrapper in a module-level dict keyed byid(tensor), and relied on aweakref.finalizeon the tensor to drop the wrapper.from_dlpackholds a DLPack capsule, which owns a reference to the tensor. The tensor is nevercollected, so the finalizer never runs.
scratch cache.
Impact: GPU memory grows without bound whenever prefill shapes vary, by about 1 KiB per token per KDA head for every
evicted shape.
per rank.
gc.collect()reclaims none of it.The fix:
_scratch_ctcaches each buffer's wrapper in thecute_wrappersdict of that buffer's own_buf_cacheentry, soevicting the entry releases the buffers and their wrappers together.
from_dlpack._ct_cachedand its dict have no other users and are removed.This PR and #19835 (a new prefill output tensor per call) change different lines of the module and apply in either
order.
Test Coverage
tests/unittest/_torch/modules/kimi_kda/test_kda_cache_soundness.py(inl0_b200.yml):test_evicted_prefill_scratch_is_released(one GPU): runs indexed varlen prefill in cyclic passes over 12 tokencounts. The cache holds 8, so every call misses and evicts.
torch.cuda.memory_allocated()is within 16 MiB of its value after the first pass.(their weak references are dead).
Results
One GB200 GPU, the whole test file, with the module as on main at cf5dc9f and with this PR:
test_recycled_cu_seqlens_id_matches_fla("could not obtain a recycled cu_seqlens tensor ID"),the same before and after.
End to end, Kimi K3 at TP16 (16 GB200 GPUs) serving GSM8K-200 five times on one LLM instance:
torch.cuda.memory_allocated()on every rank stays within 0.3 GiB of its round-1 value over the fiverounds, with no trend (the minimum over ranks is 112,562-112,569 MiB).
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. (No API change.)Any new dependencies have been scanned for license and vulnerabilities (No new dependencies.)
CODEOWNERS updated if ownership changes (No ownership change.)
Documentation updated as needed (No user-facing change.)
Update tava architecture diagram if there is a significant design change in PR. (No design change.)
The reviewers assigned automatically/manually are appropriate for the PR. (To check once the PR is open.)
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.