Skip to content

Commit df98367

Browse files
committed
updated the attetion implementation to support sage-attention-3
1 parent 8c8f997 commit df98367

1 file changed

Lines changed: 58 additions & 12 deletions

File tree

diffusers_helper/models/hunyuan_video_packed.py

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@
4040
flash2_attn_func = None
4141
flash4_attn_varlen_func = None
4242
flash4_attn_func = None
43-
sageattn_varlen = None
44-
sageattn = None
43+
sageattn1_varlen = None
44+
sageattn1 = None
45+
sageattn3 = None
4546

4647
try:
4748
# raise NotImplementedError
@@ -65,20 +66,38 @@
6566

6667
try:
6768
# raise NotImplementedError
68-
from sageattention import sageattn_varlen, sageattn
69+
from sageattention import (sageattn_varlen as sageattn1_varlen,
70+
sageattn as sageattn1)
6971
except:
7072
pass
7173

74+
try:
75+
from sageattn3 import sageattn3_blackwell as sageattn3
76+
except:
77+
pass
78+
79+
major, minor = torch.cuda.get_device_capability()
80+
arch = f"sm_{major}{minor}"
81+
if major == 10:
82+
s = "Datacenter Blackwell"
83+
elif major == 12:
84+
s = "Workstation/Consumer Blackwell"
85+
else:
86+
s = "Other architecture (Hopper, Ada, Ampere, etc.)"
87+
print(f"Detected CUDA Architecture: {arch} ({s})")
88+
7289
print("\n--- Attention Configuration ---")
73-
has_sage = sageattn is not None and sageattn_varlen is not None
90+
has_sage1 = sageattn1 is not None and sageattn1_varlen is not None
91+
has_sage3 = sageattn3 is not None
7492
has_flash2 = flash2_attn_func is not None and flash2_attn_varlen_func is not None
7593
has_flash4 = flash4_attn_func is not None and flash4_attn_varlen_func is not None
7694
has_xformers = xformers_attn_func is not None
7795

7896
# Priority order, best to worst
7997
PRIORITY = [
98+
("SAGE Attention-3", has_sage3),
8099
("Flash Attention-4", has_flash4),
81-
("SAGE Attention", has_sage),
100+
("SAGE Attention-1", has_sage1),
82101
("Flash Attention-2", has_flash2),
83102
("xFormers", has_xformers),
84103
]
@@ -93,16 +112,25 @@ def worse_installed(current_name):
93112
idx = next(i for i, (name, _) in enumerate(PRIORITY) if name == current_name)
94113
return [name for name, installed in PRIORITY[idx + 1:] if installed]
95114

96-
if has_flash4:
115+
if has_sage3 and (major == 10 or major == 12): # can only be used on blackwell cards
116+
print("✅ Using SAGE Attention-3 (highest performance).")
117+
for opt in better_options("Flash Attention-4"):
118+
print(f" - Consider installing {opt} for even higher performance.")
119+
ignored = worse_installed("SAGE Attention-3")
120+
if ignored:
121+
print(f" - Ignoring other installed attention libraries: {', '.join(ignored)}")
122+
elif has_flash4 and major == 10: # can only be used on datacenter blackwell cards
97123
print("✅ Using Flash Attention-4 (highest performance).")
124+
for opt in better_options("Flash Attention-4"):
125+
print(f" - Consider installing {opt} for even higher performance.")
98126
ignored = worse_installed("Flash Attention-4")
99127
if ignored:
100128
print(f" - Ignoring other installed attention libraries: {', '.join(ignored)}")
101-
elif has_sage:
129+
elif has_sage1:
102130
print("✅ Using SAGE Attention (high performance).")
103-
for opt in better_options("SAGE Attention"):
131+
for opt in better_options("SAGE Attention-1"):
104132
print(f" - Consider installing {opt} for even higher performance.")
105-
ignored = worse_installed("SAGE Attention")
133+
ignored = worse_installed("SAGE Attention-1")
106134
if ignored:
107135
print(f" - Ignoring other installed attention libraries: {', '.join(ignored)}")
108136
elif has_flash2:
@@ -177,12 +205,30 @@ def attn_varlen_func(q, k, v, cu_seqlens_q, cu_seqlens_kv, max_seqlen_q, max_seq
177205
and max_seqlen_q is None
178206
and max_seqlen_kv is None
179207
):
208+
if sageattn3 is not None:
209+
# Tensor layout is: HND, not NHD
210+
211+
# NHD → HND
212+
q_c = q.transpose(1, 2).contiguous()
213+
k_c = k.transpose(1, 2).contiguous()
214+
v_c = v.transpose(1, 2).contiguous()
215+
216+
x_c = sageattn3(
217+
q_c, k_c, v_c,
218+
is_causal=False
219+
)
220+
221+
# HND → NHD
222+
x = x_c.transpose(1, 2).contiguous()
223+
224+
return x
225+
180226
if flash4_attn_func is not None:
181227
out, lse = flash4_attn_func(q, k, v)
182228
return out
183229

184-
if sageattn is not None:
185-
x = sageattn(q, k, v, tensor_layout="NHD")
230+
if sageattn1 is not None:
231+
x = sageattn1(q, k, v, tensor_layout="NHD")
186232
return x
187233

188234
if flash2_attn_func is not None:
@@ -203,7 +249,7 @@ def attn_varlen_func(q, k, v, cu_seqlens_q, cu_seqlens_kv, max_seqlen_q, max_seq
203249
k = k.view(k.shape[0] * k.shape[1], *k.shape[2:])
204250
v = v.view(v.shape[0] * v.shape[1], *v.shape[2:])
205251
if sageattn_varlen is not None:
206-
x = sageattn_varlen(
252+
x = sageattn1_varlen(
207253
q, k, v, cu_seqlens_q, cu_seqlens_kv, max_seqlen_q, max_seqlen_kv
208254
)
209255
elif flash2_attn_varlen_func is not None:

0 commit comments

Comments
 (0)