@@ -1275,20 +1275,28 @@ def create_sa_config(config, query, key, attn_logits_soft_cap):
12751275 else :
12761276 mask = mask_module .CausalMask (shape = mask_shape )
12771277
1278- # Create LoadBalancedCausalMask if cp and load_balancing
1279- if cp_size > 1 and load_balanced_context_parallel :
1278+ use_load_balanced_cp = cp_size > 1 and load_balanced_context_parallel
1279+ if use_load_balanced_cp and self . attention_type != AttentionType . FULL :
12801280 mask = LoadBalancedCausalMask (shape = mask_shape , cp_size = cp_size )
12811281
1282- # TODO: figure out local_sliding attention + load_balancing, default is global
12831282 # Apply local masking if local sliding attention is enabled.
12841283 if self .attention_type == AttentionType .LOCAL_SLIDING :
12851284 if self .sliding_window_size is None :
12861285 raise ValueError ("Sliding_window_size must be set if Local Sliding attention type" )
1287- mask &= mask_module .LocalMask (
1288- shape = (query .shape [2 ], key .shape [2 ]),
1289- window_size = (self .sliding_window_size - 1 , self .sliding_window_size ),
1290- offset = 0 ,
1291- )
1286+ local_window_size = (self .sliding_window_size - 1 , self .sliding_window_size )
1287+ if use_load_balanced_cp :
1288+ mask &= LoadBalancedLocalMask (
1289+ shape = (query .shape [2 ], key .shape [2 ]),
1290+ window_size = local_window_size ,
1291+ offset = 0 ,
1292+ cp_size = cp_size ,
1293+ )
1294+ else :
1295+ mask &= mask_module .LocalMask (
1296+ shape = (query .shape [2 ], key .shape [2 ]),
1297+ window_size = local_window_size ,
1298+ offset = 0 ,
1299+ )
12921300 elif self .attention_type == AttentionType .CHUNK :
12931301 if self .chunk_attn_window_size is None :
12941302 raise ValueError ("chunk_attn_window_size must be set for chunk attention type" )
@@ -2164,6 +2172,12 @@ def __call__(
21642172 return prefill_unnormalized_output / prefill_exponentials_sum
21652173
21662174
2175+ def _load_balanced_q_sequence (shape : tuple [int , int ], cp_size : int ):
2176+ """Reorders query positions the same way as load-balanced input tokens."""
2177+ arr = np .arange (shape [0 ])
2178+ return max_utils .reorder_mask_load_balancing (arr , cp_size , 0 )
2179+
2180+
21672181# pylint: disable=protected-access
21682182class LoadBalancedCausalMask (splash_attention_mask ._ComputableMask ):
21692183 """Lazy causal mask, prevents the model from attending to future tokens.
@@ -2194,20 +2208,14 @@ def causal_mask_function(q_ids, kv_ids):
21942208 else :
21952209 return q_ids + self .offset >= kv_ids
21962210
2197- arr = np .arange (shape [0 ])
2198- # we reorder the mask to be load balanced following the same approach as
2199- # used to reorder the input tokens
2200- out = max_utils .reorder_mask_load_balancing (arr [None , :, None , None ], cp_size , 1 )
2201- q_sequence = out [0 , :, 0 , 0 ]
2202-
22032211 mask_function = causal_mask_function
22042212
22052213 super ().__init__ (
22062214 shape = shape ,
22072215 mask_function = mask_function ,
22082216 shard_count = shard_count ,
22092217 )
2210- self .q_sequence = q_sequence
2218+ self .q_sequence = _load_balanced_q_sequence ( shape , cp_size )
22112219
22122220 def __eq__ (self , other : object ):
22132221 if not isinstance (other , type (self )):
@@ -2224,3 +2232,25 @@ def __hash__(self):
22242232 self .q_sequence .tobytes () if self .q_sequence is not None else None ,
22252233 )
22262234 )
2235+
2236+
2237+ class LoadBalancedLocalMask (splash_attention_mask .LocalMask ):
2238+ """Lazy local mask with load-balanced query positions."""
2239+
2240+ def __init__ (
2241+ self ,
2242+ shape : tuple [int , int ],
2243+ window_size : tuple [int | None , int | None ],
2244+ offset : int ,
2245+ shard_count : int = 1 ,
2246+ cp_size : int = - 1 ,
2247+ ):
2248+ super ().__init__ (
2249+ shape = shape ,
2250+ window_size = window_size ,
2251+ offset = offset ,
2252+ shard_count = shard_count ,
2253+ )
2254+ # LocalMask uses shard_count for mask-shard validation. cp_size is the
2255+ # context-parallel size used for the load-balanced query order.
2256+ self .q_sequence = _load_balanced_q_sequence (shape , cp_size )
0 commit comments