[Diffusion] Support LoRA in step-wise execution (#3639)
Signed-off-by: samithuang <285365963@qq.com>
This commit is contained in:
1 parent
f74cba84ac
commit
083b5e363f
8 files changed
+338
-60
No files matched your search
@@ -185,6 +185,10 @@ class DiffusionWorker:
|
||||
self.model_runner: DiffusionModelRunner | None = None
|
||||
self._sleep_saved_buffers: dict[str, torch.Tensor] = {}
|
||||
self.lora_manager: DiffusionLoRAManager | None = None
|
||||
# Worker-side cache of (lora_request, lora_scale) per scheduled
|
||||
# request id. Used by step mode to recover LoRA identity for cached
|
||||
# requests, which only carry their sched_req_id in subsequent ticks.
|
||||
self._step_lora_state: dict[str, tuple[LoRARequest | None, float]] = {}
|
||||
self.stage_id = getattr(od_config, "stage_id", 0)
|
||||
self.init_device()
|
||||
# Create model runner using the platform-specified class
|
||||
@@ -367,13 +371,7 @@ class DiffusionWorker:
|
||||
def execute_stepwise(self, scheduler_output: DiffusionSchedulerOutput) -> BaseRunnerOutput:
|
||||
"""Execute one diffusion step by delegating to the model runner."""
|
||||
assert self.model_runner is not None, "Model runner not initialized"
|
||||
if self.lora_manager is not None:
|
||||
# Step mode does not support LoRA yet. Clear any previously active
|
||||
# adapter first so worker-local LoRA state cannot leak in.
|
||||
self.lora_manager.set_active_adapter(None)
|
||||
|
||||
if any(new_req.req.sampling_params.lora_request is not None for new_req in scheduler_output.scheduled_new_reqs):
|
||||
raise ValueError("Step mode does not support LoRA yet.")
|
||||
self._activate_step_lora(scheduler_output)
|
||||
profiler = self._get_profiler()
|
||||
ctx = profiler.annotate_context_manager("diffusion_step") if profiler else nullcontext()
|
||||
with ctx:
|
||||
@@ -382,6 +380,43 @@ class DiffusionWorker:
|
||||
profiler.step()
|
||||
return output
|
||||
|
||||
def _activate_step_lora(self, scheduler_output: DiffusionSchedulerOutput) -> None:
|
||||
"""Activate the LoRA adapter for the scheduled step batch.
|
||||
|
||||
Newly scheduled requests register their (lora_request, lora_scale)
|
||||
in ``_step_lora_state`` so cached requests can resolve to the same
|
||||
adapter on later ticks. Finished requests are evicted. Batch
|
||||
homogeneity is enforced by the scheduler via ``SamplingParamsKey``,
|
||||
so any scheduled request id resolves to the active LoRA identity.
|
||||
"""
|
||||
for sched_req_id in scheduler_output.finished_req_ids:
|
||||
self._step_lora_state.pop(sched_req_id, None)
|
||||
|
||||
for new_req in scheduler_output.scheduled_new_reqs:
|
||||
sampling = new_req.req.sampling_params
|
||||
self._step_lora_state[new_req.sched_req_id] = (
|
||||
sampling.lora_request,
|
||||
sampling.lora_scale,
|
||||
)
|
||||
|
||||
if self.lora_manager is None:
|
||||
return
|
||||
|
||||
lora_request: LoRARequest | None = None
|
||||
lora_scale = 1.0
|
||||
for sched_req_id in scheduler_output.scheduled_req_ids:
|
||||
entry = self._step_lora_state.get(sched_req_id)
|
||||
if entry is not None:
|
||||
lora_request, lora_scale = entry
|
||||
break
|
||||
|
||||
try:
|
||||
self.lora_manager.set_active_adapter(lora_request, lora_scale)
|
||||
except Exception as exc:
|
||||
if lora_request is not None:
|
||||
raise
|
||||
logger.warning("LoRA activation skipped: %s", exc)
|
||||
|
||||
def load_weights(self, weights) -> set[str]:
|
||||
"""Load weights by delegating to the model runner."""
|
||||
assert self.model_runner is not None, "Model runner not initialized"
|
||||
|
||||
Reference in new issue
Block a user