Repository navigation
[Fix] Don't retain the last tensor in layout-dynamic DLPack fills - #1321
Merged
sjfeng1999 merged 2 commits intoOct 28, 2026
Merged
Conversation
4 of 10 tasks
josh-schell-amd
marked this pull request as ready for review
October 23, 2026 17:18
sjfeng1999
approved these changes
Oct 26, 2026
DLTensorJitArg's layout-dynamic __c_abi_spec__ passes the per-launch DLTensorAdaptor from the pointer fill to the layout fill through a thread-local, but never clears it. The fills live as long as the cached CallState, and the adaptor keeps the tensor alive, so every layout-dynamic from_dlpack argument pins its most recent launch's tensor until the next launch replaces it. In AITER's gfx950 A16W16 GEMM this pinned 10.6 GiB (A + C of a 768000-row ViT projection run once during vLLM's encoder profiling), which vLLM then counted as persistent memory, shrinking the KV cache by 7.4 GiB on MiniMax-M3 (MI355X). Clear the thread-local in the layout fill once it has been read. Co-Authored-By: Claude <noreply@anthropic.com>
josh-schell-amd
force-pushed
the
fix/dlpack-layout-fill-retains-tensor
branch
from
October 26, 2026 16:48
203d2c4 to
8fdabcb
Compare
coderfeli
approved these changes
Oct 27, 2026
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.
Motivation
In the layout-dynamic
from_dlpackpath,DLTensorJitArg.__c_abi_spec__hands the launch'sDLTensorAdaptorfrom the pointer fill to the layout fill via a thread-local (_shared.dladaptor, added in #682) and never clears it. The fills live as long as the cachedCallState, so each such argument keeps its last launch's tensor alive until the next launch.In AITER's gfx950 A16W16 GEMM (ROCm/aiter#6853), whose arguments use layout-dynamic
from_dlpack, FlyDSL kept each launch's input and output tensors alive after the launch. During startup, vLLM runs MiniMax-M3's vision-encoder projection once with 768000 rows (input 768000×1280, output 768000×6144). FlyDSL held on to that input (1.8 GiB) and output (8.8 GiB) after vLLM had freed them, so 10.6 GiB stayed allocated, and vLLM's KV cache came out 7.4 GiB smaller on MI355X. The static-layoutfrom_dlpackpath andfrom_torch_tensor(TorchTensorJitArg) don't keep tensors alive, so this looks unintended.Technical Details
jit_argument.py: the layout fill clears_shared.dladaptorafter reading it. The handoff and slot order are unchanged; the cost is one attribute store per layout-dynamic argument per launch.test_callstate_dispatch.py: new test runs both fills on a CPU tensor, drops the tensor, and asserts a weakref to it is dead.The retained reference was never a keepalive for in-flight kernels (it covered only the last launch per thread), so stream safety is unchanged.
Test Plan
pytest tests/unit/test_callstate_dispatch.pyagainst FlyDSL 0.4.0 (identical code for this function) with and without the change; black and ruff on the changed files. GPU check on MI355X: torchmemory_reserved()after the AITER GEMM above, thendel+empty_cache().Test Result
test_callstate_dispatch.pytest_launch_overhead.pynot run.Submission Checklist
AI-assisted (Claude Code); results were run and checked on MI355X.
🤖 Generated with Claude Code