feat(te): add an option to run encoder calls without torch.compile

SDNQ compiles its helpers for static shapes, so an encode at a new prompt length or condition-image size recompiles them; on a long-running server each new length costs tens of seconds and logs the long-encode warning. With torch_skip_compile_te on (Compute Settings, next to the Triton autotune skips, off by default), hijack_encode_prompt runs the encoder under torch.compiler.set_stance("force_eager"): warm encodes are as fast as compiled ones and the denoiser keeps its compiled kernels. An encoder ticked under Compile Model keeps its compile.
This commit is contained in:
CalamitousFelicitousness
2026-10-04 19:17:34 +01:00
parent 10f22af07d
commit 4c8172154e
4 changed files with 13 additions and 1 deletions
+1
View File
@@ -21,6 +21,7 @@
- zluda should only be used on older amd gpus not supported by rocm/windows
- **Compute**
- sdnq: support double-quant, including `nvfp4`
- text encoder: *skip torch compile for TE* option runs encoder calls without torch.compile, so a new prompt length or image size does not trigger a recompile, see *settings -> compute settings*
- **Fixes**
- schedulers: update init signature for new configuration options
- rocm: remove incompatible env flags
+10 -1
View File
@@ -1,5 +1,7 @@
import os
import time
import contextlib
import torch
from modules import shared, errors, timer, sd_models
from modules.logger import log
from modules.attention import context as attention_context
@@ -51,6 +53,13 @@ class PromptCache:
prompt_cache = PromptCache()
def encode_stance():
# sdnq compiles its helpers for static shapes, so a compiled encode recompiles for every new prompt length or image size and runs no faster once warm
if not shared.opts.torch_skip_compile_te or 'TE' in shared.opts.cuda_compile or not hasattr(torch.compiler, 'set_stance'): # an encoder compiled through compile model keeps its compile
return contextlib.nullcontext()
return torch.compiler.set_stance('force_eager')
def hijack_encode_prompt(*args, **kwargs):
jobid = shared.state.begin('TE Encode')
t0 = time.time()
@@ -85,7 +94,7 @@ def hijack_encode_prompt(*args, **kwargs):
log.debug(f'Encode: prompt={prompt} hijack=True')
else:
log.debug(f'Encode: prompt="{prompt}" hijack=True')
with attention_context.role('te'):
with attention_context.role('te'), encode_stance():
if hasattr(shared.sd_model, 'orig_encode_prompt'):
res = shared.sd_model.orig_encode_prompt(*args_copy, **kwargs)
else:
+1
View File
@@ -298,6 +298,7 @@ def create_settings(cmd_opts):
"torch_sync": OptionInfo(True, "Force synchronize"),
"triton_skip_autotune": OptionInfo(False, "Skip Triton autotune", gr.Checkbox),
"triton_skip_autotune_te": OptionInfo(False, "Skip Triton autotune for TE", gr.Checkbox),
"torch_skip_compile_te": OptionInfo(False, "Skip Torch compile for TE", 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}),
+1
View File
@@ -1759,6 +1759,7 @@
{"id": "", "label": "Skip guidance layers", "localized": "", "hint": "Comma-separated layer indices where guidance skip is applied", "ui": "script_slg"},
{"id": "", "label": "Skip input frames", "localized": "", "hint": "Number of input frames to skip between each processed frame when the input is a video.<br>Use to thin out long source videos: only every (N+1)-th frame is processed and the rest are dropped.<br><br>Set to <b>0</b> to process every frame. Set to <b>1</b> to process every other frame, <b>2</b> for every third, and so on.<br>Default 0.", "ui": "control"},
{"id": "", "label": "Skip input processing", "localized": "", "hint": "Passes every input image to the pipeline as given: control processors, resize before and the mask are not applied.<br>Useful when the image is already preprocessed externally (depth map, canny edges, openpose skeleton). The input still routes through any selected <i>ControlNet</i>/<i>T2I-Adapter</i>/etc. model.<br>Multi-image models generate at the size set on the Initial sub-tab of the Size accordion; other models generate at the size of the first image.<br><br>Default off.", "ui": "control"},
{"id": "", "label": "Skip Torch compile for TE", "localized": "", "hint": "Runs text encoder with <i>torch.compile</i> turned off.<br><br>Disabled by default.", "ui": "settings_backends"},
{"id": "", "label": "Skip Triton autotune", "localized": "", "hint": "Bypass Triton kernel autotuning to reduce initial compilation warmup latency"},
{"id": "", "label": "Skip Triton autotune for TE", "localized": "", "hint": "Bypass Triton autotuning specifically for text encoder kernels"},
{"id": "", "label": "SLG config", "localized": "", "hint": "Preset configuration profile for Skip-Layer Guidance", "ui": "txt2img"},