Nodes/ComfyUI-LoopedDiT/Looped-DiT Unload
ComfyUI Node

Looped-DiT Unload

The one node ComfyUI's memory manager can't replace

By hiroki-abe-58·Created 14 days ago·Updated 14 days ago· 0
Looped-DiT Unload
  • after
  • report

Most of the time you don't need this node. You load a model, you generate, ComfyUI decides when to page things out, and life goes on. Looped-DiT is the exception, and the README says so without dressing it up: ComfyUI's memory manager does not know about this model. It isn't loaded through ComfyUI's own model classes, so the usual free-memory behaviour - the stuff that quietly evicts a checkpoint when you queue a different workflow - never touches it.

So when you're done with Looped-DiT and want your VRAM back for something else, there's nothing in stock ComfyUI that will do it for you. That's the gap this node fills.

What it does

It drops the pack's resident model slot, runs a garbage collection, and empties the CUDA cache. That's it - it's a one-job utility, and it's honest about it. You get a report string back telling you what happened:

  • unloaded - whether there was actually anything to free,
  • was - the info block of the model that was resident (checkpoint file, T5 release, device, config), or null if the slot was already empty,
  • cuda_allocated_mib - PyTorch's view of allocated CUDA memory right after the free.

Read it, because it's the only feedback you'll get. "unloaded": false with "was": null means nothing was resident - your graph was already clean and the node did nothing. "unloaded": true is the pack confirming it let go.

The node also displays that report directly on its own face, so you don't need a Show Text node just to see the numbers. If you want the JSON recorded somewhere permanent, wire the output into Show Text anyway.

The optional input, and why it exists

There's one input, after, and it takes an IMAGE. It's not there to be processed - it takes the image and does nothing with it. Its only job is to give you a wire to hang the unload node off, so it runs after your Save Image rather than in parallel with your generation. Without it, an unload node that has no inputs and no dependencies is free to execute at whatever point ComfyUI feels like, including before your sampler has finished with the model.

So the wiring for "generate, save, then free everything" is: Generate's image into Save Image, and the same image into Unload's after. Because Unload is an output node, it runs as part of the queue and isn't treated as dead code.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/hiroki-abe-58/ComfyUI-LoopedDiT
python custom_nodes/ComfyUI-LoopedDiT/tools/download_models.py --models-dir models

Restart, and the node shows up under loaders/looped-dit. Nothing to pip install - the pack has no dependency of its own - but you do need ComfyUI 0.38.0 or newer, and a CUDA GPU, since the whole pack is CUDA-only.

Where it goes wrong

Putting it between the loader and the generator. Don't. The next Generate call will simply reload the model - around 1.7 seconds for the checkpoint, 1.5 for the T5, plus the SHA-256 pass on first use if hash verification is on. You'll pay that on every queue and wonder why the graph is slow. Unload is for the end of a chain, not the middle.

Expecting it to persist. It's non-idempotent by design: every queue re-runs it. So if you unload at the end of a graph and then hit queue again, you're back to a cold load. That's the correct behaviour for its purpose and the wrong thing to leave in a graph you run repeatedly.

Expecting it to free what isn't loaded. The report's was: null is your diagnostic. If you never queued a Generate, nothing was resident, and there was never any VRAM to reclaim.

Treating it as a general VRAM fix. It frees Looped-DiT and only Looped-DiT. If a video model is sitting in memory, this node doesn't know or care. The genuine use case is narrow and real: you've finished comparing loop depths on a 12GB card and you want the card back for a Wan render. That's exactly the moment to drag this node in.

Categoryloaders/looped-dit

Inputs (1)

NameTypeDefaultDescription
afteroptIMAGEOptional: connect an image so this runs after it

Outputs (1)

NameTypeDescription
reportSTRING—