Skip to content

Commit 8a8b2f1

Browse files
authored
allow for zero length sequences in hdim 256 sm100 kernels (Dao-AILab#2568)
1 parent 0409f9a commit 8a8b2f1

5 files changed

Lines changed: 198 additions & 133 deletions

flash_attn/cute/sm100_hd256_2cta_fmha_backward.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from flash_attn.cute.sm100_hd256_2cta_fmha_backward_dkdvkernel import (
2222
BlackwellFusedMultiHeadAttentionBackwardDKDVKernel,
2323
)
24+
from flash_attn.cute.cute_dsl_utils import assume_tensor_aligned
2425

2526

2627
def _as_bshkrd_tensor(
@@ -251,6 +252,8 @@ def __call__(
251252
else:
252253
b = Q.shape[0]
253254

255+
Q, K, V, dQ, dK, dV, dO = [assume_tensor_aligned(t) for t in (Q, K, V, dQ, dK, dV, dO)]
256+
254257
Q = _as_bshkrd_tensor(Q, h_k, h_r, varlen)
255258
K = _as_bshkrd_tensor(K, h_k, 1, varlen)
256259
V = _as_bshkrd_tensor(V, h_k, 1, varlen)

flash_attn/cute/sm100_hd256_2cta_fmha_backward_dkdvkernel.py

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
Sm100FmhaStaticTileSchedulerParams as FmhaStaticTileSchedulerParams,
3333
)
3434

35+
import flash_attn.cute.copy_utils as fa_copy_utils
3536

3637
LAYOUT_RANK_CONSTANT = 3
3738

@@ -2811,38 +2812,53 @@ def epilogue_clear(
28112812
dK.iterator + mdK_offset,
28122813
cute.make_layout((K, self.tile_shape_dQ_K, HB), stride=dK.stride),
28132814
)
2814-
gdK = cute.local_tile(
2815-
mdK, (self.dSQ_mma_tiler[0], self.dSQ_mma_tiler[1]), (None, None, None)
2816-
)
2815+
gdK = cute.local_tile(mdK, (self.cta_tiler[1], self.cta_tiler[2]), (None, None, None))
28172816
gdK = gdK[None, None, blk_coord_k, 0, blk_coord_batch]
28182817
cdK = cute.domain_offset(
28192818
(blk_coord_k * self.tile_shape_K, 0),
2820-
cute.make_identity_tensor((self.dSQ_mma_tiler[0], self.dSQ_mma_tiler[1])),
2819+
cute.make_identity_tensor((self.cta_tiler[1], self.cta_tiler[2])),
28212820
)
28222821

28232822
mdV_offset = cute.assume(blk_offset[1] * dV.stride[0], divby=64)
28242823
mdV = cute.make_tensor(
28252824
dV.iterator + mdV_offset,
28262825
cute.make_layout((K, self.tile_shape_dV_dO, HB), stride=dV.stride),
28272826
)
2828-
gdV = cute.local_tile(
2829-
mdV, (self.PdO_mma_tiler[0], self.PdO_mma_tiler[1]), (None, None, None)
2830-
)
2827+
gdV = cute.local_tile(mdV, (self.cta_tiler[1], self.cta_tiler[2]), (None, None, None))
28312828
gdV = gdV[None, None, blk_coord_k, 0, blk_coord_batch]
28322829
cdV = cute.domain_offset(
28332830
(blk_coord_k * self.tile_shape_K, 0),
2834-
cute.make_identity_tensor((self.PdO_mma_tiler[0], self.PdO_mma_tiler[1])),
2831+
cute.make_identity_tensor((self.cta_tiler[1], self.cta_tiler[2])),
28352832
)
28362833

2837-
for i in cutlass.range(tidx * 8, cute.size(gdK), block_dim_x * 8):
2838-
if cute.elem_less(cdK[i], cute.select(problem_shape, mode=[1, 2])):
2839-
gdK_i = cute.make_tensor(gdK.iterator + cute.assume(i, divby=8), (8))
2840-
gdK_i.fill(0)
2834+
num_zero_epi_threads = 256
2835+
2836+
tiled_copy_r2g = fa_copy_utils.tiled_copy_2d(
2837+
dK.element_type, self.cta_tiler[2], num_zero_epi_threads
2838+
)
2839+
2840+
thr_copy_r2g = tiled_copy_r2g.get_slice(tidx)
2841+
2842+
tRG_gdK = thr_copy_r2g.partition_D(gdK)
2843+
tRG_cdK = thr_copy_r2g.partition_D(cdK)
2844+
tRG_gdV = thr_copy_r2g.partition_D(gdV)
2845+
tRG_cdV = thr_copy_r2g.partition_D(cdV)
2846+
2847+
zero_frg = cute.make_rmem_tensor_like(tRG_gdK[None, 0, None])
2848+
zero_frg.fill(dK.element_type(0.0))
2849+
2850+
# check we don't need zero fragment duplication
2851+
V_frg_size = cute.size(tRG_gdV[None, 0, None])
2852+
assert cute.size(zero_frg) == V_frg_size
2853+
2854+
if tidx < num_zero_epi_threads:
2855+
for n in cutlass.range(cute.size(tRG_gdK.shape[1]), unroll_full=True):
2856+
if cute.elem_less(tRG_cdK[0, n, 0][0], problem_shape[1]):
2857+
cute.copy(tiled_copy_r2g, zero_frg, tRG_gdK[None, n, None])
28412858

2842-
for i in cutlass.range(tidx * 8, cute.size(gdV), block_dim_x * 8):
2843-
if cute.elem_less(cdV[i], cute.select(problem_shape, mode=[1, 2])):
2844-
gdV_i = cute.make_tensor(gdV.iterator + cute.assume(i, divby=8), (8))
2845-
gdV_i.fill(0)
2859+
for n in cutlass.range(cute.size(tRG_gdV.shape[1]), unroll_full=True):
2860+
if cute.elem_less(tRG_cdV[0, n, 0][0], problem_shape[1]):
2861+
cute.copy(tiled_copy_r2g, zero_frg, tRG_gdV[None, n, None])
28462862

28472863
@cute.jit
28482864
def epilogue(

0 commit comments

Comments
 (0)