diff --git a/CHANGELOG.md b/CHANGELOG.md index 08582e5b6..73c7025c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # Change Log for SD.Next -## Update for 2026-09-04 +## Update for 2026-09-05 -### Highlights for 2026-09-04 +### Highlights for 2026-09-05 All-about-optimizations: - improved LoRA performance and quality, especially with quantized models @@ -11,8 +11,11 @@ All-about-optimizations: - support for different caching stacks - compute updates across the board -### Details for 2026-09-04 +### Details for 2026-09-05 +- **Models** + - [Anima 2.9B Preview v1](https://huggingface.co/yeoj34760/Anima-2.9B) + expanded version of Anima 2B - **LoRA** - *TODO*: see [LoRA docs](https://vladmandic.github.io/sdnext-docs/LoRA) for all of the improvements and usage instructions *note*: lora now has its own settings section in *settings -> lora* @@ -48,9 +51,11 @@ All-about-optimizations: - **Compute** - cuda: update `torch==2.14.0` with `cuda==13.2` - openvino: update `openvino==2026.3.1` with `torch==2.13.0` - - add `SD_SKIP_AUTOTUNE` env variable to skip triton autotune and use default config for all triton kernels + - option to skip triton autotune and use default config for all triton kernels + in *settings -> compute settings* *note*: this may improve initial generate time, but may also reduce performance on some models - - new optional transformer hooks: *settings -> compute add-ons* + - new optional transformer hooks + in *settings -> compute add-ons* *PAG: Perturbed attention guidance, PAB: Pyramid attention broadcast, FBC: First Block Cache, FC: Faster Cache, LS: Layer Skip, MC: Mag Cache, TS: TaylorSeer* *note*: compatibility of different methods varies across different models - update `numpy` and `scipy` frozen requirements as required by new compute drivers diff --git a/modules/attention/dispatcher.py b/modules/attention/dispatcher.py index ad5082d2c..94c817949 100644 --- a/modules/attention/dispatcher.py +++ b/modules/attention/dispatcher.py @@ -111,9 +111,9 @@ def set_attention_dispatcher(pipe): current = a._AttentionBackendRegistry.get_active_backend() # pylint: disable=protected-access log.debug(f'Attention dispatcher: target={attn} previous={prev[0].value} active={current[0]} list={backends}') elif len(attn) > 0: - log.warning(f'Attention dispatcher: active={prev[0].value} list={backends} target={attn} not found') + log.warning(f'Attention dispatcher: active={prev[0].value} kernels={backends} target={attn} not found') else: - log.debug(f'Attention dispatcher: active={prev[0].value} list={backends}') + log.debug(f'Attention dispatcher: active={prev[0].value} kernels={backends}') def list_dispatcher_backends() -> list: diff --git a/modules/attention/registry.py b/modules/attention/registry.py index 2403cde85..c4455cd99 100644 --- a/modules/attention/registry.py +++ b/modules/attention/registry.py @@ -69,6 +69,9 @@ class AttentionBackend: def available_on(self, platform: Platform) -> bool: return self.platforms is None or platform.backend in self.platforms + def __repr__(self) -> str: + return f'AttentionBackend(name="{self.name}" label="{self.label}" priority={self.priority} terminal={self.terminal} platforms={list(self.platforms) if self.platforms is not None else []} options={self.options} caps={list(self.caps)})' + class Registry: def __init__(self): @@ -98,5 +101,8 @@ class Registry: def with_cap(self, cap: str) -> list[AttentionBackend]: return [backend for backend in self.ordered() if cap in backend.caps] + def __repr__(self) -> str: + return f'Registry(backends={list(self.backends.keys())})' + registry = Registry() diff --git a/modules/loader.py b/modules/loader.py index 3a9689930..b0960f7d4 100644 --- a/modules/loader.py +++ b/modules/loader.py @@ -133,13 +133,6 @@ if ".dev" in torch.__version__ or "+git" in torch.__version__: torch.__version__ = re.search(r'[\d.]+[\d]', torch.__version__).group(0) timer.startup.record("torch") -try: - from modules.sd_hijack_triton import install as install_autotune_report # pylint: disable=ungrouped-imports - install_autotune_report() -except Exception as e: - log.warning(f'Triton logging: {e}') -timer.startup.record("triton") - try: import bitsandbytes # pylint: disable=unused-import _bnb = True @@ -201,8 +194,6 @@ except Exception as e: _onnx = False timer.startup.record("onnx") -timer.startup.record("fastapi") - import gradio # pylint: disable=W0611,C0411 timer.startup.record("gradio") errors.install([gradio]) @@ -237,6 +228,13 @@ diffusers.utils.import_utils._sdnq_available = True # pylint: disable=protected- diffusers.utils.import_utils._sdnq_version = sdnq.__version__ # pylint: disable=protected-access timer.startup.record("sdnq") +try: + from modules.sd_hijack_triton import install as install_autotune_report # pylint: disable=ungrouped-imports + install_autotune_report() +except Exception as e: + log.warning(f'Triton logging: {e}') +timer.startup.record("triton") + try: import pillow_jxl # pylint: disable=W0611,C0411 except Exception: diff --git a/modules/sd_hijack_triton.py b/modules/sd_hijack_triton.py index 2fad5ba3c..cdd66f8c7 100644 --- a/modules/sd_hijack_triton.py +++ b/modules/sd_hijack_triton.py @@ -156,6 +156,7 @@ def run_hook(orig): """Report the register use of the config a sweep just chose. n_regs and n_spills are filled in when the driver loads the binary, so they exist only once the kernel has run, not at compile.""" def wrapped(self, *args, **kwargs): + from modules import shared session = status['session'] if session is not None: stop_progress(session) @@ -172,7 +173,7 @@ def run_hook(orig): if hasattr(arg, 'dtype'): key += (str(arg.dtype),) needs_benchmark = len(self.configs) > 1 and key not in self.cache - skip_autotune = os.environ.get('SD_SKIP_AUTOTUNE', None) is not None + skip_autotune = (os.environ.get('SD_SKIP_AUTOTUNE', None) is not None) or shared.opts.triton_skip_autotune if needs_benchmark and skip_autotune: self.cache[key] = self.configs[0] # pre-seed the cache so orig() takes its cache-hit path and skips the sweep needs_benchmark = False diff --git a/modules/shared.py b/modules/shared.py index a3a40f643..246105c8d 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -10,8 +10,8 @@ from typing import TYPE_CHECKING import gradio as gr from installer import print_dict # pylint: disable=unused-import from modules.logger import log -log.debug('Initializing: shared module') +log.debug('Initializing: shared module') import modules.memmon import modules.paths as paths from modules.json_helpers import readfile # pylint: disable=W0611 @@ -19,6 +19,9 @@ from modules.shared_helpers import listdir, req # pylint: disable=W0611 from modules import errors, devices, shared_state, cmd_args, theme, history, files_cache # pylint: disable=unused-import from modules.memstats import memory_stats # pylint: disable=unused-import +# main entry point that triggers package imports +from modules import loader # pylint: disable=unused-import + log.debug('Initializing: pipelines') from modules import shared_items # pylint: disable=unused-import from modules.caption.openclip import get_clip_models, refresh_clip_models # pylint: disable=unused-import diff --git a/modules/ui_definitions.py b/modules/ui_definitions.py index 03aa08036..66088e8a8 100644 --- a/modules/ui_definitions.py +++ b/modules/ui_definitions.py @@ -287,6 +287,7 @@ def create_settings(cmd_opts): "diffusers_fuse_projections": OptionInfo(False, "Fused projections"), "torch_expandable_segments": OptionInfo(False, "Expandable segments"), "torch_sync": OptionInfo(True, "Force synchronize"), + "triton_skip_autotune": OptionInfo(False, "Skip Triton autotune", gr.Checkbox), "cudnn_enabled": OptionInfo("default", "cuDNN enabled", gr.Radio, {"choices": ["default", "true", "false"]}), "cudnn_benchmark": OptionInfo(devices.backend != "rocm", "cuDNN full-depth benchmark"), "cudnn_benchmark_limit": OptionInfo(10, "cuDNN benchmark limit", gr.Slider, {"minimum": 0, "maximum": 100, "step": 1}),