Skip to content

Commit 5a69571

Browse files
work PR 2520 into interface and kernels
1 parent 83328ab commit 5a69571

12 files changed

Lines changed: 484 additions & 170 deletions

benchmarks/benchmark_varlen_sched.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ def build_ctx(
181181

182182

183183
def _make_meta(ctx):
184+
tile_m = 128
185+
qhead_per_kvhead = ctx["nheads"] // ctx["nheads_kv"]
186+
arch = torch.cuda.get_device_capability()[0]
187+
if arch == 10 and ctx["max_seqlen_q"] * qhead_per_kvhead > tile_m:
188+
q_stage = 2
189+
else:
190+
q_stage = 1
184191
return get_scheduler_metadata(
185192
num_batch=ctx["batch"],
186193
max_seqlen_q=ctx["max_seqlen_q"],
@@ -189,12 +196,13 @@ def _make_meta(ctx):
189196
nheads_kv=ctx["nheads_kv"],
190197
headdim=ctx["headdim"],
191198
num_splits=ctx["num_splits"],
192-
tile_m=128,
199+
tile_m=tile_m,
193200
tile_n=128,
194201
causal=ctx["causal"],
195202
pack_gqa=ctx["pack_gqa"],
196203
cu_seqlens_q=ctx["cu_q"],
197204
cu_seqlens_k=ctx["cu_k"],
205+
q_stage=q_stage,
198206
)
199207

200208

@@ -322,8 +330,12 @@ def parse_args():
322330
p.add_argument("--headdim", type=int, default=128)
323331
p.add_argument("--nheads", type=int, default=16)
324332
p.add_argument("--nheads-kv", type=int, default=2)
325-
p.add_argument("--pack-gqa", action="store_true", default=True,
326-
help="Force pack_gqa=True (default). --no-pack-gqa to disable.")
333+
p.add_argument(
334+
"--pack-gqa",
335+
action="store_true",
336+
default=True,
337+
help="Force pack_gqa=True (default). --no-pack-gqa to disable.",
338+
)
327339
p.add_argument("--no-pack-gqa", dest="pack_gqa", action="store_false")
328340
p.add_argument("--seeds", type=int, default=3)
329341
p.add_argument("--warmup", type=int, default=2)
@@ -434,7 +446,9 @@ def main():
434446
eff = sq * sk - sq * (sq - 1) // 2
435447
else:
436448
# clamp to non-negative for queries near 0
437-
first_visible_q = -shift # smallest q with sk - sq + q + 1 > 0 is q = sq - sk
449+
first_visible_q = (
450+
-shift
451+
) # smallest q with sk - sq + q + 1 > 0 is q = sq - sk
438452
visible = sq - first_visible_q
439453
eff = visible * sk - visible * (visible - 1) // 2
440454
eff = max(0, eff)

flash_attn/cute/flash_bwd.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ def __call__(
389389
mdV_semaphore: Optional[cute.Tensor] = None,
390390
aux_tensors: Optional[list] = None,
391391
blocksparse_tensors: Optional[BlockSparseTensors] = None,
392+
mCuTotalMBlocks: Optional[cute.Tensor] = None,
392393
# Always keep stream as the last parameter (EnvStream: obtained implicitly via TVM FFI).
393394
stream: cuda.CUstream = None,
394395
):
@@ -429,6 +430,7 @@ def __call__(
429430
qhead_per_kvhead_packgqa=self.qhead_per_kvhead if cutlass.const_expr(self.pack_gqa) else 1,
430431
mCuSeqlensQ=mCuSeqlensK,
431432
mSeqUsedQ=mSeqUsedK,
433+
cu_total_m_blocks_ptr=mCuTotalMBlocks,
432434
)
433435

434436
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)

flash_attn/cute/flash_bwd_postprocess.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ def __call__(
215215
scale: cutlass.Float32,
216216
mCuSeqlensQ: Optional[cute.Tensor],
217217
mSeqUsedQ: Optional[cute.Tensor],
218+
mCuTotalMBlocks: Optional[cute.Tensor] = None,
218219
# Always keep stream as the last parameter (EnvStream: obtained implicitly via TVM FFI).
219220
stream: cuda.CUstream = None,
220221
):
@@ -258,6 +259,7 @@ def __call__(
258259
tile_shape_mn=(self.tile_m, 1),
259260
mCuSeqlensQ=mCuSeqlensQ,
260261
mSeqUsedQ=mSeqUsedQ,
262+
cu_total_m_blocks_ptr=mCuTotalMBlocks,
261263
)
262264

263265
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)

flash_attn/cute/flash_bwd_preprocess.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ def __call__(
136136
mCuSeqlensQ: Optional[cute.Tensor], # (batch + 1,)
137137
mSeqUsedQ: Optional[cute.Tensor], # (batch,)
138138
mdLSE: Optional[cute.Tensor], # (batch, nheads, seqlen) or (nheads, total_q)
139+
mCuTotalMBlocks: Optional[cute.Tensor] = None,
139140
# Always keep stream as the last parameter (EnvStream: obtained implicitly via TVM FFI).
140141
stream: cuda.CUstream = None,
141142
):
@@ -193,6 +194,7 @@ def __call__(
193194
tile_shape_mn=(self.tile_m, 1),
194195
mCuSeqlensQ=mCuSeqlensQ,
195196
mSeqUsedQ=mSeqUsedQ,
197+
cu_total_m_blocks_ptr=mCuTotalMBlocks,
196198
)
197199

198200
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)

flash_attn/cute/flash_bwd_sm100.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ def __call__(
466466
aux_tensors: Optional[list] = None,
467467
# Block-sparse tensors (Q direction - for iterating m_blocks per n_block):
468468
blocksparse_tensors: Optional[BlockSparseTensors] = None,
469+
mCuTotalMBlocks: Optional[cute.Tensor] = None,
469470
# Always keep stream as the last parameter (EnvStream: obtained implicitly via TVM FFI).
470471
stream: cuda.CUstream = None,
471472
):
@@ -732,6 +733,7 @@ def __call__(
732733
qhead_per_kvhead_packgqa=1, # pack_gqa disabled for bwd
733734
element_size=self.k_dtype.width // 8,
734735
is_persistent=self.is_persistent, # persistent mode not tested
736+
cu_total_m_blocks_ptr=mCuTotalMBlocks,
735737
lpt=self.spt,
736738
head_swizzle=self.deterministic,
737739
)

flash_attn/cute/flash_bwd_sm90.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ def __call__(
357357
mdV_semaphore: Optional[cute.Tensor] = None,
358358
aux_tensors: Optional[list] = None,
359359
blocksparse_tensors: Optional[BlockSparseTensors] = None,
360+
mCuTotalMBlocks: Optional[cute.Tensor] = None,
360361
# Always keep stream as the last parameter (EnvStream: obtained implicitly via TVM FFI).
361362
stream: cuda.CUstream = None,
362363
):
@@ -536,6 +537,7 @@ def _qkv_transpose(t):
536537
is_persistent=False,
537538
lpt=self.spt,
538539
head_swizzle=self.deterministic,
540+
cu_total_m_blocks_ptr=mCuTotalMBlocks,
539541
)
540542

541543
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)

flash_attn/cute/flash_fwd.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,8 @@ def __call__(
631631
learnable_sink: Optional[cute.Tensor] = None,
632632
blocksparse_tensors: Optional[BlockSparseTensors] = None,
633633
aux_tensors=None,
634+
mCuTotalMBlocks: Optional[cute.Tensor] = None,
635+
mCuTotalSplitsMBlocks: Optional[cute.Tensor] = None,
634636
# Always keep stream as the last parameter (EnvStream: obtained implicitly via TVM FFI).
635637
stream: cuda.CUstream = None,
636638
):
@@ -692,6 +694,8 @@ def __call__(
692694
qhead_per_kvhead_packgqa=self.qhead_per_kvhead if const_expr(self.pack_gqa) else 1,
693695
mCuSeqlensQ=mCuSeqlensQ,
694696
mSeqUsedQ=mSeqUsedQ,
697+
cu_total_m_blocks_ptr=mCuTotalMBlocks,
698+
cu_total_splits_m_blocks_ptr=mCuTotalSplitsMBlocks,
695699
)
696700
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)
697701
grid_dim = TileScheduler.get_grid_shape(tile_sched_params)

flash_attn/cute/flash_fwd_sm100.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,8 @@ def __call__(
398398
tile_count_semaphore: Optional[cute.Tensor] = None,
399399
virtual_batch_idx_ptr: Optional[cute.Tensor] = None,
400400
num_nheads_in_l2_ptr: Optional[cute.Tensor] = None,
401-
cu_total_m_blocks_ptr: Optional[cute.Tensor] = None,
402-
cu_total_splits_m_blocks_ptr: Optional[cute.Tensor] = None,
401+
mCuTotalMBlocks: Optional[cute.Tensor] = None,
402+
mCuTotalSplitsMBlocks: Optional[cute.Tensor] = None,
403403
max_seqlen_q: Int32 | int | None = None,
404404
# Always keep stream as the last parameter (EnvStream: obtained implicitly via TVM FFI).
405405
stream: cuda.CUstream = None,
@@ -688,8 +688,8 @@ def __call__(
688688
num_splits_dynamic_ptr=num_splits_dynamic_ptr,
689689
virtual_batch_idx_ptr=virtual_batch_idx_ptr,
690690
num_nheads_in_l2_ptr=num_nheads_in_l2_ptr,
691-
cu_total_m_blocks_ptr=cu_total_m_blocks_ptr,
692-
cu_total_splits_m_blocks_ptr=cu_total_splits_m_blocks_ptr,
691+
cu_total_m_blocks_ptr=mCuTotalMBlocks,
692+
cu_total_splits_m_blocks_ptr=mCuTotalSplitsMBlocks,
693693
tile_count_semaphore=tile_count_semaphore.iterator if tile_count_semaphore is not None else None,
694694
)
695695
tile_sched_params = TileScheduler.to_underlying_arguments(

flash_attn/cute/flash_fwd_sm90.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ def __call__(
172172
learnable_sink: Optional[cute.Tensor] = None,
173173
blocksparse_tensors: Optional[BlockSparseTensors] = None,
174174
aux_tensors: Optional[list] = None,
175+
mCuTotalMBlocks: Optional[cute.Tensor] = None,
176+
mCuTotalSplitsMBlocks: Optional[cute.Tensor] = None,
175177
# Always keep stream as the last parameter (EnvStream: obtained implicitly via TVM FFI).
176178
stream: cuda.CUstream = None,
177179
):
@@ -312,6 +314,7 @@ def __call__(
312314
(self.tile_m, self.tile_hdimv), # No mcast
313315
)
314316
if const_expr(mCuSeqlensQ is not None or mSeqUsedQ is not None):
317+
# TODO: dispatch to DynamicPersistentVarlenScheduler when appropriate
315318
TileScheduler = SingleTileVarlenScheduler
316319
else:
317320
TileScheduler = (
@@ -341,6 +344,8 @@ def __call__(
341344
element_size=self.dtype.width // 8,
342345
is_persistent=False,
343346
lpt=self.is_causal or self.is_local,
347+
cu_total_m_blocks_ptr=mCuTotalMBlocks,
348+
cu_total_splits_m_blocks_ptr=mCuTotalSplitsMBlocks,
344349
)
345350
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)
346351
grid_dim = TileScheduler.get_grid_shape(tile_sched_params)

0 commit comments

Comments
 (0)