improve state management

Signed-off-by: Vladimir Mandic <mandic00@live.com>
This commit is contained in:
Vladimir Mandic
2026-08-15 19:21:51 +02:00
parent a6a6fb2aaa
commit 12bf006b00
6 changed files with 102 additions and 92 deletions
+1 -1
View File
@@ -584,7 +584,7 @@ def check_diffusers():
t_start = time.time()
if args.skip_all:
return
target_commit = "7564fb016dabda0c943416190fc92398c50b1b20" # diffusers commit hash == 0.40.0.dev0 == 08-11-2026
target_commit = "d5baa4fb548294f47dbca49890abd4b291204c60" # diffusers commit hash == 0.40.0.dev0 == 08-15-2026
# if args.use_rocm or args.use_zluda:
# sha = '043ab2520f6a19fce78e6e060a68dbc947edb9f9' # lock diffusers versions for now
pkg = package_spec('diffusers')
+1 -1
View File
@@ -548,7 +548,7 @@ def set_sdpa_params():
log.debug(f'Torch attention installed: flashattn={flash} sageattention={sage}')
from diffusers.models import attention_dispatch as a
log.debug(f'Torch attention available: flash={a._CAN_USE_FLASH_ATTN} flash3={a._CAN_USE_FLASH_ATTN_3} aiter={a._CAN_USE_AITER_ATTN} sage={a._CAN_USE_SAGE_ATTN} flex={a._CAN_USE_FLEX_ATTN} npu={a._CAN_USE_NPU_ATTN} xla={a._CAN_USE_XLA_ATTN} xformers={a._CAN_USE_XFORMERS_ATTN} kernels={a.is_kernels_available()} sdnq=True') # pylint: disable=protected-access
log.debug(f'Torch attention available: flash={a._CAN_USE_FLASH_ATTN} flash3={a._CAN_USE_FLASH_ATTN_3} sage={a._CAN_USE_SAGE_ATTN} flex={a._CAN_USE_FLEX_ATTN} npu={a._CAN_USE_NPU_ATTN} xla={a._CAN_USE_XLA_ATTN} xformers={a._CAN_USE_XFORMERS_ATTN} kernels={a.is_kernels_available()} sdnq=True') # pylint: disable=protected-access
except Exception as e:
log.warning(f'Torch SDPA: {e}')
-1
View File
@@ -11,7 +11,6 @@ from modules import timer, errors
from modules.logger import log
log.info('Initializing: packages')
initialized = False
errors.install()
logging.getLogger("DeepSpeed").disabled = True
+2 -2
View File
@@ -698,5 +698,5 @@ def run_ltx(task_id,
progress.finish_task(task_id)
p.close()
log.info(f'Processed: fn="{video_file}" frames={num_frames} fps={fps} its={its} resolution={resolution} time={t_end-t0:.2f} timers={timer.process.dct()} memory={memstats.memory_stats()}')
yield video_file, f'LTX: Generation completed | File {video_file} | Frames {num_frames} | Resolution {resolution} | f/s {fps} | it/s {its} ' + f"<div class='performance'><p>{summary} {memory}</p></div>"
log.info(f'Processed: fn="{video_file}" frames={num_frames} fps={fps} its={its} resolution={resolution} time={t_end-t0:.2f} timers={timer.process.dct(no_total=True)} memory={memstats.memory_stats()}')
yield video_file, f'Video | File {video_file} | Frames {num_frames} | Resolution {resolution} | f/s {fps} | it/s {its} ' + f"<div class='performance'><p>{summary} {memory}</p></div>"
+93 -85
View File
@@ -3,7 +3,7 @@ import time
from PIL import Image
import numpy as np
from modules.logger import log
from modules import shared, devices, processing, timer, progress, paths, sd_models, scripts_manager, call_queue, memstats, processing_video
from modules import shared, devices, errors, processing, timer, progress, paths, sd_models, scripts_manager, call_queue, memstats, processing_video
from modules.video_models import models_def, video_save, video_utils
@@ -98,42 +98,6 @@ def generate(task_id, _ui_state,
progress.start_task(task_id)
memstats.reset_stats()
timer.process.reset()
workflow = load_model(model) # override workflow based on loaded model
if not workflow:
progress.finish_task(task_id)
log.error('Video: model not loaded')
return None, 'Model not loaded'
p = processing.StableDiffusionProcessingVideo(
sd_model=shared.sd_model,
video_engine=engine,
video_model=model,
prompt=prompt,
styles=styles,
seed=int(seed) if seed is not None else -1,
steps=int(steps),
width=width,
height=height,
frames=frames,
do_not_save_grid=True,
do_not_save_samples=not mp4_frames,
outpath_samples=paths.resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_video),
ops=['video'],
)
video_minimax.apply_overrides(p, shared.sd_model, still=False, audio=audio_enable)
video_minimax.set_sampler_shift(shared.sd_model, video_shift=video_shift, audio_shift=audio_shift)
log.debug(f'Video: engine="{engine}" model="{model}" workflow={workflow} cls={shared.sd_model.__class__.__name__} shift={video_shift}:{audio_shift} kwargs={p.task_args}')
processing.fix_seed(p)
p.ops.append('video')
p.scripts = scripts_manager.scripts_video
p.script_args = args
prepare_inputs(workflow, p, init_image, last_image, reference_media)
_processed: processing.Processed = scripts_manager.scripts_video.run(p, *args)
processed = processing.process_images(p)
sd_models.offload_ondemand(shared.sd_model, reason='finish', force=True) # force offload all loaded modules to cpu
devices.torch_gc(force=True) # free gpu memory before saving video
# init vars
pixels = None
@@ -141,65 +105,109 @@ def generate(task_id, _ui_state,
video_file = None
aac_sample_rate = 32000
audio = getattr(processed, 'audio', None) if audio_enable else None
if audio is not None:
audio = audio[0].float().cpu() if audio.ndim == 3 else audio.float().cpu()
aac_sample_rate = getattr(shared.sd_model, 'audio_sampling_rate', 32000)
try:
workflow = load_model(model) # override workflow based on loaded model
if not workflow:
progress.finish_task(task_id)
log.error('Video: model not loaded')
return None, 'Model not loaded'
p = processing.StableDiffusionProcessingVideo(
sd_model=shared.sd_model,
video_engine=engine,
video_model=model,
prompt=prompt,
styles=styles,
seed=int(seed) if seed is not None else -1,
steps=int(steps),
width=width,
height=height,
frames=frames,
do_not_save_grid=True,
do_not_save_samples=not mp4_frames,
outpath_samples=paths.resolve_output_path(shared.opts.outdir_samples, shared.opts.outdir_video),
ops=['video'],
)
video_minimax.apply_overrides(p, shared.sd_model, still=False, audio=audio_enable)
video_minimax.set_sampler_shift(shared.sd_model, video_shift=video_shift, audio_shift=audio_shift)
log.debug(f'Video: engine="{engine}" model="{model}" workflow={workflow} cls={shared.sd_model.__class__.__name__} shift={video_shift}:{audio_shift} kwargs={p.task_args}')
processing.fix_seed(p)
p.ops.append('video')
p.scripts = scripts_manager.scripts_video
p.script_args = args
images = getattr(processed, 'images', [])
if isinstance(images, list):
pixels = video_save.images_to_tensor(images)
elif isinstance(images, np.ndarray):
pixels = video_save.numpy_to_tensor(images)
else:
log.error(f'Video: images={images} type={type(images)} unsupported')
prepare_inputs(workflow, p, init_image, last_image, reference_media)
if pixels is None:
return None, "MiniMax: No frames generated"
_processed: processing.Processed = scripts_manager.scripts_video.run(p, *args)
processed = processing.process_images(p)
if mp4_interpolate > 0:
p.video_interpolate = mp4_interpolate
from modules.processing_video import apply_video_interpolation
# pixels is 5-D (N,C,T,H,W) in [-1,1]; RIFE needs 4-D (T,C,H,W) in [0,1]
x = pixels.squeeze(0).permute(1, 0, 2, 3)
x = (x.clamp(-1., 1.) + 1.0) * 0.5
x = apply_video_interpolation(p, x, count=mp4_interpolate) # sets p.video_interpolated otherwise main save_video would do it also
x = x * 2.0 - 1.0
pixels = x.permute(1, 0, 2, 3).unsqueeze(0)
sd_models.offload_ondemand(shared.sd_model, reason='finish', force=True) # force offload all loaded modules to cpu
devices.torch_gc(force=True) # free gpu memory before saving video
save_fps = mp4_fps * processing_video.interpolation_factor(p)
num_frames, video_file, _thumb = video_save.save_video(
p=p,
pixels=pixels,
audio=audio,
mp4_fps=save_fps,
mp4_codec=mp4_codec,
mp4_opt=mp4_opt,
mp4_ext=mp4_ext,
mp4_sf=mp4_sf,
mp4_video=mp4_video,
mp4_frames=mp4_frames,
mp4_thumb=mp4_thumb,
mp4_interpolate=mp4_interpolate,
aac_sample_rate=aac_sample_rate,
metadata={},
)
_n, _c, _t, h, w = pixels.shape
del pixels
if audio is not None:
del audio
audio = getattr(processed, 'audio', None) if audio_enable else None
if audio is not None:
audio = audio[0].float().cpu() if audio.ndim == 3 else audio.float().cpu()
aac_sample_rate = getattr(shared.sd_model, 'audio_sampling_rate', 32000)
images = getattr(processed, 'images', [])
if isinstance(images, list):
pixels = video_save.images_to_tensor(images)
elif isinstance(images, np.ndarray):
pixels = video_save.numpy_to_tensor(images)
else:
log.error(f'Video: images={images} type={type(images)} unsupported')
if pixels is None:
return None, "MiniMax: No frames generated"
if mp4_interpolate > 0:
p.video_interpolate = mp4_interpolate
from modules.processing_video import apply_video_interpolation
# pixels is 5-D (N,C,T,H,W) in [-1,1]; RIFE needs 4-D (T,C,H,W) in [0,1]
x = pixels.squeeze(0).permute(1, 0, 2, 3)
x = (x.clamp(-1., 1.) + 1.0) * 0.5
x = apply_video_interpolation(p, x, count=mp4_interpolate) # sets p.video_interpolated otherwise main save_video would do it also
x = x * 2.0 - 1.0
pixels = x.permute(1, 0, 2, 3).unsqueeze(0)
save_fps = mp4_fps * processing_video.interpolation_factor(p)
num_frames, video_file, _thumb = video_save.save_video(
p=p,
pixels=pixels,
audio=audio,
mp4_fps=save_fps,
mp4_codec=mp4_codec,
mp4_opt=mp4_opt,
mp4_ext=mp4_ext,
mp4_sf=mp4_sf,
mp4_video=mp4_video,
mp4_frames=mp4_frames,
mp4_thumb=mp4_thumb,
mp4_interpolate=mp4_interpolate,
aac_sample_rate=aac_sample_rate,
metadata={},
)
_n, _c, _t, h, w = pixels.shape
del pixels
if audio is not None:
del audio
except Exception as e:
log.error(f'Video: engine="{engine}" model="{model}" workflow={workflow} {e}')
errors.display(e, 'Video')
finally:
jobid = getattr(shared.sd_model, 'sdnext_phaseid', None) # previous jobid if any
shared.state.end(jobid) # clear the previous job if exists
progress.finish_task(task_id)
p.close()
t1 = time.time()
progress.finish_task(task_id)
p.close()
resolution = f'{w}x{h}' if num_frames > 0 else None
summary = timer.process.summary(min_time=0.25, total=False).replace('=', ' ')
memory = shared.mem_mon.summary()
total_time = max(t1 - t0, 1e-6)
fps = f'{num_frames/total_time:.2f}'
its = f'{(steps)/total_time:.3f}'
log.info(f'Processed: fn="{video_file}" frames={num_frames} fps={fps} its={its} resolution={resolution} time={total_time:.2f} timers={timer.process.dct()} memory={memstats.memory_stats()}')
log.info(f'Processed: fn="{video_file}" frames={num_frames} fps={fps} its={its} resolution={resolution} time={total_time:.2f} timers={timer.process.dct(no_total=True)} memory={memstats.memory_stats()}')
ui_text = f'MiniMax: Generation completed | File {video_file} | Frames {num_frames} | Resolution {resolution} | f/s {fps} | it/s {its} ' + f"<div class='performance'><p>{summary} {memory}</p></div>"
ui_text = f'Video | File {video_file} | Frames {num_frames} | Resolution {resolution} | f/s {fps} | it/s {its} ' + f"<div class='performance'><p>{summary} {memory}</p></div>"
return video_file, ui_text
+5 -2
View File
@@ -20,6 +20,7 @@ def start_task(id_task):
global current_task # pylint: disable=global-statement
current_task = id_task
pending_tasks.pop(id_task, None)
log.debug(f'State: start id={id_task} pending={len(pending_tasks)} finished={len(finished_tasks)}')
def record_results(id_task, res):
@@ -30,10 +31,12 @@ def record_results(id_task, res):
def finish_task(id_task):
global current_task # pylint: disable=global-statement
log.debug(f'State: end id={id_task}')
if current_task == id_task:
current_task = None
finished_tasks.append(id_task)
if len(finished_tasks) > 16:
if id_task not in finished_tasks:
finished_tasks.append(id_task)
if len(finished_tasks) > 1024*1024:
finished_tasks.pop(0)