Skip to content

Commit 97b9640

Browse files
[2026-06-01] pull origin main
2 parents 5391f12 + 6dba037 commit 97b9640

24 files changed

Lines changed: 1907 additions & 1180 deletions

.github/workflows/ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ permissions:
99

1010
env:
1111
CI_WORK_DIR: ${{ vars.CI_WORK_DIR || format('/scratch/user/{0}', github.actor) }}
12-
FA4_TEST_FILTER: "1024-1024-128-True-0-0.0-False-False-False-mha-dtype0 or 1024-1024-128-False-0-0.0-False-False-False-mha-dtype0"
12+
FA4_TEST_FILTER: >-
13+
1024-1024-128-True-0-0.0-False-False-False-mha-dtype0
14+
or 1024-1024-128-False-0-0.0-False-False-False-mha-dtype0
15+
or test_flash_attn_ex2_emu_decode_prefill_consistency
1316
1417
jobs:
1518
lint:

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pip install flash-attn-4
2020
pip install -e "flash_attn/cute[dev]"
2121
```
2222

23-
Dependencies: `nvidia-cutlass-dsl>=4.4.1`, `torch`, `einops`, `apache-tvm-ffi`, `quack-kernels>=0.4.0`.
23+
Dependencies: `nvidia-cutlass-dsl>=4.5.2`, `torch`, `einops`, `apache-tvm-ffi`, `quack-kernels>=0.5.0`.
2424

2525
## Running Tests
2626

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Copyright (c) 2025, Johnsonms.
2+
3+
# We recommend locking GPU clocks before running the benchmark to ensure consistent results.
4+
# This can be done using the following commands (2619 MHz is the max clock for B200):
5+
# sudo nvidia-smi -i 0 -pm 1
6+
# sudo nvidia-smi -i 0 --lock-gpu-clocks 2619,2619
7+
# See more here: https://github.com/triton-lang/triton/blob/d9f10ebdc5da53f73eb852fde73d8d7d80b679d1/python/triton/testing.py#L487
8+
9+
import time
10+
import torch
11+
12+
from triton.testing import do_bench
13+
14+
from flash_attn.cute.interface import flash_attn_varlen_func
15+
16+
17+
device = "cuda"
18+
dtype = torch.bfloat16
19+
seqlen_q = 1
20+
nheads_q = 128
21+
nheads_kv = 1 # MQA-128
22+
headdim = 64
23+
headdim_v = 512
24+
causal = True
25+
26+
batch_size = 128
27+
page_sizes = [None, 16, 64, 128] # None = non-paged baseline
28+
29+
torch.manual_seed(0)
30+
31+
print(f"\nMLA paged KV, nheads_q = {nheads_q}, nheads_kv = {nheads_kv}, headdim = {headdim}, headdim_v = {headdim_v}, causal = {causal}")
32+
33+
for seqlen in [s * 1024 for s in [1, 2, 4, 8, 16, 32, 64]]:
34+
# Varlen format: (total_tokens, nheads, hdim)
35+
total_q = batch_size * seqlen_q
36+
total_k = batch_size * seqlen
37+
38+
try:
39+
q = torch.randn(total_q, nheads_q, headdim, dtype=dtype, device=device)
40+
k = torch.randn(total_k, nheads_kv, headdim, dtype=dtype, device=device)
41+
v = torch.randn(total_k, nheads_kv, headdim_v, dtype=dtype, device=device)
42+
qv = torch.randn(total_q, nheads_q, headdim_v, dtype=dtype, device=device)
43+
except torch.OutOfMemoryError:
44+
continue
45+
46+
cu_seqlens_q = torch.arange(0, total_q + seqlen_q, seqlen_q, dtype=torch.int32, device=device)
47+
cu_seqlens_k = torch.arange(0, total_k + seqlen, seqlen, dtype=torch.int32, device=device)
48+
49+
# Mem I/O: KV read + Q/QV read + O write
50+
total_seqlen = seqlen * batch_size
51+
mem_io = (
52+
total_seqlen * nheads_kv * (headdim + headdim_v) * 2 # K + V read
53+
+ q.numel() * 2 + qv.numel() * 2 # Q + QV read
54+
+ total_q * nheads_q * headdim_v * 2 # O write
55+
)
56+
# FLOPs: QK^T + PV (with qv, PV uses headdim_v)
57+
flops = seqlen_q * total_seqlen * nheads_q * (headdim + headdim_v * 2) * 2
58+
59+
for page_size in page_sizes:
60+
if page_size is None:
61+
# Non-paged baseline
62+
fn = lambda: flash_attn_varlen_func( # noqa: E731
63+
q, k, v, qv=qv,
64+
cu_seqlens_q=cu_seqlens_q, cu_seqlens_k=cu_seqlens_k,
65+
max_seqlen_q=seqlen_q, max_seqlen_k=seqlen,
66+
causal=causal,
67+
)
68+
label = "non-paged"
69+
else:
70+
# Create paged KV
71+
num_pages_per_seq = (seqlen + page_size - 1) // page_size
72+
total_pages = num_pages_per_seq * batch_size
73+
k_paged = torch.zeros(total_pages, page_size, nheads_kv, headdim, device=device, dtype=dtype)
74+
v_paged = torch.zeros(total_pages, page_size, nheads_kv, headdim_v, device=device, dtype=dtype)
75+
page_table = torch.zeros(batch_size, num_pages_per_seq, dtype=torch.int32, device=device)
76+
for b in range(batch_size):
77+
for p in range(num_pages_per_seq):
78+
page_idx = b * num_pages_per_seq + p
79+
start = p * page_size
80+
end = min(start + page_size, seqlen)
81+
k_offset = b * seqlen
82+
if start < seqlen:
83+
k_paged[page_idx, :end - start] = k[k_offset + start:k_offset + end]
84+
v_paged[page_idx, :end - start] = v[k_offset + start:k_offset + end]
85+
page_table[b, p] = page_idx
86+
seqused_k = torch.full((batch_size,), seqlen, dtype=torch.int32, device=device)
87+
88+
fn = lambda kp=k_paged, vp=v_paged, pt=page_table, su=seqused_k: flash_attn_varlen_func( # noqa: E731
89+
q, kp, vp, qv=qv,
90+
cu_seqlens_q=cu_seqlens_q, cu_seqlens_k=None,
91+
max_seqlen_q=seqlen_q, max_seqlen_k=None,
92+
seqused_k=su, page_table=pt,
93+
causal=causal,
94+
)
95+
path = "TMA" if page_size == 128 else "cp.async"
96+
label = f"paged-{page_size} ({path})"
97+
98+
fn() # warmup / compile
99+
time.sleep(1) # avoid power throttling
100+
t = do_bench(fn, warmup=5, rep=20)
101+
print(
102+
f"Seqlen = {seqlen}, {label}: {t * 1e3:.1f} us, "
103+
f"{mem_io * 1e-9 / (t * 1e-3):.0f} GB/s, "
104+
f"{flops * 1e-12 / (t * 1e-3):.0f} TFLOPS/s"
105+
)
106+
107+
print(f"Arithmetic intensity: {flops / mem_io:.1f}")
108+
print()

flash_attn/cute/block_sparse_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,7 @@ def handle_block_sparse_empty_tile_correction_sm100(
754754
sScale: cute.Tensor,
755755
stats: list,
756756
correction_epilogue: Callable,
757-
thr_mma_pv: cute.core.ThrMma,
757+
thr_mma_pv: cute.ThrMma,
758758
tOtO: cute.Tensor,
759759
sO: cute.Tensor,
760760
pipeline_sm_stats: cutlass.pipeline.PipelineAsync,

flash_attn/cute/cute_dsl_utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def assume_tensor_aligned(t):
6161

6262
def to_cute_tensor(t, assumed_align=16, leading_dim=-1, fully_dynamic=False, enable_tvm_ffi=True):
6363
"""Convert torch tensor to cute tensor for TVM FFI. leading_dim=-1 defaults to t.ndim-1."""
64+
if t is None:
65+
return None
6466
# NOTE: torch 2.9.1 doesn't support fp8 via DLPack but 2.11.0 nightly does
6567
# currently export raw bytes as uint8 and tell cutlass correct type
6668
# can directly export as fp8 when torch supports it

flash_attn/cute/flash_bwd.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -639,8 +639,8 @@ def kernel(
639639
thr_mma_dq = tiled_mma_dq.get_slice(tidx)
640640
acc_shape_dK = thr_mma_dkv.partition_shape_C((self.n_block_size, self.head_dim_padded))
641641
acc_shape_dV = thr_mma_dkv.partition_shape_C((self.n_block_size, self.head_dim_v_padded))
642-
acc_dK = cute.make_fragment(acc_shape_dK, cutlass.Float32)
643-
acc_dV = cute.make_fragment(acc_shape_dV, cutlass.Float32)
642+
acc_dK = cute.make_rmem_tensor(acc_shape_dK, cutlass.Float32)
643+
acc_dV = cute.make_rmem_tensor(acc_shape_dV, cutlass.Float32)
644644
acc_dK.fill(0.0)
645645
acc_dV.fill(0.0)
646646

@@ -887,7 +887,7 @@ def load_dO_next():
887887
acc_shape_SdP = mma_params.thr_mma_sdp.partition_shape_C(
888888
(self.m_block_size, self.n_block_size) if cutlass.const_expr(not self.SdP_swapAB) else (self.n_block_size, self.m_block_size)
889889
)
890-
acc_S = cute.make_fragment(acc_shape_SdP, cutlass.Float32)
890+
acc_S = cute.make_rmem_tensor(acc_shape_SdP, cutlass.Float32)
891891
acc_S.fill(0.0)
892892
cute.arch.cp_async_wait_group(1 if cutlass.const_expr(self.num_stages_Q > 1) else 0)
893893
cute.arch.barrier()
@@ -925,7 +925,7 @@ def load_dO_next():
925925
# if cute.arch.thread_idx()[0] == 0 and cute.arch.block_idx()[0] == bidx: cute.print_tensor(acc_S_mn)
926926

927927
# MMA dP
928-
acc_dP = cute.make_fragment(acc_shape_SdP, cutlass.Float32)
928+
acc_dP = cute.make_rmem_tensor(acc_shape_SdP, cutlass.Float32)
929929
acc_dP.fill(0.0)
930930
cute.arch.cp_async_wait_group(1 if cutlass.const_expr(self.num_stages_dO > 1) else 0)
931931
cute.arch.barrier()
@@ -989,7 +989,7 @@ def dQ_mma(hook_fn):
989989
acc_shape_dQ = mma_params.thr_mma_dq.partition_shape_C(
990990
(self.m_block_size, self.head_dim_padded) if cutlass.const_expr(not self.dQ_swapAB) else (self.head_dim_padded, self.m_block_size)
991991
)
992-
acc_dQ = cute.make_fragment(acc_shape_dQ, cutlass.Float32)
992+
acc_dQ = cute.make_rmem_tensor(acc_shape_dQ, cutlass.Float32)
993993
acc_dQ.fill(0.0)
994994
sm80_utils.gemm(
995995
mma_params.thr_mma_dq, acc_dQ, mma_params.tdQrdS, mma_params.tdQrK,

flash_attn/cute/flash_bwd_postprocess.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ def kernel(
398398
g2s_thr_copy = tiled_copy_accum.get_slice(tidx)
399399

400400
# S -> R
401-
tdQrdQ_fp32 = cute.make_fragment(tdQrdQ.shape, cutlass.Float32)
401+
tdQrdQ_fp32 = cute.make_rmem_tensor(tdQrdQ.shape, cutlass.Float32)
402402
tdQrdQ_s2r = cute.make_tensor(tdQrdQ_fp32.iterator, tdQrdQ_fp32.shape)
403403

404404
smem_copy_atom = sm100_utils_basic.get_smem_store_op(
@@ -410,7 +410,7 @@ def kernel(
410410
tiler_mn=tiled_tmem_ld.tiler_mn,
411411
)
412412
tdQsdQ_r2s = thr_tmem_ld.partition_D(thr_mma_dsk.partition_C(sdQ))
413-
tdQrdQ_r2s = cute.make_fragment(tdQsdQ_r2s.shape, self.dtype)
413+
tdQrdQ_r2s = cute.make_rmem_tensor(tdQsdQ_r2s.shape, self.dtype)
414414

415415
num_stages = cute.size(tdQrdQ_fp32, mode=[1])
416416
stage_stride = self.dQ_reduce_ncol
@@ -510,7 +510,7 @@ def kernel(
510510
acc_shape = tiled_mma.partition_shape_C(
511511
tile_shape if const_expr(not dQ_swapAB) else tile_shape[::-1]
512512
)
513-
acc = cute.make_fragment(acc_shape, cutlass.Float32)
513+
acc = cute.make_rmem_tensor(acc_shape, cutlass.Float32)
514514
assert cute.size(acc) == cute.size(tdQsdQaccum)
515515
else:
516516
thr_mma = tiled_mma.get_slice(0) # 1-CTA
@@ -526,7 +526,7 @@ def kernel(
526526
tiled_copy_t2r = tcgen05.make_tmem_copy(tmem_load_atom, tdQtdQ)
527527
thr_copy_t2r = tiled_copy_t2r.get_slice(tidx)
528528
tdQrdQ_t2r_shape = thr_copy_t2r.partition_D(tdQcdQ).shape
529-
acc = cute.make_fragment(tdQrdQ_t2r_shape, Float32)
529+
acc = cute.make_rmem_tensor(tdQrdQ_t2r_shape, Float32)
530530
tdQrdQaccum = cute.make_tensor(acc.iterator, cute.make_layout(tdQsdQaccum.shape))
531531
cute.autovec_copy(tdQsdQaccum, tdQrdQaccum)
532532
# Convert tdQrdQaccum from fp32 to fp16/bf16

flash_attn/cute/flash_bwd_sm100.py

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,11 +1674,11 @@ def relay(
16741674
@cute.jit
16751675
def load(
16761676
self,
1677-
thr_mma_S: cute.core.ThrMma,
1678-
thr_mma_dP: cute.core.ThrMma,
1679-
thr_mma_dV: cute.core.ThrMma,
1680-
thr_mma_dK: cute.core.ThrMma,
1681-
thr_mma_dQ: cute.core.ThrMma,
1677+
thr_mma_S: cute.ThrMma,
1678+
thr_mma_dP: cute.ThrMma,
1679+
thr_mma_dV: cute.ThrMma,
1680+
thr_mma_dK: cute.ThrMma,
1681+
thr_mma_dQ: cute.ThrMma,
16821682
mQ: cute.Tensor,
16831683
mK: cute.Tensor,
16841684
mKt: Optional[cute.Tensor],
@@ -2821,10 +2821,10 @@ def apply_score_mod_bwd(
28212821
@cute.jit
28222822
def compute_loop(
28232823
self,
2824-
thr_mma_S: cute.core.ThrMma,
2825-
thr_mma_dP: cute.core.ThrMma,
2826-
thr_mma_dV: cute.core.ThrMma,
2827-
thr_mma_dK: cute.core.ThrMma,
2824+
thr_mma_S: cute.ThrMma,
2825+
thr_mma_dP: cute.ThrMma,
2826+
thr_mma_dV: cute.ThrMma,
2827+
thr_mma_dK: cute.ThrMma,
28282828
tStS: cute.Tensor,
28292829
tdPtdP: cute.Tensor,
28302830
tdVtdV: cute.Tensor,
@@ -3047,14 +3047,14 @@ def compute_loop(
30473047
m_block_oob = m_block >= m_block_max
30483048
# Prefetch 1 stage of LSE
30493049
pipeline_LSE.consumer_wait(consumer_state_LSE)
3050-
tSrLSE_s2r = cute.make_fragment(tScS_t2r[None, 0, 0, 0].shape, Float32)
3050+
tSrLSE_s2r = cute.make_rmem_tensor(tScS_t2r[None, 0, 0, 0].shape, Float32)
30513051
if const_expr(prefetch_LSE and not self.shuffle_LSE):
30523052
cute.autovec_copy(tSsLSE[None, 0, 0, 0, consumer_state_LSE.index], tSrLSE_s2r)
30533053

30543054
pipeline_S_P.consumer_wait(consumer_state_S_P_dP)
30553055
# pipeline_S_P.sync_object_full.wait(0, consumer_phase_S_P_dP)
30563056
#### TMEM->RMEM (Load S from TMEM)
3057-
tSrS_t2r = cute.make_fragment(tScS_t2r.shape, Float32)
3057+
tSrS_t2r = cute.make_rmem_tensor(tScS_t2r.shape, Float32)
30583058
cute.copy(thr_copy_t2r, tStS_t2r, tSrS_t2r)
30593059

30603060
if const_expr(self.tile_hdim == 192):
@@ -3105,7 +3105,7 @@ def compute_loop(
31053105
#### P = exp(S - LSE)
31063106
# ---------------------------------------------
31073107
lane_idx = cute.arch.lane_idx()
3108-
tSrP_r2t_f32 = cute.make_fragment(tScP_r2t.shape, Float32) # 64
3108+
tSrP_r2t_f32 = cute.make_rmem_tensor(tScP_r2t.shape, Float32) # 64
31093109
tSrP_r2t = cute.recast_tensor(tSrP_r2t_f32, self.q_dtype)
31103110
for stage in cutlass.range_constexpr(num_stages):
31113111
tSrS_cur = tSrS_t2r[None, stage, 0, 0]
@@ -3167,7 +3167,7 @@ def compute_loop(
31673167

31683168
##### dS.T = P.T * (dP.T - Psum)
31693169
for stage in cutlass.range_constexpr(num_stages):
3170-
tdPrdP_t2r = cute.make_fragment(tScS_t2r[None, 0, None, None].shape, Float32)
3170+
tdPrdP_t2r = cute.make_rmem_tensor(tScS_t2r[None, 0, None, None].shape, Float32)
31713171
cute.copy(thr_copy_t2r, tdPtdP_t2r[None, stage, None, None], tdPrdP_t2r)
31723172
cute.arch.fence_view_async_tmem_load()
31733173
self.compute_sync_barrier.arrive_and_wait()
@@ -3459,7 +3459,7 @@ def dQacc_reduce(
34593459
self,
34603460
mdQaccum: cute.Tensor,
34613461
sdQaccum: cute.Tensor,
3462-
thr_mma_dQ: cute.core.ThrMma,
3462+
thr_mma_dQ: cute.ThrMma,
34633463
tdQtdQ: cute.Tensor,
34643464
pipeline_dQ: PipelineAsync,
34653465
dQaccum_empty_mbar_ptr: Optional[cute.Pointer],
@@ -3590,7 +3590,7 @@ def dQacc_reduce(
35903590
m_block_oob_upper = m_block >= m_block_max
35913591
pipeline_dQ.consumer_wait(dQ_consumer_state)
35923592
# TMEM -> RMEM
3593-
tdQrdQ_t2r = cute.make_fragment(tdQrdQ_t2r_shape, Float32)
3593+
tdQrdQ_t2r = cute.make_rmem_tensor(tdQrdQ_t2r_shape, Float32)
35943594
cute.copy(thr_copy_t2r, tdQtdQ_t2r, tdQrdQ_t2r)
35953595
cute.arch.fence_view_async_tmem_load()
35963596
cute.arch.sync_warp()
@@ -3721,8 +3721,8 @@ def epilogue_dKV(
37213721
head_idx: Int32,
37223722
n_block: Int32,
37233723
seqlen,
3724-
thr_mma_dV: cute.core.ThrMma,
3725-
thr_mma_dK: cute.core.ThrMma,
3724+
thr_mma_dV: cute.ThrMma,
3725+
thr_mma_dK: cute.ThrMma,
37263726
tdVtdV: cute.Tensor,
37273727
tdKtdK: cute.Tensor,
37283728
mdV: cute.Tensor,
@@ -3758,7 +3758,7 @@ def epilogue_dKV(
37583758

37593759
tdVcdV_t2r_p = thr_tmem_ld_dV.partition_D(tdVcdV_tensor)
37603760
tdVcdV_t2r = self.split_wg(tdVcdV_t2r_p, wg_idx, num_wg)
3761-
tdVrdV_t2r = cute.make_fragment(tdVcdV_t2r.shape, Float32)
3761+
tdVrdV_t2r = cute.make_rmem_tensor(tdVcdV_t2r.shape, Float32)
37623762

37633763
cute.copy(thr_tmem_ld_dV, tdVtdV_t2r, tdVrdV_t2r)
37643764
cute.arch.fence_view_async_tmem_load()
@@ -3775,7 +3775,7 @@ def epilogue_dKV(
37753775
tiler_mn=tiled_tmem_ld_dV.tiler_mn,
37763776
)
37773777

3778-
tdVrdV_r2s = cute.make_fragment(tdVrdV_t2r.shape, self.dv_dtype)
3778+
tdVrdV_r2s = cute.make_rmem_tensor(tdVrdV_t2r.shape, self.dv_dtype)
37793779
for i in cutlass.range_constexpr(cute.size(tdVrdV_t2r, mode=[1])):
37803780
dV_vec = tdVrdV_t2r[(None, i, 0, 0)].load()
37813781
tdVrdV_r2s[(None, i, 0, 0)].store(dV_vec.to(self.dv_dtype))
@@ -3810,7 +3810,7 @@ def epilogue_dKV(
38103810

38113811
tdKcdK_t2r_p = thr_tmem_ld_dK.partition_D(tdKcdK_tensor)
38123812
tdKcdK_t2r = self.split_wg(tdKcdK_t2r_p, wg_idx, num_wg)
3813-
tdKrdK_t2r = cute.make_fragment(tdKcdK_t2r.shape, Float32)
3813+
tdKrdK_t2r = cute.make_rmem_tensor(tdKcdK_t2r.shape, Float32)
38143814

38153815
cute.copy(tiled_tmem_ld_dK, tdKtdK_t2r, tdKrdK_t2r)
38163816
cute.arch.fence_view_async_tmem_load()
@@ -3828,7 +3828,7 @@ def epilogue_dKV(
38283828
tiler_mn=tiled_tmem_ld_dK.tiler_mn,
38293829
)
38303830

3831-
tdKrdK_r2s = cute.make_fragment(tdKrdK_t2r.shape, self.dk_dtype)
3831+
tdKrdK_r2s = cute.make_rmem_tensor(tdKrdK_t2r.shape, self.dk_dtype)
38323832

38333833
for i in cutlass.range_constexpr(cute.size(tdKrdK_t2r, mode=[1])):
38343834
dK_vec = tdKrdK_t2r[(None, i, 0, 0)].load() * softmax_scale
@@ -3857,7 +3857,7 @@ def epilogue_dK_or_dV_tma(
38573857
head_idx: Int32,
38583858
n_block: Int32,
38593859
seqlen,
3860-
thr_mma: cute.core.ThrMma,
3860+
thr_mma: cute.ThrMma,
38613861
tdKVtdKV: cute.Tensor,
38623862
mdKV: cute.Tensor,
38633863
sdKV: cute.Tensor,
@@ -3976,7 +3976,7 @@ def epilogue_dK_or_dV_tma(
39763976
if const_expr(num_epi_stages > 1):
39773977
tdKVcdKV_t2r = tdKVcdKV_t2r[None, epi_stage]
39783978

3979-
tdKVrdKV_t2r = cute.make_fragment(tdKVcdKV_t2r.shape, Float32)
3979+
tdKVrdKV_t2r = cute.make_rmem_tensor(tdKVcdKV_t2r.shape, Float32)
39803980

39813981
assert cute.size(tdKVrdKV_t2r) == cute.size(tdKVtdKV_t2r) // cute.arch.WARP_SIZE, (
39823982
"RMEM<->TMEM fragment size mismatch"
@@ -3992,7 +3992,7 @@ def epilogue_dK_or_dV_tma(
39923992
tdKVrdKV_t2r[2 * i], tdKVrdKV_t2r[2 * i + 1] = cute.arch.mul_packed_f32x2(
39933993
(tdKVrdKV_t2r[2 * i], tdKVrdKV_t2r[2 * i + 1]), (scale, scale)
39943994
)
3995-
tdKVrdKV = cute.make_fragment(tdKVrdKV_t2r.shape, dtype) # (32 columns)
3995+
tdKVrdKV = cute.make_rmem_tensor(tdKVrdKV_t2r.shape, dtype) # (32 columns)
39963996
tdKVrdKV.store(tdKVrdKV_t2r.load().to(dtype))
39973997

39983998
# RMEM -> SMEM -- copy, fence and barrier

flash_attn/cute/flash_bwd_sm90.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ def load(
10171017
def apply_score_mod(
10181018
self,
10191019
acc_S: cute.Tensor,
1020-
thr_mma_SdP: cute.core.ThrMma,
1020+
thr_mma_SdP: cute.ThrMma,
10211021
batch_idx,
10221022
head_idx,
10231023
m_block,
@@ -1061,7 +1061,7 @@ def apply_score_mod_bwd(
10611061
self,
10621062
grad_tensor: cute.Tensor,
10631063
score_tensor: cute.Tensor,
1064-
thr_mma_SdP: cute.core.ThrMma,
1064+
thr_mma_SdP: cute.ThrMma,
10651065
batch_idx,
10661066
head_idx,
10671067
m_block,

0 commit comments

Comments
 (0)