mirror of
https://github.com/Comfy-Org/ComfyUI_Nvidia_VFX_Nodes.git
synced 2026-11-04 23:37:30 +00:00
[PR #38] Reduce memory pressure and fix DLPack lifetime in RTX VSR #42
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/ComfyUI_Nvidia_VFX_Nodes#42
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/ComfyUI_Nvidia_VFX_Nodes/pull/38
Author: @xmarre
Created: 8/22/2026
Status: 🔄 Open
Base:
main← Head:upstream/reduce-rtx-vsr-memory-pressure📝 Commits (1)
46ffadbReduce RTX VSR memory pressure and fix DLPack lifetime📊 Changes
2 files changed (+144 additions, -20 deletions)
View changed files
📝
README.md(+14 -2)📝
__init__.py(+130 -18)📄 Description
Summary
This reduces memory pressure in long/high-resolution
RTX Video Super Resolutionworkflows and fixes the NVVFX DLPack output lifetime without adding per-frame CUDA allocator flushes.The change is intentionally limited to the existing RTX VSR node and its README documentation.
Problems addressed
The current implementation has three separate memory/lifetime costs:
IMAGEtensor is allocated onimages.device. In normal CPU-backed ComfyUI image chains, that materializes the entire upscaled video in system RAM even when the next consumer can accept a CUDAIMAGEtensor.VideoSuperRes.run()returns DLPack-backed storage owned by NVVFX. The frame must establish PyTorch-owned storage before that effect-owned buffer can be reused or torn down. This is the lifetime issue tracked in #35 and targeted by #36.For video chains that already perform a latent spatial upscale before VSR, the final pixel tensor can become very large. A 2x latent spatial upscale followed by 2x VSR produces 16x the original pixel count, so unnecessarily retaining another complete float32 RGB video in host memory can mean tens of GiB.
Changes
.to(...).contiguous()chain that can require two CUDA temporaries.run().copy_, including device/dtype conversion, avoiding another full-frameoutput_frame.to(...)temporary.torch.cuda.empty_cache()per frame. Released PyTorch blocks remain reusable by the caching allocator without forcing a synchronization/allocation cycle every frame. This incorporates the outstanding review feedback on #36.output_devicecontrol:auto(default): keep the full result on CUDA only when current free VRAM can hold the output, peak per-frame scratch, and conservative headroom; otherwise use CPU.cuda: explicitly keep the complete result in VRAM.cpu: explicitly keep the complete result in system RAM.autoonly afterVideoSuperRes.load()so NVVFX resident allocations are already reflected in the free-VRAM measurement.auto: one float32 input frame plus the simultaneously-live NVVFX float32 output and owned float32 clone, in addition to the complete returned tensor and conservative headroom.IMAGEtensor.[frames, height, width, channels]contract and preserve empty inputs.Compatibility
nvvfx.VideoSuperResremains the inference backend.IMAGEtensor.output_deviceis appended to the schema andexecute()supplies a default, so existing workflows that do not serialize the new input continue to have a valid call signature.VideoHelperSuite's current standard FFmpeg path iterates the
IMAGEtensor frame by frame and converts each frame to CPU before writing it to FFmpeg. That path therefore does not require a second complete floating-point host tensor when this node returns CUDA output. Formats that require a pre-pass may retain encoded frame bytes separately.Validation
main(892515e3, v0.1.3); the PR branch is exactly one commit ahead with no upstream drift.copy_/contiguous-copy behavior used by the final implementation.This includes the core owned-DLPack fix from #36 while also addressing the independent host-memory and batch-staging pressure. It deliberately omits #36's per-frame
torch.cuda.empty_cache()because that call was also flagged in review as unnecessary allocator churn.Closes #35.
Addresses #16.
Related: #36.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.