Async patch load with GPU support
This commit is contained in:
@@ -76,6 +76,7 @@ class LoraLoaderGGUFModelOnly:
|
||||
"model": ("MODEL",),
|
||||
"lora_name": (folder_paths.get_filename_list("loras"), ),
|
||||
"strength_model": ("FLOAT", {"default": 1.0, "min": -100.0, "max": 100.0, "step": 0.01}),
|
||||
"lora_on_gpu": ("BOOLEAN", {"default": True}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +85,7 @@ class LoraLoaderGGUFModelOnly:
|
||||
CATEGORY = "bootleg"
|
||||
TITLE = "LoRA Loader Model Only (GGUF)"
|
||||
|
||||
def load_lora(self, model, lora_name, strength_model):
|
||||
def load_lora(self, model, lora_name, strength_model, lora_on_gpu):
|
||||
if strength_model == 0:
|
||||
return (model,)
|
||||
|
||||
@@ -102,6 +103,26 @@ class LoraLoaderGGUFModelOnly:
|
||||
lora = comfy.utils.load_torch_file(lora_path, safe_load=True)
|
||||
self.loaded_lora = (lora_path, lora)
|
||||
|
||||
# This is a super hacky method to get it to load alongside the model
|
||||
param_dict_name = f"lora_state_dict"#_{lora_name}".replace('.', '_')
|
||||
target_model = model.model.diffusion_model
|
||||
if lora_on_gpu:
|
||||
print(f"WARNING! Loading the LoRA to GPU memory may cause OOM issues or memory leaks!")
|
||||
temp = {}
|
||||
params = torch.nn.ParameterDict()
|
||||
for k,v in lora.items():
|
||||
param = torch.nn.Parameter(v, requires_grad=False)
|
||||
temp[k] = param
|
||||
params[k.replace('.', '_')] = param
|
||||
params.to(model.load_device, dtype=torch.float16)
|
||||
target_model.register_module(param_dict_name, params)
|
||||
lora = temp
|
||||
else:
|
||||
params = getattr(target_model, param_dict_name, None)
|
||||
if params:
|
||||
params.to("cpu", dtype=torch.float16)
|
||||
delattr(target_model, param_dict_name)
|
||||
|
||||
model_lora = load_lora_gguf(model, lora, strength_model)
|
||||
return (model_lora,)
|
||||
|
||||
|
||||
@@ -83,12 +83,33 @@ class GGMLLayer(torch.nn.Module):
|
||||
super()._apply(fn)
|
||||
return self
|
||||
|
||||
def move_patch_to_cuda(self, item, device):
|
||||
if isinstance(item, torch.Tensor):
|
||||
return item.to(device, non_blocking=True)
|
||||
elif isinstance(item, tuple):
|
||||
return tuple(self.move_patch_to_cuda(x, device) for x in item)
|
||||
elif isinstance(item, list):
|
||||
return [self.move_patch_to_cuda(x, device) for x in item]
|
||||
else:
|
||||
return item
|
||||
|
||||
def get_weight(self, tensor, dtype):
|
||||
if tensor is None:
|
||||
return
|
||||
|
||||
# consolidate and load patches to GPU in async
|
||||
patch_list = []
|
||||
device = tensor.device
|
||||
t_move = lambda x: x.to(device) if torch.is_tensor(x) else x
|
||||
for function, patches, _ in getattr(tensor, "patches", []):
|
||||
patch_list += self.move_patch_to_cuda(patches, device)
|
||||
|
||||
# dequantize tensor while patches load
|
||||
weight = dequantize_tensor(tensor, dtype)
|
||||
for function, patches, key in getattr(tensor, "patches", []):
|
||||
weight = function(patches, weight, key)
|
||||
|
||||
# apply patches
|
||||
if patch_list:
|
||||
weight = function(patch_list, weight, "dequant.name.unknown")
|
||||
return weight
|
||||
|
||||
def get_weights(self, dtype=torch.float16):
|
||||
|
||||
Reference in New Issue
Block a user