Load weights to process RAM with MRU policy using pinning infrastruct… · code/app-python-comfyui@c011755 · GitHub
Skip to content

Commit c011755

Browse files
authored
Load weights to process RAM with MRU policy using pinning infrastructure (Comfy-Org#15027)
1 parent 3d41e3e commit c011755

7 files changed

Lines changed: 209 additions & 94 deletions

File tree

‎comfy/model_management.py‎

Lines changed: 55 additions & 32 deletions

‎comfy/model_patcher.py‎

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,52 @@
4242

4343
import comfy_aimdo.model_vbar
4444

45+
def is_model_patcher_output(output):
46+
return isinstance(output, ModelPatcher) or isinstance(getattr(output, "patcher", None), ModelPatcher)
47+
48+
class PromptModelTracker:
49+
def __init__(self):
50+
self.models = {}
51+
52+
def start(self):
53+
self.end()
54+
55+
def add(self, outputs):
56+
if isinstance(outputs, collections.abc.Mapping):
57+
outputs = outputs.values()
58+
elif not isinstance(outputs, (list, tuple)):
59+
outputs = (outputs,)
60+
61+
for output in outputs:
62+
if isinstance(output, (collections.abc.Mapping, list, tuple)):
63+
self.add(output)
64+
continue
65+
66+
models = []
67+
if isinstance(output, ModelPatcher):
68+
models.append(output)
69+
models.extend(output.model_patches_models())
70+
models.extend(output.get_nested_additional_models())
71+
else:
72+
patcher = getattr(output, "patcher", None)
73+
if isinstance(patcher, ModelPatcher):
74+
models.append(patcher)
75+
get_models = getattr(output, "get_models", None)
76+
if callable(get_models):
77+
models.extend(get_models())
78+
79+
for model in models:
80+
if not isinstance(model, ModelPatcher) or not model.is_dynamic():
81+
continue
82+
key = (id(model.model), model.load_device)
83+
self.models[key] = model
84+
model.set_in_use_by_current_prompt(True)
85+
86+
def end(self):
87+
for model in self.models.values():
88+
model.set_in_use_by_current_prompt(False)
89+
self.models.clear()
90+
4591
def set_model_options_patch_replace(model_options, patch, name, block_name, number, transformer_index=None):
4692
to = model_options["transformer_options"].copy()
4793

@@ -1724,14 +1770,20 @@ def register_load_device(self, device):
17241770
self.model.dynamic_pins[device] = {
17251771
"weights": (comfy_aimdo.host_buffer.HostBuffer(0, 0, 0), [], [-1], [0], [0], {}),
17261772
"patches": (comfy_aimdo.host_buffer.HostBuffer(0, 0, 0), [], [-1], [0], [0], {}),
1773+
"weights-loaded": (comfy_aimdo.host_buffer.HostBuffer(0, 0, 0), [], [-1], [0], [0], {}),
1774+
"patches-loaded": (comfy_aimdo.host_buffer.HostBuffer(0, 0, 0), [], [-1], [0], [0], {}),
17271775
"hostbufs_initialized": False,
17281776
"failed": False,
17291777
"active": False,
1778+
"current_prompt": False,
17301779
}
17311780

17321781
def is_dynamic(self):
17331782
return True
17341783

1784+
def set_in_use_by_current_prompt(self, in_use):
1785+
self.model.dynamic_pins[self.load_device]["current_prompt"] = in_use
1786+
17351787
def _vbar_get(self, create=False):
17361788
if self.load_device == torch.device("cpu"):
17371789
return None
@@ -1802,6 +1854,8 @@ def load(self, device_to=None, lowvram_model_memory=0, force_patch_weights=False
18021854
hostbuf_size = comfy.model_management.pinned_hostbuf_size(self.model_size())
18031855
pin_state["weights"] = (comfy_aimdo.host_buffer.HostBuffer(0, 64 * 1024 * 1024, hostbuf_size), [], [-1], [0], [0], {})
18041856
pin_state["patches"] = (comfy_aimdo.host_buffer.HostBuffer(0, 8 * 1024 * 1024, hostbuf_size), [], [-1], [0], [0], {})
1857+
pin_state["weights-loaded"] = (comfy_aimdo.host_buffer.HostBuffer(0, 64 * 1024 * 1024, hostbuf_size), [], [-1], [0], [0], {})
1858+
pin_state["patches-loaded"] = (comfy_aimdo.host_buffer.HostBuffer(0, 8 * 1024 * 1024, hostbuf_size), [], [-1], [0], [0], {})
18051859
pin_state["hostbufs_initialized"] = True
18061860
pin_state["failed"] = False
18071861
pin_state["active"] = True
@@ -1943,28 +1997,32 @@ def partially_unload(self, device_to, memory_to_free=0, force_patch_weights=Fals
19431997
return freed
19441998

19451999
def loaded_ram_size(self):
1946-
return (self.model.dynamic_pins[self.load_device]["weights"][0].size)
2000+
pin_state = self.model.dynamic_pins[self.load_device]
2001+
return pin_state["weights"][0].size + pin_state["weights-loaded"][0].size
19472002

19482003
def pinned_memory_size(self):
1949-
return (self.model.dynamic_pins[self.load_device]["weights"][3][0])
2004+
pin_state = self.model.dynamic_pins[self.load_device]
2005+
return pin_state["weights"][3][0] + pin_state["weights-loaded"][3][0]
19502006

1951-
def unregister_inactive_pins(self, ram_to_unload, subsets=[ "weights", "patches" ]):
2007+
def unregister_inactive_pins(self, ram_to_unload, subsets=[ "weights-loaded", "patches-loaded", "weights", "patches" ]):
19522008
freed = 0
19532009
pin_state = self.model.dynamic_pins[self.load_device]
19542010
for subset in subsets:
19552011
hostbuf, stack, stack_split, pinned_size, *_ = pin_state[subset]
19562012
split = stack_split[0]
19572013
while split >= 0:
19582014
module, offset = stack[split]
2015+
module_pin = module._pins[subset]
19592016
split -= 1
19602017
stack_split[0] = split
1961-
if not module._pin_registered:
2018+
if not module_pin["registered"]:
19622019
continue
1963-
size = module._pin.numel() * module._pin.element_size()
1964-
if torch.cuda.cudart().cudaHostUnregister(module._pin.data_ptr()) != 0:
2020+
pin = module_pin["pin"]
2021+
size = pin.numel() * pin.element_size()
2022+
if torch.cuda.cudart().cudaHostUnregister(pin.data_ptr()) != 0:
19652023
comfy.model_management.discard_cuda_async_error()
19662024
continue
1967-
module._pin_registered = False
2025+
module_pin["registered"] = False
19682026
comfy.model_management.TOTAL_PINNED_MEMORY = max(0, comfy.model_management.TOTAL_PINNED_MEMORY - size)
19692027
pinned_size[0] = max(0, pinned_size[0] - size)
19702028
freed += size
@@ -1973,20 +2031,23 @@ def unregister_inactive_pins(self, ram_to_unload, subsets=[ "weights", "patches"
19732031
return freed
19742032
return freed
19752033

1976-
def partially_unload_ram(self, ram_to_unload, subsets=[ "weights", "patches" ]):
2034+
def partially_unload_ram(self, ram_to_unload, subsets=[ "weights-loaded", "patches-loaded", "weights", "patches" ]):
19772035
freed = 0
19782036
pin_state = self.model.dynamic_pins[self.load_device]
19792037
for subset in subsets:
19802038
hostbuf, stack, stack_split, pinned_size, *_ = pin_state[subset]
19812039
while len(stack) > 0:
19822040
module, offset = stack.pop()
1983-
size = module._pin.numel() * module._pin.element_size()
1984-
module._pin_balancer_entry[-1] = None
1985-
del module._pin_balancer_entry
1986-
del module._pin
1987-
hostbuf.truncate(offset, do_unregister=module._pin_registered)
2041+
module_pin = module._pins[subset]
2042+
pin = module_pin["pin"]
2043+
size = pin.numel() * pin.element_size()
2044+
module_pin["balancer_entry"][-1] = None
2045+
del module_pin["balancer_entry"]
2046+
del module_pin["pin"]
2047+
registered = module_pin["registered"]
2048+
hostbuf.truncate(offset, do_unregister=registered)
19882049
stack_split[0] = min(stack_split[0], len(stack) - 1)
1989-
if module._pin_registered:
2050+
if registered:
19902051
comfy.model_management.TOTAL_PINNED_MEMORY = max(0, comfy.model_management.TOTAL_PINNED_MEMORY - size)
19912052
pinned_size[0] = max(0, pinned_size[0] - size)
19922053
freed += size

‎comfy/ops.py‎

Lines changed: 19 additions & 6 deletions

0 commit comments

Comments
 (0)