4040flash2_attn_func = None
4141flash4_attn_varlen_func = None
4242flash4_attn_func = None
43- sageattn_varlen = None
44- sageattn = None
43+ sageattn1_varlen = None
44+ sageattn1 = None
45+ sageattn3 = None
4546
4647try :
4748 # raise NotImplementedError
6566
6667try :
6768 # raise NotImplementedError
68- from sageattention import sageattn_varlen , sageattn
69+ from sageattention import (sageattn_varlen as sageattn1_varlen ,
70+ sageattn as sageattn1 )
6971except :
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+
7289print ("\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
7492has_flash2 = flash2_attn_func is not None and flash2_attn_varlen_func is not None
7593has_flash4 = flash4_attn_func is not None and flash4_attn_varlen_func is not None
7694has_xformers = xformers_attn_func is not None
7795
7896# Priority order, best to worst
7997PRIORITY = [
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 )} " )
108136elif 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