Skip to content

Fix GC-cycle leak: drop frame self-references in CuTe DSL decorators - #3423

Open
thakkarV wants to merge 2 commits into
NVIDIA:mainfrom
thakkarV:fix-cutedsl-decorator-frame-leak
Open

Fix GC-cycle leak: drop frame self-references in CuTe DSL decorators#3423
thakkarV wants to merge 2 commits into
NVIDIA:mainfrom
thakkarV:fix-cutedsl-decorator-frame-leak

Conversation

@thakkarV

@thakkarV thakkarV commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Fixes #3421 and adds a regression test.

thakkarV added 2 commits July 29, 2026 18:25
`BaseDSL.jit`, `BaseDSL.kernel`, the `CuTeDSL.kernel` /
`CuteExperimentalDSL.kernel` overrides, and `DSLBaseError.__init__` bind
`inspect.currentframe()` to a local variable. A frame whose locals
reference the frame itself forms a reference cycle, so the frame can only
be reclaimed by the cyclic garbage collector -- and through `f_back` it
keeps the entire caller stack, including every frame's locals, alive
until a collection runs.

For applications that disable automatic gc (common in CUDA-graph training
loops), every `@cute.jit` / `@cute.kernel` decoration therefore leaks
whatever the calling stack held at decoration time. When kernel-bearing
modules are imported lazily inside a model's forward pass, that includes
live activation tensors: upgrading from 4.4.2 (whose decorators used the
cycle-free one-expression `inspect.currentframe().f_back` spelling) to
4.6.1 cost a measured +3-5 GiB of peak GPU memory per rank in a large
gc-disabled training job, with `CuTeDSL.kernel` frames pinning the
importing stack.

Fix by deleting the local frame reference before returning, following the
existing pattern in `_mlir_helpers/op.py:_get_caller_frame_info()`.

Minimal repro (retains 1 GiB until gc.collect() without this fix):

    import gc, torch
    import cutlass.cute as cute
    gc.disable()

    def scope():
        big = torch.randn(1 << 28, device="cuda")  # 1 GiB, local
        @cute.kernel
        def knl(): pass

    scope()
    torch.cuda.synchronize()
    print(torch.cuda.memory_allocated())  # 1 GiB before fix, 0 after
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] 4.6.1: @cute.kernel / @cute.jit decorators leak caller call stack into reference cycles - regression vs 4.4.2

1 participant