diff --git a/CHANGELOG.md b/CHANGELOG.md index da6e11169..9c26f559b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ StandardUI is still available and can be selected in settings, but ModernUI is n *What's else*? **Chroma** is in its final form, there are several new **Qwen-Image** variants and **Nunchaku** hit version 1.0! Also, there are quite a few offloading improvements and many quality-of-life changes to UI and overal workflows +And check out new **history** tab in the right panel, it now shows visualization of entire processing timeline! [ReadMe](https://github.com/vladmandic/automatic/blob/master/README.md) | [ChangeLog](https://github.com/vladmandic/automatic/blob/master/CHANGELOG.md) | [Docs](https://vladmandic.github.io/sdnext-docs/) | [WiKi](https://github.com/vladmandic/automatic/wiki) | [Discord](https://discord.com/invite/sd-next-federal-batch-inspectors-1101998836328697867) | [Sponsor](https://github.com/sponsors/vladmandic) diff --git a/javascript/gpu.js b/javascript/gpu.js index d95542f3d..724299375 100644 --- a/javascript/gpu.js +++ b/javascript/gpu.js @@ -44,7 +44,6 @@ async function updateGPU() { } const gpuTbody = gpuTable.querySelector('tbody'); for (const gpu of data) { - console.log(gpu); let rows = `GPU${gpu.name}`; for (const item of Object.entries(gpu.data)) rows += `${item[0]}${item[1]}`; gpuTbody.innerHTML = rows; diff --git a/javascript/history.js b/javascript/history.js index 805c8e4e4..ff2db4831 100644 --- a/javascript/history.js +++ b/javascript/history.js @@ -1,8 +1,12 @@ +const inferenceTypes = ['inference', 'vae', 'te']; +const ioTypes = ['load', 'save']; + function refreshHistory() { log('refreshHistory'); fetch(`${window.api}/history`, { priority: 'low' }).then((res) => { const timeline = document.getElementById('history_timeline'); const table = document.getElementById('history_table'); + timeline.innerHTML = ''; res.json().then((data) => { if (!data || !data.length) { table.innerHTML = '

No history data available.

'; @@ -37,10 +41,13 @@ function refreshHistory() { if (entry.op === 'begin') { const start = entry.timestamp; const end = data.find((e) => (e.id === entry.id && e.op === 'end')) || data[data.length - 1].timestamp; - ts.push({ start, end: end.timestamp, label: entry.job, type: '' }); + if (end.timestamp - start < 0.02) continue; // skip very short entries + if (inferenceTypes.some((type) => entry.job.toLowerCase().startsWith(type))) entry.type = 'inference'; + else if (ioTypes.some((type) => entry.job.toLowerCase().startsWith(type))) entry.type = 'io'; + else entry.type = 'default'; + ts.push({ start, end: end.timestamp, label: entry.job, type: entry.type }); } } - timeline.innerHTML = ''; if (!ts.length) return; new Timesheet(timeline, ts); // eslint-disable-line no-undef, no-new }); diff --git a/javascript/timesheet.css b/javascript/timesheet.css index c84165ab1..f27edfbda 100644 --- a/javascript/timesheet.css +++ b/javascript/timesheet.css @@ -7,36 +7,6 @@ background-color: var(--sd-main-background-color); position: relative; } -.timesheet.color-scheme-default .bubble-default { - background-color: RGBA(252, 70, 74, 1); -} -.timesheet.color-scheme-default .bubble-lorem { - background-color: RGBA(154, 202, 39, 1); -} -.timesheet.color-scheme-default .bubble-ipsum { - background-color: RGBA(60, 182, 227, 1); -} -.timesheet.color-scheme-default .bubble-dolor { - background-color: RGBA(244, 207, 48, 1); -} -.timesheet.color-scheme-default .bubble-sit { - background-color: RGBA(169, 105, 202, 1); -} -.timesheet.color-scheme-alternative .bubble-default { - background-color: #f3552e; -} -.timesheet.color-scheme-alternative .bubble-lorem { - background-color: #88c33a; -} -.timesheet.color-scheme-alternative .bubble-ipsum { - background-color: #436ae0; -} -.timesheet.color-scheme-alternative .bubble-dolor { - background-color: #f4d234; -} -.timesheet.color-scheme-alternative .bubble-sit { - background-color: #707d86; -} .timesheet .scale { height: 100%; position: absolute; @@ -52,7 +22,8 @@ line-height: 24px; font-weight: lighter; border-left: 1px dashed rgba(250, 250, 250, 0.2); - height: 100%} + height: 100%; +} .timesheet .data { margin: 10px 0 10px 0; padding: 0; @@ -93,29 +64,16 @@ float: left; position: relative; top: 7px; - border-radius: 4px; + border-radius: 2px; margin: 0 10px 0 0; opacity: 0.7; +} +.bubble-default { background: var(--sd-main-accent-color); } -#timesheet-alternative { - background-color: RGBA(247, 247, 247, 1); - border-radius: 5px; +.bubble-inference { + background-color: violet; } -#timesheet-alternative section { - color: RGBA(63, 68, 72, 1); - border-left: 1px dashed RGBA(63, 68, 72, 0.2); -} -#timesheet-alternative section:first-child { - border-left: 1px dashed transparent; -} -#timesheet-alternative .date { - display: none; -} -#timesheet-alternative .bubble { - margin-right: 7px; -} -#timesheet-alternative .label { - padding-left: 0px; - color: RGBA(48, 48, 48, 1); +.bubble-io { + background-color: rgb(75, 75, 150); } diff --git a/javascript/timesheet.js b/javascript/timesheet.js index 679a75944..90aac773e 100644 --- a/javascript/timesheet.js +++ b/javascript/timesheet.js @@ -1,14 +1,15 @@ /* eslint max-classes-per-file: ["error", 2] */ class Bubble { - constructor(min, start, end, label, scale) { + constructor(min, start, end, label, scale, type) { + this.type = type; + this.label = label; this.min = min; this.start = start; this.end = end; this.scale = scale; this.offset = Math.round(this.scale * (this.start - this.min)); this.width = Math.round(this.scale * (this.end - this.start)); - this.label = label; this.duration = Math.round(1000 * (this.end - this.start)) / 1000; this.title = `Job: ${this.label}\nDuration: ${this.duration}s\nStart: ${new Date(1000 * this.start).toLocaleString()}\nEnd: ${new Date(1000 * this.end).toLocaleString()}`; } @@ -38,11 +39,11 @@ class Timesheet { html = []; for (let n = 0, m = this.data.length; n < m; n++) { const cur = this.data[n]; - const bubble = new Bubble(this.min, cur.start, cur.end, cur.label, this.scale); + const bubble = new Bubble(this.min, cur.start, cur.end, cur.label, this.scale, cur.type); const line = [ - ``, - `${bubble.duration} `, - `${bubble.label}`, + ``, + `${bubble.duration} `, + `${bubble.label}`, ].join(''); html.push(`
  • ${line}
  • `); } diff --git a/javascript/ui.js b/javascript/ui.js index 66416d0d5..a61297a54 100644 --- a/javascript/ui.js +++ b/javascript/ui.js @@ -189,7 +189,6 @@ function get_tab_index(tabId) { .forEach((button, i) => { if (button.className.indexOf('selected') !== -1) res = i; }); - console.log('get_tab_index', tabId, res); return res; } @@ -297,7 +296,6 @@ function submit_video_wrapper(...args) { log('submitVideoWrapper', id); const btn = gradioApp().getElementById(`${id}_generate_btn`); if (btn) btn.click(); - else console.log('submit_video_wrapper: no button found', id); } function submit_postprocessing(...args) { diff --git a/modules/civitai/download_civitai.py b/modules/civitai/download_civitai.py index a767d9c9f..508bd0a8f 100644 --- a/modules/civitai/download_civitai.py +++ b/modules/civitai/download_civitai.py @@ -62,7 +62,7 @@ def download_civit_preview(model_path: str, preview_url: str): block_size = 16384 # 16KB blocks written = 0 img = None - jobid = shared.state.begin('Download') + jobid = shared.state.begin('Download CivitAI') if pbar is None: pbar = p.Progress(p.TextColumn('[cyan]Download'), p.DownloadColumn(), p.BarColumn(), p.TaskProgressColumn(), p.TimeRemainingColumn(), p.TimeElapsedColumn(), p.TransferSpeedColumn(), p.TextColumn('[yellow]{task.description}'), console=shared.console) try: @@ -139,7 +139,7 @@ def download_civit_model_thread(model_name: str, model_url: str, model_path: str res += f' size={round((starting_pos + total_size)/1024/1024, 2)}Mb' shared.log.info(res) - jobid = shared.state.begin('Download') + jobid = shared.state.begin('Download CivitAI') block_size = 16384 # 16KB blocks written = starting_pos global pbar # pylint: disable=global-statement diff --git a/modules/control/processor.py b/modules/control/processor.py index 4626f3e27..80ca18cd9 100644 --- a/modules/control/processor.py +++ b/modules/control/processor.py @@ -51,6 +51,7 @@ def preprocess_image( has_models:bool = False, ): t0 = time.time() + jobid = shared.state.begin('Preprocess') # run resize before if p.resize_mode_before != 0 and p.resize_name_before != 'None': @@ -246,4 +247,5 @@ def preprocess_image( t1 = time.time() process_timer.add('proc', t1-t0) + shared.state.end(jobid) return processed_image, blended_image diff --git a/modules/control/processors.py b/modules/control/processors.py index 796cb0cc8..7cb8f8833 100644 --- a/modules/control/processors.py +++ b/modules/control/processors.py @@ -160,6 +160,7 @@ class Processor(): self.load_config[k] = v def load(self, processor_id: str = None, force: bool = True) -> str: + from modules.shared import state try: t0 = time.time() processor_id = processor_id or self.processor_id @@ -179,6 +180,7 @@ class Processor(): cls = config[processor_id]['class'] # log.debug(f'Control Processor loading: id="{processor_id}" class={cls.__name__}') debug(f'Control Processor config={self.load_config}') + jobid = state.begin('Load processor') if 'DWPose' in processor_id: det_ckpt = 'https://download.openmmlab.com/mmdetection/v2.0/yolox/yolox_l_8x8_300e_coco/yolox_l_8x8_300e_coco_20211126_140236-d3bd2b23.pth' if 'Tiny' == config['DWPose']['model']: @@ -209,6 +211,7 @@ class Processor(): else: self.model = cls() # class instance only t1 = time.time() + state.end(jobid) self.processor_id = processor_id log.debug(f'Control Processor loaded: id="{processor_id}" class={self.model.__class__.__name__} time={t1-t0:.2f}') return f'Processor loaded: {processor_id}' diff --git a/modules/control/run.py b/modules/control/run.py index 6c400cc23..6d1b885b7 100644 --- a/modules/control/run.py +++ b/modules/control/run.py @@ -597,12 +597,9 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg if processed_image is not None and isinstance(processed_image, Image.Image): output_images.append(processed_image) - if is_generator: + if is_generator and frame is not None and video is not None: image_txt = f'{output_image.width}x{output_image.height}' if output_image is not None else 'None' - if video is not None: - msg = f'Control output | {index} of {frames} skip {video_skip_frames} | Frame {image_txt}' - else: - msg = f'Control output | {index} of {len(inputs)} | Image {image_txt}' + msg = f'Control output | {index} of {frames} skip {video_skip_frames} | Frame {image_txt}' yield (output_image, blended_image, msg) # result is control_output, proces_output if video is not None and frame is not None: @@ -643,5 +640,7 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg if len(info_txt) > 0: html_txt = html_txt + infotext_to_html(info_txt[0]) if is_generator: + jobid = shared.state.begin('UI') yield (output_images, blended_image, html_txt, output_filename) + shared.state.end(jobid) return (output_images, blended_image, html_txt, output_filename) diff --git a/modules/control/units/controlnet.py b/modules/control/units/controlnet.py index 9ad4df844..990ca2e4a 100644 --- a/modules/control/units/controlnet.py +++ b/modules/control/units/controlnet.py @@ -4,7 +4,7 @@ import threading from typing import Union from diffusers import StableDiffusionPipeline, StableDiffusionXLPipeline, FluxPipeline, StableDiffusion3Pipeline, ControlNetModel from modules.control.units import detect -from modules.shared import log, opts, cmd_opts, listdir +from modules.shared import log, opts, cmd_opts, state, listdir from modules import errors, sd_models, devices, model_quant from modules.processing import StableDiffusionProcessingControl @@ -308,6 +308,7 @@ class ControlNet(): log.error(f'Control {what} model load: id="{model_id}" unknown base model') return self.reset() + jobid = state.begin(f'Load {what}') if model_path.endswith('.safetensors'): self.load_safetensors(model_id, model_path, cls, config) else: @@ -365,6 +366,7 @@ class ControlNet(): t1 = time.time() self.model_id = model_id log.info(f'Control {what} model loaded: id="{model_id}" path="{model_path}" cls={cls.__name__} time={t1-t0:.2f}') + state.end(jobid) return f'{what} loaded model: {model_id}' except Exception as e: log.error(f'Control {what} model load: id="{model_id}" {e}') diff --git a/modules/framepack/framepack_load.py b/modules/framepack/framepack_load.py index 3a4fb90a4..0e80e8485 100644 --- a/modules/framepack/framepack_load.py +++ b/modules/framepack/framepack_load.py @@ -61,7 +61,7 @@ def reset_model(): def load_model(variant:str=None, pipeline:str=None, text_encoder:str=None, text_encoder_2:str=None, feature_extractor:str=None, image_encoder:str=None, transformer:str=None): - shared.state.begin('Load') + shared.state.begin('Load FramePack') if variant is not None: if variant not in models.keys(): raise ValueError(f'FramePack: variant="{variant}" invalid') diff --git a/modules/framepack/framepack_worker.py b/modules/framepack/framepack_worker.py index ab29f219e..1b87334ec 100644 --- a/modules/framepack/framepack_worker.py +++ b/modules/framepack/framepack_worker.py @@ -84,6 +84,7 @@ def worker( prompts = list(reversed(prompts)) def text_encode(prompt, i:int=None): + jobid = shared.state.begin('TE Encode') pbar.update(task, description=f'text encode section={i}') t0 = time.time() torch.manual_seed(seed) @@ -102,9 +103,11 @@ def worker( llama_vec_n, llama_attention_mask_n = utils.crop_or_pad_yield_mask(llama_vec_n, length=512) sd_models.apply_balanced_offload(shared.sd_model) timer.process.add('prompt', time.time()-t0) + shared.state.end(jobid) return llama_vec, llama_vec_n, llama_attention_mask, llama_attention_mask_n, clip_l_pooler, clip_l_pooler_n def latents_encode(input_image, end_image): + jobid = shared.state.begin('VAE Encode') pbar.update(task, description='image encode') # shared.log.debug(f'FramePack: image encode init={input_image.shape} end={end_image.shape if end_image is not None else None}') t0 = time.time() @@ -126,6 +129,7 @@ def worker( end_latent = None sd_models.apply_balanced_offload(shared.sd_model) timer.process.add('encode', time.time()-t0) + shared.state.end(jobid) return start_latent, end_latent def vision_encode(input_image, end_image): diff --git a/modules/images.py b/modules/images.py index 8fd0e04f8..d93170be8 100644 --- a/modules/images.py +++ b/modules/images.py @@ -46,7 +46,7 @@ def atomically_save_image(): Image.MAX_IMAGE_PIXELS = None # disable check in Pillow and rely on check below to allow large custom image sizes while True: image, filename, extension, params, exifinfo, filename_txt, is_grid = save_queue.get() - jobid = shared.state.begin('Save') + jobid = shared.state.begin('Save image') shared.state.image_history += 1 if len(exifinfo) > 2: with open(paths.params_path, "w", encoding="utf8") as file: diff --git a/modules/interrogate/openclip.py b/modules/interrogate/openclip.py index aa8c907ce..508a4d897 100644 --- a/modules/interrogate/openclip.py +++ b/modules/interrogate/openclip.py @@ -135,7 +135,7 @@ def interrogate(image, mode, caption=None): def interrogate_image(image, clip_model, blip_model, mode): - jobid = shared.state.begin('Interrogate') + jobid = shared.state.begin('Interrogate CLiP') try: if shared.sd_loaded: from modules.sd_models import apply_balanced_offload # prevent circular import diff --git a/modules/interrogate/vqa.py b/modules/interrogate/vqa.py index 958eebdd5..578c96093 100644 --- a/modules/interrogate/vqa.py +++ b/modules/interrogate/vqa.py @@ -605,7 +605,7 @@ def sa2(question: str, image: Image.Image, repo: str = None): def interrogate(question:str='', system_prompt:str=None, prompt:str=None, image:Image.Image=None, model_name:str=None, quiet:bool=False): global quant_args # pylint: disable=global-statement - jobid = shared.state.begin('Interrogate') + jobid = shared.state.begin('Interrogate LLM') t0 = time.time() quant_args = model_quant.create_config(module='LLM') model_name = model_name or shared.opts.interrogate_vlm_model diff --git a/modules/ipadapter.py b/modules/ipadapter.py index ad2caec2e..676045d1f 100644 --- a/modules/ipadapter.py +++ b/modules/ipadapter.py @@ -188,6 +188,7 @@ def load_image_encoder(pipe: diffusers.DiffusionPipeline, adapter_names: list[st # load image encoder used by ip adapter if pipe.image_encoder is None or clip_loaded != f'{clip_repo}/{clip_subfolder}': + jobid = shared.state.begin('Load encoder') try: if shared.sd_model_type == 'sd3': image_encoder = transformers.SiglipVisionModel.from_pretrained(clip_repo, torch_dtype=devices.dtype, cache_dir=shared.opts.hfcache_dir) @@ -209,6 +210,7 @@ def load_image_encoder(pipe: diffusers.DiffusionPipeline, adapter_names: list[st shared.log.error(f'IP adapter load: encoder="{clip_repo}/{clip_subfolder}" {e}') errors.display(e, 'IP adapter: type=encoder') return False + shared.state.end(jobid) sd_models.move_model(pipe.image_encoder, devices.device) return True @@ -217,6 +219,7 @@ def load_feature_extractor(pipe): # load feature extractor used by ip adapter if pipe.feature_extractor is None: try: + jobid = shared.state.begin('Load extractor') if shared.sd_model_type == 'sd3': feature_extractor = transformers.SiglipImageProcessor.from_pretrained(SIGLIP_ID, torch_dtype=devices.dtype, cache_dir=shared.opts.hfcache_dir) else: @@ -231,6 +234,7 @@ def load_feature_extractor(pipe): shared.log.error(f'IP adapter load: extractor {e}') errors.display(e, 'IP adapter: type=extractor') return False + shared.state.end(jobid) return True diff --git a/modules/processing_args.py b/modules/processing_args.py index a82bf11f3..5d40d8db0 100644 --- a/modules/processing_args.py +++ b/modules/processing_args.py @@ -137,6 +137,7 @@ def task_specific_kwargs(p, model): def set_pipeline_args(p, model, prompts:list, negative_prompts:list, prompts_2:typing.Optional[list]=None, negative_prompts_2:typing.Optional[list]=None, prompt_attention:typing.Optional[str]=None, desc:typing.Optional[str]='', **kwargs): t0 = time.time() shared.sd_model = sd_models.apply_balanced_offload(shared.sd_model) + argsid = shared.state.begin('Params') apply_circular(p.tiling, model) args = {} has_vae = hasattr(model, 'vae') or (hasattr(model, 'pipe') and hasattr(model.pipe, 'vae')) @@ -445,4 +446,5 @@ def set_pipeline_args(p, model, prompts:list, negative_prompts:list, prompts_2:t else: _args[k] = v + shared.state.end(argsid) return _args diff --git a/modules/processing_vae.py b/modules/processing_vae.py index 883686152..aca549a39 100644 --- a/modules/processing_vae.py +++ b/modules/processing_vae.py @@ -316,6 +316,7 @@ def vae_decode(latents, model, output_type='np', vae_type='Full', width=None, he def vae_encode(image, model, vae_type='Full'): # pylint: disable=unused-variable + jobid = shared.state.begin('VAE Encode') import torchvision.transforms.functional as f if shared.state.interrupted or shared.state.skipped: return [] @@ -331,6 +332,7 @@ def vae_encode(image, model, vae_type='Full'): # pylint: disable=unused-variable else: latents = taesd_vae_encode(image=tensor) devices.torch_gc() + shared.state.end(jobid) return latents diff --git a/modules/sd_models.py b/modules/sd_models.py index 9a73eb787..a251495c3 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -1122,7 +1122,7 @@ def reload_model_weights(sd_model=None, info=None, op='model', force=False, revi if checkpoint_info is None: unload_model_weights(op=op) return None - jobid = shared.state.begin('Load') + jobid = shared.state.begin('Load model') if sd_model is None: sd_model = model_data.sd_model if op == 'model' or op == 'dict' else model_data.sd_refiner if sd_model is None: # previous model load failed diff --git a/modules/styles.py b/modules/styles.py index cbfffbb39..ec3ca71e9 100644 --- a/modules/styles.py +++ b/modules/styles.py @@ -319,6 +319,7 @@ class StyleDatabase: if seeds is None or not isinstance(prompts, list): shared.log.error(f'Styles invalid seeds: {seeds}') return prompts, negatives + jobid = shared.state.begin('Styles') parsed_positive = [] parsed_negative = [] for i in range(len(prompts)): @@ -331,6 +332,7 @@ class StyleDatabase: prompt = apply_styles_to_prompt(prompt, [self.find_style(x).negative_prompt for x in styles]) prompt = apply_wildcards_to_prompt(prompt, [self.find_style(x).wildcards for x in styles], seeds[i]) parsed_negative.append(prompt) + shared.state.end(jobid) return parsed_positive, parsed_negative def apply_styles_to_prompt(self, prompt, styles, wildcards:bool=True): diff --git a/modules/video.py b/modules/video.py index 8efbad070..fe7d88c36 100644 --- a/modules/video.py +++ b/modules/video.py @@ -29,6 +29,7 @@ def save_video_atomic(images, filename, video_type: str = 'none', duration: floa except Exception as e: shared.log.error(f'Save video: cv2: {e}') return + jobid = shared.state.begin('Save video') os.makedirs(os.path.dirname(filename), exist_ok=True) if video_type.lower() in ['gif', 'png']: append = images.copy() @@ -56,6 +57,7 @@ def save_video_atomic(images, filename, video_type: str = 'none', duration: floa video_writer.write(img) size = os.path.getsize(filename) shared.log.info(f'Save video: file="{filename}" frames={len(frames)} duration={duration} fourcc={fourcc} size={size}') + shared.state.end(jobid) def save_video(p, images, filename = None, video_type: str = 'none', duration: float = 2.0, loop: bool = False, interpolate: int = 0, scale: float = 1.0, pad: int = 1, change: float = 0.3, sync: bool = False): diff --git a/modules/video_models/video_load.py b/modules/video_models/video_load.py index 7d0b9d15d..72c411166 100644 --- a/modules/video_models/video_load.py +++ b/modules/video_models/video_load.py @@ -15,7 +15,7 @@ def load_model(selected: models_def.Model): return '' sd_models.unload_model_weights() t0 = time.time() - jobid = shared.state.begin('Load') + jobid = shared.state.begin('Load model') video_cache.apply_teacache_patch(selected.dit_cls) diff --git a/modules/video_models/video_save.py b/modules/video_models/video_save.py index 274ff69a1..2ce71f0af 100644 --- a/modules/video_models/video_save.py +++ b/modules/video_models/video_save.py @@ -78,6 +78,7 @@ def save_video( size = pixels.element_size() * pixels.numel() shared.log.debug(f'Video: video={mp4_video} export={mp4_frames} safetensors={mp4_sf} interpolate={mp4_interpolate}') shared.log.debug(f'Video: encode={t} raw={size} latent={pixels.shape} fps={mp4_fps} codec={mp4_codec} ext={mp4_ext} options="{mp4_opt}"') + jobid = shared.state.begin('Save video') try: if stream is not None: stream.output_queue.push(('progress', (None, 'Saving video...'))) @@ -124,4 +125,5 @@ def save_video( shared.log.error(f'Video save: raw={size} {e}') errors.display(e, 'video') timer.process.add('save', time.time()-t_save) + shared.state.end(jobid) return t, output_video diff --git a/pipelines/generic.py b/pipelines/generic.py index 43e282b17..2c5f0b847 100644 --- a/pipelines/generic.py +++ b/pipelines/generic.py @@ -10,6 +10,7 @@ debug = os.environ.get('SD_LOAD_DEBUG', None) is not None def load_transformer(repo_id, cls_name, load_config={}, subfolder="transformer", allow_quant=True, variant=None, dtype=None, modules_to_not_convert=[], modules_dtype_dict={}): transformer = None + jobid = shared.state.begin('Load DiT') try: load_args, quant_args = model_quant.get_dit_args(load_config, module='Model', device_map=True, allow_quant=allow_quant, modules_to_not_convert=modules_to_not_convert, modules_dtype_dict=modules_dtype_dict) quant_type = model_quant.get_quant_type(quant_args) @@ -68,11 +69,13 @@ def load_transformer(repo_id, cls_name, load_config={}, subfolder="transformer", errors.display(e, 'Load:') raise devices.torch_gc() + shared.state.end(jobid) return transformer def load_text_encoder(repo_id, cls_name, load_config={}, subfolder="text_encoder", allow_quant=True, allow_shared=True, variant=None, dtype=None, modules_to_not_convert=[], modules_dtype_dict={}): text_encoder = None + jobid = shared.state.begin('Load TE') try: load_args, quant_args = model_quant.get_dit_args(load_config, module='TE', device_map=True, allow_quant=allow_quant, modules_to_not_convert=modules_to_not_convert, modules_dtype_dict=modules_dtype_dict) quant_type = model_quant.get_quant_type(quant_args) @@ -159,4 +162,5 @@ def load_text_encoder(repo_id, cls_name, load_config={}, subfolder="text_encoder errors.display(e, 'Load:') raise devices.torch_gc() + shared.state.end(jobid) return text_encoder diff --git a/webui.py b/webui.py index 3fd7de7f0..ec33c908e 100644 --- a/webui.py +++ b/webui.py @@ -155,7 +155,7 @@ def load_model(): if not shared.opts.sd_checkpoint_autoload and shared.cmd_opts.ckpt is None: log.info('Model: autoload=False') else: - jobid = shared.state.begin('Load') + jobid = shared.state.begin('Load model') thread_model = Thread(target=lambda: shared.sd_model) thread_model.start() thread_refiner = Thread(target=lambda: shared.sd_refiner)