-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path__init__.py
More file actions
77 lines (61 loc) · 2.25 KB
/
Copy path__init__.py
File metadata and controls
77 lines (61 loc) · 2.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
"""
ComfyUI-PipelineBarrier — force-flush GPU caches between pipeline stages.
Inserts an explicit GPU cache flush and GC pass into a ComfyUI workflow graph.
Useful in multi-stage or multi-GPU pipelines (e.g. WanVideo two-pass sampling)
where model offload alone does not fully release GPU and CPU memory before the
next stage begins, leading to OOM kills.
"""
import gc
import psutil
import torch
import comfy.model_management as mm
def _log_memory(label: str) -> None:
for i in range(torch.cuda.device_count()):
alloc = torch.cuda.memory_allocated(i) / 1024**3
rsvd = torch.cuda.memory_reserved(i) / 1024**3
print(
f"[PipelineBarrier] {label} | GPU {i}: "
f"alloc={alloc:.2f} GiB reserved={rsvd:.2f} GiB"
)
vm = psutil.virtual_memory()
print(
f"[PipelineBarrier] {label} | RAM: "
f"{vm.used / 1024**3:.1f}/{vm.total / 1024**3:.1f} GiB ({vm.percent:.0f}% used)"
)
def _flush() -> None:
mm.soft_empty_cache(force=True)
gc.collect()
for i in range(torch.cuda.device_count()):
with torch.cuda.device(i):
torch.cuda.empty_cache()
torch.cuda.synchronize()
class PipelineMemoryBarrier:
"""Force-flush GPU caches between pipeline stages.
Pass a LATENT through this node to trigger an explicit GPU cache flush
before the next stage loads its models. Zero compute cost; useful between
samplers and before VAE decode in multi-stage workflows.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"latent": ("LATENT",),
},
"optional": {
"log_memory": ("BOOLEAN", {"default": True}),
},
}
RETURN_TYPES = ("LATENT",)
RETURN_NAMES = ("latent",)
FUNCTION = "barrier"
CATEGORY = "utils/memory"
OUTPUT_NODE = False
def barrier(self, latent, log_memory: bool = True):
if log_memory:
_log_memory("before flush")
_flush()
if log_memory:
_log_memory("after flush")
return (latent,)
NODE_CLASS_MAPPINGS = {"PipelineMemoryBarrier": PipelineMemoryBarrier}
NODE_DISPLAY_NAME_MAPPINGS = {"PipelineMemoryBarrier": "Pipeline Memory Barrier"}