video: gate 'auto' attention on diffusers' real Sage usability

The 'auto' attention-backend resolver picked 'sage' whenever the
sageattention package was merely importable. But diffusers requires a
specific version with compiled CUDA kernels (0.38 needs >=2.1.1); an old
v1 wheel is importable yet rejected, which would silently drop to plain
SDPA instead of Flash. Gate on diffusers' own _CAN_USE_SAGE_ATTN (with an
is_sageattention_version fallback) so 'auto' chooses sage only when it can
actually dispatch, else flash, else SDPA.

SageAttention 2.2.0 is now built from source in the venv (CUDA kernels,
TORCH_CUDA_ARCH_LIST=8.6), so 'auto' resolves to sage on this host.
Co-Authored-By: 's avatarClaude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RdMufYvtTbtGDWsiZVoXce
parent fe2cdee1
...@@ -871,7 +871,12 @@ def _resolve_attn_backend(model_cfg: dict): ...@@ -871,7 +871,12 @@ def _resolve_attn_backend(model_cfg: dict):
return None return None
if val == 'auto': if val == 'auto':
import importlib.util as _u import importlib.util as _u
if _u.find_spec('sageattention') is not None: # Prefer Sage ONLY when diffusers can actually use it: it requires a
# specific SageAttention version with compiled CUDA kernels (e.g. 0.38
# needs >=2.1.1). Merely having the package importable is NOT enough — an
# old v1 wheel would be rejected by diffusers and silently drop us to
# plain SDPA instead of Flash. So gate on diffusers' own capability flag.
if _sage_usable():
return 'sage' return 'sage'
if _u.find_spec('flash_attn') is not None: if _u.find_spec('flash_attn') is not None:
return 'flash' return 'flash'
...@@ -879,6 +884,21 @@ def _resolve_attn_backend(model_cfg: dict): ...@@ -879,6 +884,21 @@ def _resolve_attn_backend(model_cfg: dict):
return val return val
def _sage_usable() -> bool:
"""True only when diffusers can actually dispatch to SageAttention (correct
version + compiled kernels importable)."""
try:
from diffusers.models.attention_dispatch import _CAN_USE_SAGE_ATTN
return bool(_CAN_USE_SAGE_ATTN)
except Exception:
try:
from diffusers.utils import import_utils as _iu
return bool(_iu.is_sageattention_available()
and _iu.is_sageattention_version(">=", "2.1.1"))
except Exception:
return False
def _apply_attention_backend(pipe, model_cfg: dict) -> None: def _apply_attention_backend(pipe, model_cfg: dict) -> None:
"""Switch the Wan transformer(s) to a faster attention backend (diffusers 0.38+ """Switch the Wan transformer(s) to a faster attention backend (diffusers 0.38+
dispatcher). Best-effort and per-component: if a backend isn't available it dispatcher). Best-effort and per-component: if a backend isn't available it
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment