Release mm features on session close and support multiple /rerun-ut specs (#21501)
This commit is contained in:
@@ -366,6 +366,11 @@ class MultimodalInputs:
|
||||
mrope_position_delta: Optional[torch.Tensor] = None
|
||||
mrope_position_delta_repeated_cache: Optional[torch.Tensor] = None
|
||||
|
||||
def release_features(self):
|
||||
"""Release feature tensors to free GPU memory."""
|
||||
for item in self.mm_items:
|
||||
item.feature = None
|
||||
|
||||
@staticmethod
|
||||
def from_dict(obj: dict):
|
||||
# Check if MM splitting is enabled
|
||||
|
||||
@@ -1674,8 +1674,7 @@ class Scheduler(
|
||||
if req.session:
|
||||
continue
|
||||
# For non-session requests, clear features and mm_inputs
|
||||
for item in mm_inputs.mm_items:
|
||||
item.feature = None
|
||||
mm_inputs.release_features()
|
||||
req.multimodal_inputs = None
|
||||
|
||||
def handle_generate_request(
|
||||
|
||||
@@ -438,11 +438,7 @@ class SchedulerOutputProcessorMixin:
|
||||
if req.finished():
|
||||
# delete feature to save memory
|
||||
if req.multimodal_inputs is not None and req.session is None:
|
||||
for mm_item in req.multimodal_inputs.mm_items:
|
||||
pixel_values = mm_item.feature
|
||||
if isinstance(pixel_values, torch.Tensor):
|
||||
mm_item.feature = None
|
||||
del pixel_values
|
||||
req.multimodal_inputs.release_features()
|
||||
self.maybe_collect_routed_experts(req)
|
||||
|
||||
if self.server_args.disaggregation_decode_enable_offload_kvcache:
|
||||
|
||||
@@ -169,7 +169,14 @@ class Session:
|
||||
if req.mm_inputs:
|
||||
for item in req.mm_inputs.get("mm_items", []):
|
||||
if item.offsets:
|
||||
item.offsets = [(s - 1, e - 1) for s, e in item.offsets]
|
||||
if any(s == 0 for s, _ in item.offsets):
|
||||
logging.warning(
|
||||
"mm_item offset starts at 0 (BOS position), "
|
||||
"clamping to 0 after BOS strip"
|
||||
)
|
||||
item.offsets = [
|
||||
(max(0, s - 1), max(0, e - 1)) for s, e in item.offsets
|
||||
]
|
||||
|
||||
input_ids = (
|
||||
last_req.origin_input_ids
|
||||
@@ -284,6 +291,18 @@ class SessionController:
|
||||
req = next(iter(session.req_nodes.values())).req
|
||||
if not req.finished():
|
||||
req.session = None
|
||||
|
||||
# Release multimodal features held by session requests.
|
||||
# Session reqs skip the normal mm cleanup path (scheduler and
|
||||
# output_processor) so features stay alive until the session closes.
|
||||
seen_mm = set()
|
||||
for node in session.req_nodes.values():
|
||||
mm = node.req.multimodal_inputs
|
||||
if mm is not None and id(mm) not in seen_mm:
|
||||
seen_mm.add(id(mm))
|
||||
mm.release_features()
|
||||
node.req.multimodal_inputs = None
|
||||
|
||||
if isinstance(self.tree_cache, SessionAwareCache):
|
||||
self.tree_cache.release_session(session_id)
|
||||
del self.sessions[session_id]
|
||||
|
||||
Reference in New Issue
Block a user