mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 17:24:32 +02:00
redesign profiler
This commit is contained in:
@@ -1,22 +1,16 @@
|
||||
import re
|
||||
import gradio as gr
|
||||
from fastapi import FastAPI
|
||||
import network
|
||||
import networks
|
||||
import lora # noqa:F401 # pylint: disable=unused-import
|
||||
# import lora_patches
|
||||
import extra_networks_lora
|
||||
import ui_extra_networks_lora
|
||||
from network import NetworkOnDisk
|
||||
from ui_extra_networks_lora import ExtraNetworksPageLora
|
||||
from extra_networks_lora import ExtraNetworkLora
|
||||
# import lora # noqa:F401 # pylint: disable=unused-import
|
||||
from modules import script_callbacks, ui_extra_networks, extra_networks, shared
|
||||
|
||||
|
||||
# def unload():
|
||||
# networks.originals.undo()
|
||||
|
||||
|
||||
def before_ui():
|
||||
ui_extra_networks.register_page(ui_extra_networks_lora.ExtraNetworksPageLora())
|
||||
networks.extra_network_lora = extra_networks_lora.ExtraNetworkLora()
|
||||
ui_extra_networks.register_page(ExtraNetworksPageLora())
|
||||
networks.extra_network_lora = ExtraNetworkLora()
|
||||
extra_networks.register_extra_network(networks.extra_network_lora)
|
||||
# extra_networks.register_extra_network_alias(networks.extra_network_lora, "lyco")
|
||||
|
||||
@@ -28,15 +22,7 @@ script_callbacks.on_before_ui(before_ui)
|
||||
script_callbacks.on_infotext_pasted(networks.infotext_pasted)
|
||||
|
||||
|
||||
shared.options_templates.update(shared.options_section(('extra_networks', "Extra Networks"), {
|
||||
# "sd_lora": shared.OptionInfo("None", "Add network to prompt", gr.Dropdown, lambda: {"choices": ["None", *networks.available_networks], "visible": False}, refresh=networks.list_available_networks),
|
||||
"sd_lora": shared.OptionInfo("None", "Add network to prompt", gr.Dropdown, {"choices": ["None"], "visible": False}),
|
||||
# "lora_show_all": shared.OptionInfo(False, "Always show all networks on the Lora page").info("otherwise, those detected as for incompatible version of Stable Diffusion will be hidden"),
|
||||
# "lora_hide_unknown_for_versions": shared.OptionInfo([], "Hide networks of unknown versions for model versions", gr.CheckboxGroup, {"choices": ["SD1", "SD2", "SDXL"]}),
|
||||
}))
|
||||
|
||||
|
||||
def create_lora_json(obj: network.NetworkOnDisk):
|
||||
def create_lora_json(obj: NetworkOnDisk):
|
||||
return {
|
||||
"name": obj.name,
|
||||
"alias": obj.alias,
|
||||
@@ -45,7 +31,7 @@ def create_lora_json(obj: network.NetworkOnDisk):
|
||||
}
|
||||
|
||||
|
||||
def api_networks(_: gr.Blocks, app: FastAPI):
|
||||
def api_networks(_, app: FastAPI):
|
||||
@app.get("/sdapi/v1/loras")
|
||||
async def get_loras():
|
||||
return [create_lora_json(obj) for obj in networks.available_networks.values()]
|
||||
|
||||
@@ -91,7 +91,7 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage):
|
||||
return None
|
||||
|
||||
def list_items(self):
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor:
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=shared.max_workers) as executor:
|
||||
future_items = {executor.submit(self.create_item, net): net for net in networks.available_networks}
|
||||
for future in concurrent.futures.as_completed(future_items):
|
||||
item = future.result()
|
||||
|
||||
+5
-15
@@ -6,8 +6,6 @@ import shutil
|
||||
import logging
|
||||
import platform
|
||||
import subprocess
|
||||
import io
|
||||
import pstats
|
||||
import cProfile
|
||||
import pkg_resources
|
||||
|
||||
@@ -29,6 +27,7 @@ opts = {}
|
||||
args = Dot({
|
||||
'debug': False,
|
||||
'reset': False,
|
||||
'profile': False,
|
||||
'upgrade': False,
|
||||
'skip_extensions': False,
|
||||
'skip_requirements': False,
|
||||
@@ -143,19 +142,9 @@ def print_dict(d):
|
||||
return ' '.join([f'{k}={v}' for k, v in d.items()])
|
||||
|
||||
|
||||
def print_profile(profile: cProfile.Profile, msg: str):
|
||||
try:
|
||||
from rich import print # pylint: disable=redefined-builtin
|
||||
except Exception:
|
||||
pass
|
||||
profile.disable()
|
||||
stream = io.StringIO()
|
||||
ps = pstats.Stats(profile, stream=stream)
|
||||
ps.sort_stats(pstats.SortKey.CUMULATIVE).print_stats(15)
|
||||
profile = None
|
||||
lines = stream.getvalue().split('\n')
|
||||
lines = [line for line in lines if '<frozen' not in line and '{built-in' not in line and '/logging' not in line and '/rich' not in line]
|
||||
print(f'Profile {msg}:', '\n'.join(lines))
|
||||
def print_profile(profiler: cProfile.Profile, msg: str):
|
||||
from modules.errors import profile
|
||||
profile(profiler, msg)
|
||||
|
||||
|
||||
# check if package is installed
|
||||
@@ -768,6 +757,7 @@ def set_environment():
|
||||
os.environ.setdefault('TF_ENABLE_ONEDNN_OPTS', '0')
|
||||
os.environ.setdefault('USE_TORCH', '1')
|
||||
os.environ.setdefault('UVICORN_TIMEOUT_KEEP_ALIVE', '60')
|
||||
os.environ.setdefault('KINETO_LOG_LEVEL', '3')
|
||||
os.environ.setdefault('HF_HUB_CACHE', opts.get('hfcache_dir', os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'hub')))
|
||||
log.debug(f'Cache folder: {os.environ.get("HF_HUB_CACHE")}')
|
||||
if sys.platform == 'darwin':
|
||||
|
||||
@@ -2,9 +2,6 @@ import html
|
||||
import threading
|
||||
import time
|
||||
import cProfile
|
||||
import pstats
|
||||
import io
|
||||
from rich import print # pylint: disable=redefined-builtin
|
||||
from modules import shared, progress, errors
|
||||
|
||||
queue_lock = threading.Lock()
|
||||
@@ -62,10 +59,7 @@ def wrap_gradio_call(func, extra_outputs=None, add_stats=False, name=None):
|
||||
else:
|
||||
res = list(res)
|
||||
if shared.cmd_opts.profile:
|
||||
pr.disable()
|
||||
s = io.StringIO()
|
||||
pstats.Stats(pr, stream=s).sort_stats(pstats.SortKey.CUMULATIVE).print_stats(15)
|
||||
print('Profile Exec:', s.getvalue())
|
||||
errors.profile(pr, 'Wrap')
|
||||
except Exception as e:
|
||||
errors.display(e, 'gradio call')
|
||||
if extra_outputs_array is None:
|
||||
|
||||
@@ -150,6 +150,25 @@ def torch_gc(force=False):
|
||||
log.debug(f'gc: collected={collected} device={torch.device(get_optimal_device_name())} {memstats.memory_stats()}')
|
||||
|
||||
|
||||
def set_cuda_sync_mode(mode):
|
||||
"""
|
||||
Set the CUDA device synchronization mode: auto, spin, yield or block.
|
||||
auto: Chooses spin or yield depending on the number of available CPU cores.
|
||||
spin: Runs one CPU core per GPU at 100% to poll for completed operations.
|
||||
yield: Gives control to other threads between polling, if any are waiting.
|
||||
block: Lets the thread sleep until the GPU driver signals completion.
|
||||
"""
|
||||
if mode == -1 or mode == 'none' or not cuda_ok:
|
||||
return
|
||||
try:
|
||||
import ctypes
|
||||
log.info(f'Set cuda synch: mode={mode}')
|
||||
torch.cuda.set_device(torch.device(get_optimal_device_name()))
|
||||
ctypes.CDLL('libcudart.so').cudaSetDeviceFlags({'auto': 0, 'spin': 1, 'yield': 2, 'block': 4}[mode])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def test_fp16():
|
||||
if shared.cmd_opts.experimental:
|
||||
return True
|
||||
@@ -272,6 +291,9 @@ dtype = torch.float16
|
||||
dtype_vae = torch.float16
|
||||
dtype_unet = torch.float16
|
||||
unet_needs_upcast = False
|
||||
if args.profile:
|
||||
log.info(f'Torch build config: {torch.__config__.show()}')
|
||||
# set_cuda_sync_mode('block') # none/auto/spin/yield/block
|
||||
|
||||
|
||||
def cond_cast_unet(tensor):
|
||||
|
||||
@@ -55,3 +55,34 @@ def run(code, task):
|
||||
|
||||
def exception(suppress=[]): # noqa: B006
|
||||
console.print_exception(show_locals=False, max_frames=10, extra_lines=2, suppress=suppress, theme="ansi_dark", word_wrap=False, width=min([console.width, 200]))
|
||||
|
||||
|
||||
def profile(profiler, msg: str):
|
||||
profiler.disable()
|
||||
import io
|
||||
import pstats
|
||||
stream = io.StringIO() # pylint: disable=abstract-class-instantiated
|
||||
p = pstats.Stats(profiler, stream=stream)
|
||||
p.sort_stats(pstats.SortKey.CUMULATIVE)
|
||||
p.print_stats(100)
|
||||
# p.print_title()
|
||||
# p.print_call_heading(10, 'time')
|
||||
# p.print_callees(10)
|
||||
# p.print_callers(10)
|
||||
profiler = None
|
||||
lines = stream.getvalue().split('\n')
|
||||
lines = [l for l in lines if '<frozen' not in l and '{built-in' not in l and '/logging' not in l and 'Ordered by' not in l and 'List reduced' not in l and '_lsprof' not in l and '/profiler' not in l and 'rich' not in l and l.strip() != '']
|
||||
txt = '\n'.join(lines[:min(5, len(lines))])
|
||||
log.debug(f'Profile {msg}: {txt}')
|
||||
|
||||
|
||||
def profile_torch(profiler, msg: str):
|
||||
profiler.stop()
|
||||
from rich import print # pylint: disable=redefined-builtin
|
||||
# lines = profiler.key_averages().table(sort_by="self_cuda_time_total", row_limit=6)
|
||||
lines = profiler.key_averages().table(sort_by="self_cpu_time_total", row_limit=12)
|
||||
lines = lines.split('\n')
|
||||
lines = [l for l in lines if '/profiler' not in l and '---' not in l]
|
||||
txt = '\n'.join(lines)
|
||||
# print(f'Torch {msg}:', txt)
|
||||
log.debug(f'Torch profile {msg}: \n{txt}')
|
||||
|
||||
@@ -42,3 +42,16 @@ errors.install([gradio])
|
||||
import diffusers # pylint: disable=W0611,C0411
|
||||
timer.startup.record("diffusers")
|
||||
errors.log.info(f'Load packages: torch={getattr(torch, "__long_version__", torch.__version__)} diffusers={diffusers.__version__} gradio={gradio.__version__}')
|
||||
|
||||
try:
|
||||
import os
|
||||
import math
|
||||
cores = os.cpu_count()
|
||||
affinity = len(os.sched_getaffinity(0))
|
||||
threads = torch.get_num_threads()
|
||||
if threads < (affinity / 2):
|
||||
torch.set_num_threads(math.floor(affinity / 2))
|
||||
threads = torch.get_num_threads()
|
||||
errors.log.debug(f'Detected: cores={cores} affinity={affinity} set threads={threads}')
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
+1
-1
Submodule modules/lora updated: 95ae56bd22...0908c5414d
@@ -574,6 +574,7 @@ def move_files(src_path: str, dest_path: str, ext_filter: str = None):
|
||||
|
||||
def load_upscalers():
|
||||
# We can only do this 'magic' method to dynamically load upscalers if they are referenced, so we'll try to import any _model.py files before looking in __subclasses__
|
||||
t0 = time.time()
|
||||
modules_dir = os.path.join(shared.script_path, "modules", "postprocess")
|
||||
for file in os.listdir(modules_dir):
|
||||
if "_model.py" in file:
|
||||
@@ -602,4 +603,5 @@ def load_upscalers():
|
||||
datas += scaler.scalers
|
||||
names.append(name[8:])
|
||||
shared.sd_upscalers = sorted(datas, key=lambda x: x.name.lower() if not isinstance(x.scaler, (UpscalerNone, UpscalerLanczos, UpscalerNearest)) else "") # Special case for UpscalerNone keeps it at the beginning of the list.
|
||||
shared.log.debug(f"Load upscalers: total={len(shared.sd_upscalers)} downloaded={len([x for x in shared.sd_upscalers if x.data_path is not None and os.path.isfile(x.data_path)])} user={len([x for x in shared.sd_upscalers if x.custom])} {names}")
|
||||
t1 = time.time()
|
||||
shared.log.debug(f"Load upscalers: total={len(shared.sd_upscalers)} downloaded={len([x for x in shared.sd_upscalers if x.data_path is not None and os.path.isfile(x.data_path)])} user={len([x for x in shared.sd_upscalers if x.custom])} time={t1-t0:.2f} {names}")
|
||||
|
||||
+15
-41
@@ -18,7 +18,7 @@ from ldm.models.diffusion.ddpm import LatentDepth2ImageDiffusion
|
||||
from einops import repeat, rearrange
|
||||
from blendmodes.blend import blendLayers, BlendType
|
||||
from installer import git_commit
|
||||
from modules import shared, devices
|
||||
from modules import shared, devices, errors
|
||||
import modules.memstats
|
||||
import modules.lowvram
|
||||
import modules.masking
|
||||
@@ -666,36 +666,6 @@ def create_infotext(p: StableDiffusionProcessing, all_prompts=None, all_seeds=No
|
||||
return infotext
|
||||
|
||||
|
||||
"""
|
||||
def print_profile(profile, msg: str):
|
||||
try:
|
||||
from rich import print # pylint: disable=redefined-builtin
|
||||
except Exception:
|
||||
pass
|
||||
lines = profile.key_averages().table(sort_by="cuda_time_total", row_limit=20)
|
||||
lines = lines.split('\n')
|
||||
lines = [l for l in lines if '/profiler' not in l]
|
||||
print(f'Profile {msg}:', '\n'.join(lines))
|
||||
"""
|
||||
|
||||
|
||||
def print_profile(profile, msg: str):
|
||||
import io
|
||||
import pstats
|
||||
try:
|
||||
from rich import print # pylint: disable=redefined-builtin
|
||||
except Exception:
|
||||
pass
|
||||
profile.disable()
|
||||
stream = io.StringIO() # pylint: disable=abstract-class-instantiated
|
||||
ps = pstats.Stats(profile, stream=stream)
|
||||
ps.sort_stats(pstats.SortKey.CUMULATIVE).print_stats(15)
|
||||
profile = None
|
||||
lines = stream.getvalue().split('\n')
|
||||
lines = [line for line in lines if '<frozen' not in line and '{built-in' not in line and '/logging' not in line and '/rich' not in line]
|
||||
print(f'Profile {msg}:', '\n'.join(lines))
|
||||
|
||||
|
||||
def process_images(p: StableDiffusionProcessing) -> Processed:
|
||||
if not hasattr(p.sd_model, 'sd_checkpoint_info'):
|
||||
return None
|
||||
@@ -743,22 +713,26 @@ def process_images(p: StableDiffusionProcessing) -> Processed:
|
||||
modules.script_callbacks.before_process_callback(p)
|
||||
|
||||
if shared.cmd_opts.profile:
|
||||
"""
|
||||
import torch.profiler # pylint: disable=redefined-outer-name
|
||||
with torch.profiler.profile(profile_memory=True, with_modules=True) as prof:
|
||||
with torch.profiler.record_function("process_images"):
|
||||
res = process_images_inner(p)
|
||||
print_profile(prof, 'process_images')
|
||||
"""
|
||||
import cProfile
|
||||
pr = cProfile.Profile()
|
||||
pr.enable()
|
||||
profile_python = cProfile.Profile()
|
||||
profile_python.enable()
|
||||
with context_hypertile_vae(p), context_hypertile_unet(p):
|
||||
import torch.profiler # pylint: disable=redefined-outer-name
|
||||
activities=[torch.profiler.ProfilerActivity.CPU]
|
||||
if torch.cuda.is_available():
|
||||
activities.append(torch.profiler.ProfilerActivity.CUDA)
|
||||
shared.log.debug(f'Torch profile: activities={activities}')
|
||||
if shared.profiler is None:
|
||||
shared.profiler = torch.profiler.profile(activities=activities, profile_memory=True, with_modules=True)
|
||||
shared.profiler.start()
|
||||
shared.profiler.step()
|
||||
res = process_images_inner(p)
|
||||
print_profile(pr, 'Torch')
|
||||
errors.profile_torch(shared.profiler, 'Process')
|
||||
errors.profile(profile_python, 'Process')
|
||||
else:
|
||||
with context_hypertile_vae(p), context_hypertile_unet(p):
|
||||
res = process_images_inner(p)
|
||||
|
||||
finally:
|
||||
if not shared.opts.cuda_compile:
|
||||
modules.sd_models.apply_token_merging(p.sd_model, 0)
|
||||
|
||||
@@ -85,6 +85,8 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro
|
||||
return kwargs
|
||||
kwargs = correction_callback(p, timestep, kwargs)
|
||||
shared.state.current_latent = kwargs['latents']
|
||||
if shared.cmd_opts.profile and shared.profiler is not None:
|
||||
shared.profiler.step()
|
||||
return kwargs
|
||||
|
||||
def full_vae_decode(latents, model):
|
||||
@@ -139,6 +141,7 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro
|
||||
return encoded
|
||||
|
||||
def vae_decode(latents, model, output_type='np', full_quality=True):
|
||||
t0 = time.time()
|
||||
prev_job = shared.state.job
|
||||
shared.state.job = 'vae'
|
||||
if not torch.is_tensor(latents): # already decoded
|
||||
@@ -163,6 +166,9 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro
|
||||
# decoded = validate_sample(decoded)
|
||||
imgs = model.image_processor.postprocess(decoded, output_type=output_type)
|
||||
shared.state.job = prev_job
|
||||
if shared.cmd_opts.profile:
|
||||
t1 = time.time()
|
||||
shared.log.debug(f'Profile: VAE decode: {t1-t0:.2f}')
|
||||
return imgs
|
||||
|
||||
def vae_encode(image, model, full_quality=True): # pylint: disable=unused-variable
|
||||
@@ -269,6 +275,7 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro
|
||||
return task_args
|
||||
|
||||
def set_pipeline_args(model, prompts: list, negative_prompts: list, prompts_2: typing.Optional[list]=None, negative_prompts_2: typing.Optional[list]=None, desc:str='', **kwargs):
|
||||
t0 = time.time()
|
||||
if hasattr(model, "set_progress_bar_config"):
|
||||
model.set_progress_bar_config(bar_format='Progress {rate_fmt}{postfix} {bar} {percentage:3.0f}% {n_fmt}/{total_fmt} {elapsed} {remaining} ' + '\x1b[38;5;71m' + desc, ncols=80, colour='#327fba')
|
||||
args = {}
|
||||
@@ -379,6 +386,9 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro
|
||||
shared.log.debug(txt)
|
||||
# components = [{ k: getattr(v, 'device', None) } for k, v in model.components.items()]
|
||||
# shared.log.debug(f'Diffuser pipeline components: {components}')
|
||||
if shared.cmd_opts.profile:
|
||||
t1 = time.time()
|
||||
shared.log.debug(f'Profile: pipeline args: {t1-t0:.2f}')
|
||||
return args
|
||||
|
||||
def recompile_model(hires=False):
|
||||
@@ -502,7 +512,11 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro
|
||||
p.extra_generation_params['Pipeline'] = shared.sd_model.__class__.__name__
|
||||
p.extra_generation_params["Sampler Eta"] = shared.opts.scheduler_eta if shared.opts.scheduler_eta is not None and shared.opts.scheduler_eta > 0 and shared.opts.scheduler_eta < 1 else None
|
||||
try:
|
||||
t0 = time.time()
|
||||
output = shared.sd_model(**base_args) # pylint: disable=not-callable
|
||||
if shared.cmd_opts.profile:
|
||||
t1 = time.time()
|
||||
shared.log.debug(f'Profile: pipeline call: {t1-t0:.2f}')
|
||||
if not hasattr(output, 'images') and hasattr(output, 'frames'):
|
||||
shared.log.debug(f'Generated: frames={len(output.frames[0])}')
|
||||
output.images = output.frames[0]
|
||||
|
||||
@@ -329,7 +329,7 @@ def before_ui_callback():
|
||||
|
||||
|
||||
def add_callback(callbacks, fun):
|
||||
stack = [x for x in inspect.stack() if x.filename != __file__]
|
||||
stack = [x for x in inspect.stack(0) if x.filename != __file__]
|
||||
filename = stack[0].filename if len(stack) > 0 else 'unknown file'
|
||||
callbacks.append(ScriptCallback(filename, fun))
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import os
|
||||
import contextlib
|
||||
import importlib.util
|
||||
import modules.errors as errors
|
||||
from installer import setup_logging
|
||||
from installer import setup_logging, args
|
||||
|
||||
|
||||
preloaded = []
|
||||
@@ -12,6 +12,10 @@ preloaded = []
|
||||
def load_module(path):
|
||||
module_spec = importlib.util.spec_from_file_location(os.path.basename(path), path)
|
||||
module = importlib.util.module_from_spec(module_spec)
|
||||
if args.profile:
|
||||
import cProfile
|
||||
pr = cProfile.Profile()
|
||||
pr.enable()
|
||||
try:
|
||||
if '/sd-extension-' in path: # safe extensions without stdout intercept
|
||||
module_spec.loader.exec_module(module)
|
||||
@@ -25,6 +29,8 @@ def load_module(path):
|
||||
errors.log.info(f"Extension: script='{os.path.relpath(path)}' {line.strip()}")
|
||||
except Exception as e:
|
||||
errors.display(e, f'Module load: {path}')
|
||||
if args.profile:
|
||||
errors.profile(pr, f'Scripts: {path}')
|
||||
return module
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -261,6 +261,7 @@ def load_scripts():
|
||||
elif issubclass(script_class, scripts_postprocessing.ScriptPostprocessing):
|
||||
postprocessing_scripts_data.append(ScriptClassData(script_class, scriptfile.path, scriptfile.basedir, module))
|
||||
|
||||
from installer import args
|
||||
for scriptfile in scripts_list:
|
||||
try:
|
||||
if scriptfile.basedir != paths.script_path:
|
||||
@@ -274,12 +275,10 @@ def load_scripts():
|
||||
current_basedir = paths.script_path
|
||||
t.record(os.path.basename(scriptfile.basedir))
|
||||
sys.path = syspath
|
||||
|
||||
global scripts_txt2img, scripts_img2img, scripts_postproc # pylint: disable=global-statement
|
||||
scripts_txt2img = ScriptRunner()
|
||||
scripts_img2img = ScriptRunner()
|
||||
scripts_postproc = scripts_postprocessing.ScriptPostprocessingRunner()
|
||||
|
||||
return t, time.time()-t0
|
||||
|
||||
|
||||
|
||||
@@ -760,6 +760,10 @@ def set_diffuser_options(sd_model, vae, op: str):
|
||||
|
||||
def load_diffuser(checkpoint_info=None, already_loaded_state_dict=None, timer=None, op='model'): # pylint: disable=unused-argument
|
||||
import torch # pylint: disable=reimported,redefined-outer-name
|
||||
if shared.cmd_opts.profile:
|
||||
import cProfile
|
||||
pr = cProfile.Profile()
|
||||
pr.enable()
|
||||
if timer is None:
|
||||
timer = Timer()
|
||||
logging.getLogger("diffusers").setLevel(logging.ERROR)
|
||||
@@ -976,6 +980,8 @@ def load_diffuser(checkpoint_info=None, already_loaded_state_dict=None, timer=No
|
||||
|
||||
timer.record("load")
|
||||
devices.torch_gc(force=True)
|
||||
if shared.cmd_opts.profile:
|
||||
errors.profile(pr, 'Load')
|
||||
script_callbacks.model_loaded_callback(sd_model)
|
||||
shared.log.info(f"Load {op}: time={timer.summary()} native={get_native(sd_model)} {memory_stats()}")
|
||||
|
||||
|
||||
@@ -781,6 +781,7 @@ class Options:
|
||||
value = expected_type(value)
|
||||
return value
|
||||
|
||||
profiler = None
|
||||
opts = Options()
|
||||
config_filename = cmd_opts.config
|
||||
opts.load(config_filename)
|
||||
@@ -804,6 +805,7 @@ device = devices.device
|
||||
batch_cond_uncond = opts.always_batch_cond_uncond or not (cmd_opts.lowvram or cmd_opts.medvram)
|
||||
parallel_processing_allowed = not cmd_opts.lowvram
|
||||
mem_mon = modules.memmon.MemUsageMonitor("MemMon", devices.device)
|
||||
max_workers = 2
|
||||
if devices.backend == "directml":
|
||||
directml_do_hijack()
|
||||
|
||||
|
||||
+25
-12
@@ -4,6 +4,7 @@ import re
|
||||
import os
|
||||
import csv
|
||||
import json
|
||||
import time
|
||||
from installer import log
|
||||
|
||||
|
||||
@@ -87,6 +88,7 @@ class StyleDatabase:
|
||||
|
||||
def load_style(self, fn, prefix=None):
|
||||
with open(fn, 'r', encoding='utf-8') as f:
|
||||
new_style = None
|
||||
try:
|
||||
all_styles = json.load(f)
|
||||
if type(all_styles) is dict:
|
||||
@@ -100,7 +102,7 @@ class StyleDatabase:
|
||||
name = os.path.join(prefix, name)
|
||||
else:
|
||||
name = os.path.join(os.path.dirname(os.path.relpath(fn, self.path)), name)
|
||||
self.styles[style["name"]] = Style(
|
||||
new_style = Style(
|
||||
name=name,
|
||||
desc=style.get('description', name),
|
||||
prompt=style.get("prompt", ""),
|
||||
@@ -110,26 +112,37 @@ class StyleDatabase:
|
||||
filename=fn,
|
||||
mtime=os.path.getmtime(fn),
|
||||
)
|
||||
self.styles[style["name"]] = new_style
|
||||
except Exception as e:
|
||||
log.error(f'Failed to load style: file={fn} error={e}')
|
||||
return new_style
|
||||
|
||||
|
||||
def reload(self):
|
||||
t0 = time.time()
|
||||
self.styles.clear()
|
||||
|
||||
def list_folder(folder):
|
||||
for filename in os.listdir(folder):
|
||||
fn = os.path.abspath(os.path.join(folder, filename))
|
||||
if os.path.isfile(fn) and fn.lower().endswith(".json"):
|
||||
self.load_style(fn)
|
||||
elif os.path.isdir(fn) and not fn.startswith('.'):
|
||||
list_folder(fn)
|
||||
import concurrent
|
||||
future_items = {}
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor:
|
||||
for filename in os.listdir(folder):
|
||||
fn = os.path.abspath(os.path.join(folder, filename))
|
||||
if os.path.isfile(fn) and fn.lower().endswith(".json"):
|
||||
future_items[executor.submit(self.load_style, fn, None)] = fn
|
||||
# self.load_style(fn)
|
||||
elif os.path.isdir(fn) and not fn.startswith('.'):
|
||||
list_folder(fn)
|
||||
self.styles = dict(sorted(self.styles.items(), key=lambda style: style[1].filename))
|
||||
if self.built_in:
|
||||
fn = os.path.join('html', 'art-styles.json')
|
||||
future_items[executor.submit(self.load_style, fn, 'built-in')] = fn
|
||||
for future in concurrent.futures.as_completed(future_items):
|
||||
future.result()
|
||||
|
||||
list_folder(self.path)
|
||||
self.styles = dict(sorted(self.styles.items(), key=lambda style: style[1].filename))
|
||||
if self.built_in:
|
||||
self.load_style(os.path.join('html', 'art-styles.json'), 'built-in')
|
||||
|
||||
log.debug(f'Load styles: folder="{self.path}" items={len(self.styles.keys())}')
|
||||
t1 = time.time()
|
||||
log.debug(f'Load styles: folder="{self.path}" items={len(self.styles.keys())} time={t1-t0:.2f}')
|
||||
|
||||
def find_style(self, name):
|
||||
found = [style for style in self.styles.values() if style.name == name]
|
||||
|
||||
@@ -15,7 +15,7 @@ from collections import OrderedDict
|
||||
import gradio as gr
|
||||
from PIL import Image
|
||||
from starlette.responses import FileResponse, JSONResponse
|
||||
from modules import paths, shared, scripts, modelloader
|
||||
from modules import paths, shared, scripts, modelloader, errors
|
||||
from modules.ui_components import ToolButton
|
||||
import modules.ui_symbols as symbols
|
||||
|
||||
@@ -270,7 +270,7 @@ class ExtraNetworksPage:
|
||||
self.html = f"<div id='{tabname}_{self_name_id}_subdirs' class='extra-network-subdirs'>{subdirs_html}</div><div id='{tabname}_{self_name_id}_cards' class='extra-network-cards'>{self.html}</div>"
|
||||
else:
|
||||
return ''
|
||||
shared.log.debug(f"Extra networks: page='{self.name}' items={len(self.items)} subfolders={len(subdirs)} tab={tabname} folders={self.allowed_directories_for_previews()} list={self.list_time:.2f} desc={self.desc_time:.2f} info={self.info_time:.2f}")
|
||||
shared.log.debug(f"Extra networks: page='{self.name}' items={len(self.items)} subfolders={len(subdirs)} tab={tabname} folders={self.allowed_directories_for_previews()} list={self.list_time:.2f} desc={self.desc_time:.2f} info={self.info_time:.2f} workers={shared.max_workers}")
|
||||
if len(self.missing_thumbs) > 0:
|
||||
threading.Thread(target=self.create_thumb).start()
|
||||
return self.html
|
||||
@@ -463,6 +463,10 @@ def create_ui(container, button_parent, tabname, skip_indexing = False):
|
||||
ui.tabs = gr.Tabs(elem_id=tabname+"_extra_tabs")
|
||||
ui.button_details = gr.Button('Details', elem_id=tabname+"_extra_details_btn", visible=False)
|
||||
state = {}
|
||||
if shared.cmd_opts.profile:
|
||||
import cProfile
|
||||
pr = cProfile.Profile()
|
||||
pr.enable()
|
||||
|
||||
def get_item(state, params = None):
|
||||
if params is not None and type(params) == dict:
|
||||
@@ -567,6 +571,10 @@ def create_ui(container, button_parent, tabname, skip_indexing = False):
|
||||
page_html = gr.HTML(page.html, elem_id=f'{tabname}{page.name}_extra_page', elem_classes="extra-networks-page")
|
||||
ui.pages.append(page_html)
|
||||
tab.select(ui_tab_change, _js="getENActivePage", inputs=[ui.button_details], outputs=[ui.button_scan, ui.button_save, ui.button_model])
|
||||
if shared.cmd_opts.profile:
|
||||
errors.profile(pr, 'ExtraNetworks')
|
||||
pr.disable()
|
||||
|
||||
# ui.tabs.change(fn=ui_tab_change, inputs=[], outputs=[ui.button_scan, ui.button_save])
|
||||
|
||||
def fn_save_img(image):
|
||||
|
||||
@@ -64,7 +64,7 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
|
||||
return record
|
||||
|
||||
def list_items(self):
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor:
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=shared.max_workers) as executor:
|
||||
future_items = {executor.submit(self.create_item, cp): cp for cp in list(sd_models.checkpoints_list.copy())}
|
||||
for future in concurrent.futures.as_completed(future_items):
|
||||
item = future.result()
|
||||
|
||||
@@ -95,7 +95,7 @@ class ExtraNetworksPageStyles(ui_extra_networks.ExtraNetworksPage):
|
||||
return item
|
||||
|
||||
def list_items(self):
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor:
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=shared.max_workers) as executor:
|
||||
future_items = {executor.submit(self.create_item, style): style for style in list(shared.prompt_styles.styles)}
|
||||
for future in concurrent.futures.as_completed(future_items):
|
||||
item = future.result()
|
||||
|
||||
@@ -68,7 +68,7 @@ class ExtraNetworksPageTextualInversion(ui_extra_networks.ExtraNetworksPage):
|
||||
self.embeddings = []
|
||||
self.embeddings = sorted(self.embeddings, key=lambda emb: emb.filename)
|
||||
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor:
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=shared.max_workers) as executor:
|
||||
future_items = {executor.submit(self.create_item, net): net for net in self.embeddings}
|
||||
for future in concurrent.futures.as_completed(future_items):
|
||||
item = future.result()
|
||||
|
||||
@@ -311,6 +311,9 @@ def webui(restart=False):
|
||||
modules.sd_models.write_metadata()
|
||||
load_model()
|
||||
shared.opts.save(shared.config_filename)
|
||||
if cmd_opts.profile:
|
||||
for k, v in modules.script_callbacks.callback_map.items():
|
||||
shared.log.debug(f'Registered callbacks: {k}={len(v)} {[c.script for c in v]}')
|
||||
log.info(f"Startup time: {timer.startup.summary()}")
|
||||
debug = log.info if os.environ.get('SD_SCRIPT_DEBUG', None) is not None else lambda *args, **kwargs: None
|
||||
debug('Loaded scripts:')
|
||||
|
||||
Reference in New Issue
Block a user