fix pin registration priority (#15226)

This priority scheme was broken in the case where you have pin
registration exhaustion while loading a VBAR that gets a big evicition.
The weight would stay in the loaded set but inherit the MRU priority
against other workflow models WRT pin registration which leads to async
offload without pinning.

Fix by universally promiting active pin registration above workflow
pins without concern for the weights/weights-loaded split. This diverges
from the actual budgeting where the split still makes sense.
This commit is contained in:
rattus 2026-08-03 01:16:06 +10:00 committed by GitHub
parent 364081170f
commit 611f2a4e0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 7 deletions

View File

@ -671,6 +671,19 @@ def pin_eviction_tiers(loaded, evict_active):
tiers.append((PIN_SUBSETS, True, True)) tiers.append((PIN_SUBSETS, True, True))
return tiers return tiers
def registration_eviction_tiers(evict_active):
subsets = PIN_SUBSETS + LOADED_PIN_SUBSETS
tiers = [
(subsets, False, False),
(subsets, True, False),
]
if evict_active:
tiers.extend([
(subsets, False, True),
(subsets, True, True),
])
return tiers
def free_pins(size, evict_active=False, loaded=False): def free_pins(size, evict_active=False, loaded=False):
freed = 0 freed = 0
for subsets, current_prompt, active in pin_eviction_tiers(loaded, evict_active): for subsets, current_prompt, active in pin_eviction_tiers(loaded, evict_active):
@ -703,19 +716,19 @@ def ensure_pin_budget(size, evict_active=False, loaded=False):
to_free = shortfall + PIN_PRESSURE_HYSTERESIS to_free = shortfall + PIN_PRESSURE_HYSTERESIS
return free_pins(to_free, evict_active=evict_active, loaded=loaded) >= shortfall return free_pins(to_free, evict_active=evict_active, loaded=loaded) >= shortfall
def free_registrations(shortfall, evict_active=True, loaded=False): def free_registrations(shortfall, evict_active=True):
if MAX_PINNED_MEMORY <= 0: if MAX_PINNED_MEMORY <= 0:
return False return False
if shortfall <= 0: if shortfall <= 0:
return True return True
shortfall += REGISTERABLE_PIN_HYSTERESIS shortfall += REGISTERABLE_PIN_HYSTERESIS
for subsets, current_prompt, active in pin_eviction_tiers(loaded, evict_active): for subsets, current_prompt, active in registration_eviction_tiers(evict_active):
shortfall -= free_model_pins(shortfall, subsets, current_prompt, active, registrations=True) shortfall -= free_model_pins(shortfall, subsets, current_prompt, active, registrations=True)
return shortfall <= REGISTERABLE_PIN_HYSTERESIS return shortfall <= REGISTERABLE_PIN_HYSTERESIS
def ensure_pin_registerable(size, evict_active=True, loaded=False): def ensure_pin_registerable(size, evict_active=True):
return free_registrations(TOTAL_PINNED_MEMORY + size - MAX_PINNED_MEMORY, evict_active=evict_active, loaded=loaded) return free_registrations(TOTAL_PINNED_MEMORY + size - MAX_PINNED_MEMORY, evict_active=evict_active)
class LoadedModel: class LoadedModel:
def __init__(self, model: ModelPatcher): def __init__(self, model: ModelPatcher):

View File

@ -56,7 +56,7 @@ def get_pin(module, subset="weights"):
_, _, stack_split, pinned_size, *_ = module._pin_state[subset] _, _, stack_split, pinned_size, *_ = module._pin_state[subset]
size = pin.nbytes size = pin.nbytes
comfy.model_management.ensure_pin_registerable(size, loaded=subset.endswith("-loaded")) comfy.model_management.ensure_pin_registerable(size)
if torch.cuda.cudart().cudaHostRegister(pin.data_ptr(), size, 1) != 0: if torch.cuda.cudart().cudaHostRegister(pin.data_ptr(), size, 1) != 0:
comfy.model_management.discard_cuda_async_error() comfy.model_management.discard_cuda_async_error()
@ -93,7 +93,7 @@ def pin_memory(module, subset="weights", size=None):
comfy.memory_management.extra_ram_release(comfy.memory_management.RAM_CACHE_HEADROOM) comfy.memory_management.extra_ram_release(comfy.memory_management.RAM_CACHE_HEADROOM)
if (not comfy.model_management.ensure_pin_budget(size, loaded=loaded) or if (not comfy.model_management.ensure_pin_budget(size, loaded=loaded) or
not comfy.model_management.ensure_pin_registerable(registerable_size, loaded=loaded)): not comfy.model_management.ensure_pin_registerable(registerable_size)):
return _steal_pin(module, stack, buckets, size, priority, subset) return _steal_pin(module, stack, buckets, size, priority, subset)
offset = hostbuf.size offset = hostbuf.size
@ -105,7 +105,7 @@ def pin_memory(module, subset="weights", size=None):
pin.untyped_storage()._comfy_hostbuf = hostbuf pin.untyped_storage()._comfy_hostbuf = hostbuf
if torch.cuda.cudart().cudaHostRegister(pin.data_ptr(), size, 1) != 0: if torch.cuda.cudart().cudaHostRegister(pin.data_ptr(), size, 1) != 0:
comfy.model_management.discard_cuda_async_error() comfy.model_management.discard_cuda_async_error()
comfy.model_management.free_registrations(size, loaded=loaded) comfy.model_management.free_registrations(size)
if torch.cuda.cudart().cudaHostRegister(pin.data_ptr(), size, 1) != 0: if torch.cuda.cudart().cudaHostRegister(pin.data_ptr(), size, 1) != 0:
comfy.model_management.discard_cuda_async_error() comfy.model_management.discard_cuda_async_error()
del pin del pin