Skip to content

Commit af5aed0

Browse files
committed
[Cute] Apply review feedback: rename to mCuTotalMBlocks, drop num_head, use shared utility
Addresses @reubenconducts's May 22 review comments on Dao-AILab#2520: 1. Rename mTileCumsum -> mCuTotalMBlocks across all 9 kernels + scheduler + interface for consistency with the convention introduced in Dao-AILab#2224 (already in main; used by blocksparse, and by Dao-AILab#2559). 2. Drop num_head (and the related pack_gqa arch-conditional remap) from the host cumsum. Per-batch cumsum is now pure m_blocks; the scheduler handles num_head separately. Removes the SM80/SM120 vs SM90/100/110/MLA branching that previously mirrored the pack_gqa_layout reshape behavior. 3. Replace the inline binary search in _varlen_coord_map's cumsum-on branch with a call to utils.get_batch_from_cu_tensor (the shared utility from Dao-AILab#2556). The existing snap-to-group-boundary + warp-scan structure is preserved — the cumsum serves as a hint to skip ahead, and the warp-scan refines to the exact batch using _get_num_m_blocks (which already handles pack_gqa, q_stage, cluster, etc.). This matches the scheduler-side approach in Dao-AILab#2559. The pack_gqa seqlen multiplier stays in _compute_cu_total_m_blocks so that per-batch m_block counts match the kernel's _get_num_m_blocks formula — the snap is forward-only, so under-estimating per-batch counts is safe but over-estimating (which dropping the multiplier would cause when pack_gqa is on) would land the snap past the correct batch and the warp-scan couldn't recover. Verified on SM100: - 72 new tests (test_varlen_scheduler_binary_search_correctness{,_bwd}): pass - existing test_varlen (B=20 slice, 576 cases): pass - existing test_flash_attn_mla_absorbed_varlen (480 cases): pass
1 parent 5d4573c commit af5aed0

12 files changed

Lines changed: 119 additions & 123 deletions

flash_attn/cute/flash_bwd.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ def __call__(
382382
mCuSeqlensK: Optional[cute.Tensor] = None,
383383
mSeqUsedQ: Optional[cute.Tensor] = None,
384384
mSeqUsedK: Optional[cute.Tensor] = None,
385-
mTileCumsum: Optional[cute.Tensor] = None, # int32, (num_batch + 1,); see TileSchedulerArguments
385+
mCuTotalMBlocks: Optional[cute.Tensor] = None, # int32, (num_batch + 1,); see TileSchedulerArguments
386386
window_size_left: Int32 | int | None = None,
387387
window_size_right: Int32 | int | None = None,
388388
mdQ_semaphore: Optional[cute.Tensor] = None,
@@ -430,7 +430,7 @@ def __call__(
430430
qhead_per_kvhead_packgqa=self.qhead_per_kvhead if cutlass.const_expr(self.pack_gqa) else 1,
431431
mCuSeqlensQ=mCuSeqlensK,
432432
mSeqUsedQ=mSeqUsedK,
433-
mTileCumsum=mTileCumsum,
433+
mCuTotalMBlocks=mCuTotalMBlocks,
434434
)
435435

436436
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)

flash_attn/cute/flash_bwd_postprocess.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def __call__(
215215
scale: cutlass.Float32,
216216
mCuSeqlensQ: Optional[cute.Tensor],
217217
mSeqUsedQ: Optional[cute.Tensor],
218-
mTileCumsum: Optional[
218+
mCuTotalMBlocks: Optional[
219219
cute.Tensor
220220
] = None, # int32, (num_batch + 1,); see TileSchedulerArguments
221221
# Always keep stream as the last parameter (EnvStream: obtained implicitly via TVM FFI).
@@ -261,7 +261,7 @@ def __call__(
261261
tile_shape_mn=(self.tile_m, 1),
262262
mCuSeqlensQ=mCuSeqlensQ,
263263
mSeqUsedQ=mSeqUsedQ,
264-
mTileCumsum=mTileCumsum,
264+
mCuTotalMBlocks=mCuTotalMBlocks,
265265
)
266266

267267
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)

flash_attn/cute/flash_bwd_preprocess.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +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-
mTileCumsum: Optional[
139+
mCuTotalMBlocks: Optional[
140140
cute.Tensor
141141
] = None, # int32, (num_batch + 1,); see TileSchedulerArguments
142142
# Always keep stream as the last parameter (EnvStream: obtained implicitly via TVM FFI).
@@ -196,7 +196,7 @@ def __call__(
196196
tile_shape_mn=(self.tile_m, 1),
197197
mCuSeqlensQ=mCuSeqlensQ,
198198
mSeqUsedQ=mSeqUsedQ,
199-
mTileCumsum=mTileCumsum,
199+
mCuTotalMBlocks=mCuTotalMBlocks,
200200
)
201201

202202
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)

flash_attn/cute/flash_bwd_sm100.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ def __call__(
458458
mCuSeqlensK: Optional[cute.Tensor] = None,
459459
mSeqUsedQ: Optional[cute.Tensor] = None,
460460
mSeqUsedK: Optional[cute.Tensor] = None,
461-
mTileCumsum: Optional[
461+
mCuTotalMBlocks: Optional[
462462
cute.Tensor
463463
] = None, # int32, (num_batch + 1,); see TileSchedulerArguments
464464
window_size_left: Int32 | int | None = None,
@@ -737,7 +737,7 @@ def __call__(
737737
is_persistent=self.is_persistent, # persistent mode not tested
738738
lpt=self.spt,
739739
head_swizzle=self.deterministic,
740-
mTileCumsum=mTileCumsum,
740+
mCuTotalMBlocks=mCuTotalMBlocks,
741741
)
742742

743743
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)

flash_attn/cute/flash_bwd_sm90.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ def __call__(
350350
mCuSeqlensK: Optional[cute.Tensor] = None,
351351
mSeqUsedQ: Optional[cute.Tensor] = None,
352352
mSeqUsedK: Optional[cute.Tensor] = None,
353-
mTileCumsum: Optional[
353+
mCuTotalMBlocks: Optional[
354354
cute.Tensor
355355
] = None, # int32, (num_batch + 1,); see TileSchedulerArguments
356356
window_size_left: Int32 | int | None = None,
@@ -539,7 +539,7 @@ def _qkv_transpose(t):
539539
is_persistent=False,
540540
lpt=self.spt,
541541
head_swizzle=self.deterministic,
542-
mTileCumsum=mTileCumsum,
542+
mCuTotalMBlocks=mCuTotalMBlocks,
543543
)
544544

545545
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)

flash_attn/cute/flash_fwd.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ def __call__(
631631
mCuSeqlensK: Optional[cute.Tensor] = None,
632632
mSeqUsedQ: Optional[cute.Tensor] = None,
633633
mSeqUsedK: Optional[cute.Tensor] = None,
634-
mTileCumsum: Optional[cute.Tensor] = None, # int32, (num_batch + 1,); see TileSchedulerArguments
634+
mCuTotalMBlocks: Optional[cute.Tensor] = None, # int32, (num_batch + 1,); see TileSchedulerArguments
635635
mPageTable: Optional[cute.Tensor] = None,
636636
window_size_left: Optional[Int32] = None,
637637
window_size_right: Optional[Int32] = None,
@@ -699,7 +699,7 @@ def __call__(
699699
qhead_per_kvhead_packgqa=self.qhead_per_kvhead if const_expr(self.pack_gqa) else 1,
700700
mCuSeqlensQ=mCuSeqlensQ,
701701
mSeqUsedQ=mSeqUsedQ,
702-
mTileCumsum=mTileCumsum,
702+
mCuTotalMBlocks=mCuTotalMBlocks,
703703
)
704704
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)
705705
grid_dim = TileScheduler.get_grid_shape(tile_sched_params)

flash_attn/cute/flash_fwd_mla_sm100.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ def __call__(
361361
mCuSeqlensK: Optional[cute.Tensor] = None, # (b + 1)
362362
mSeqUsedQ: Optional[cute.Tensor] = None, # (b)
363363
mSeqUsedK: Optional[cute.Tensor] = None, # (b)
364-
mTileCumsum: Optional[
364+
mCuTotalMBlocks: Optional[
365365
cute.Tensor
366366
] = None, # int32, (num_batch + 1,); see TileSchedulerArguments
367367
mIndexTopk: Optional[
@@ -633,7 +633,7 @@ def make_tma(make_fn, mX, smem_layout, mma_tiler, tiled_mma):
633633
is_split_kv=False,
634634
cluster_shape_mn=self.cluster_shape_mn,
635635
use_cluster_idx=False,
636-
mTileCumsum=mTileCumsum,
636+
mCuTotalMBlocks=mCuTotalMBlocks,
637637
)
638638
tile_sched_params = TileScheduler.to_underlying_arguments(
639639
tile_sched_args, scheduling_mode=self.scheduling_mode

flash_attn/cute/flash_fwd_sm100.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ def __call__(
373373
mCuSeqlensK: Optional[cute.Tensor] = None,
374374
mSeqUsedQ: Optional[cute.Tensor] = None,
375375
mSeqUsedK: Optional[cute.Tensor] = None,
376-
mTileCumsum: Optional[cute.Tensor] = None, # int32, (num_batch + 1,); see TileSchedulerArguments
376+
mCuTotalMBlocks: Optional[cute.Tensor] = None, # int32, (num_batch + 1,); see TileSchedulerArguments
377377
mPageTable: Optional[cute.Tensor] = None, # (b_k, max_num_pages_per_seq)
378378
window_size_left: Int32 | int | None = None,
379379
window_size_right: Int32 | int | None = None,
@@ -661,7 +661,7 @@ def __call__(
661661
is_split_kv=self.is_split_kv,
662662
cluster_shape_mn=self.cluster_shape_mn,
663663
use_cluster_idx=not self.is_persistent and self.cta_group_size > 1,
664-
mTileCumsum=mTileCumsum,
664+
mCuTotalMBlocks=mCuTotalMBlocks,
665665
)
666666
tile_sched_params = TileScheduler.to_underlying_arguments(
667667
tile_sched_args, scheduling_mode=self.scheduling_mode

flash_attn/cute/flash_fwd_sm90.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ def __call__(
166166
mCuSeqlensK: Optional[cute.Tensor] = None,
167167
mSeqUsedQ: Optional[cute.Tensor] = None,
168168
mSeqUsedK: Optional[cute.Tensor] = None,
169-
mTileCumsum: Optional[
169+
mCuTotalMBlocks: Optional[
170170
cute.Tensor
171171
] = None, # int32, (num_batch + 1,); see TileSchedulerArguments
172172
mPageTable: Optional[cute.Tensor] = None, # (b_k, max_num_pages_per_seq)
@@ -344,7 +344,7 @@ def __call__(
344344
element_size=self.dtype.width // 8,
345345
is_persistent=False,
346346
lpt=self.is_causal or self.is_local,
347-
mTileCumsum=mTileCumsum,
347+
mCuTotalMBlocks=mCuTotalMBlocks,
348348
)
349349
tile_sched_params = TileScheduler.to_underlying_arguments(tile_sched_args)
350350
grid_dim = TileScheduler.get_grid_shape(tile_sched_params)

0 commit comments

Comments
 (0)