liangsu9988's picture
Promote latest kernel artifacts to main
8c8128e verified
Raw
History Blame Contribute Delete
5.67 kB
# Copyright (c) 2025, Tri Dao.
from typing import Type, Union, Optional
import cutlass
import cutlass.cute as cute
import cutlass.utils.hopper_helpers as sm90_utils_og
from cutlass.cute.nvgpu import warpgroup
from cutlass.cutlass_dsl import Numeric, dsl_user_op
from cutlass import Float32, Int32, Boolean, const_expr
from cutlass.utils import LayoutEnum
@dsl_user_op
def make_smem_layout(
dtype: Type[Numeric],
layout: LayoutEnum,
tile: cute.Tile,
stage: Optional[int] = None,
major_mode_size: Optional[int] = None,
*,
loc=None,
ip=None,
) -> Union[cute.Layout, cute.ComposedLayout]:
shape = cute.product_each(cute.shape(tile, loc=loc, ip=ip), loc=loc, ip=ip)
if const_expr(major_mode_size is None):
major_mode_size = shape[1] if layout.is_n_major_c() else shape[0]
smem_layout_atom = warpgroup.make_smem_layout_atom(
sm90_utils_og.get_smem_layout_atom(layout, dtype, major_mode_size),
dtype,
)
order = (1, 0, 2) if const_expr(layout.is_m_major_c()) else (0, 1, 2)
smem_layout_staged = cute.tile_to_shape(
smem_layout_atom,
cute.append(shape, stage) if const_expr(stage is not None) else shape,
order=order if const_expr(stage is not None) else order[:2],
)
return smem_layout_staged
# For compatibility with blackwell_helpers.py
make_smem_layout_epi = make_smem_layout
@dsl_user_op
def partition_for_epilogue(
cT: cute.Tensor,
epi_tile: cute.Tile,
tiled_copy: cute.TiledCopy,
tidx: Int32,
reference_src: bool, # do register tensors reference the src or dst layout of the tiled copy
*,
loc=None,
ip=None,
) -> cute.Tensor:
thr_copy = tiled_copy.get_slice(tidx)
cT_epi = cute.flat_divide(cT, epi_tile)
# (CPY, CPY_M, CPY_N, EPI_M, EPI_N)
if const_expr(reference_src):
return thr_copy.partition_S(cT_epi, loc=loc, ip=ip)
else:
return thr_copy.partition_D(cT_epi, loc=loc, ip=ip)
@cute.jit
def gemm(
tiled_mma: cute.TiledMma,
acc: cute.Tensor,
tCrA: cute.Tensor,
tCrB: cute.Tensor,
zero_init: cutlass.Constexpr[bool] = False,
wg_wait: cutlass.Constexpr[int] = 0,
# A_in_regs: cutlass.Constexpr[bool] = False,
swap_AB: cutlass.Constexpr[bool] = False,
) -> None:
if const_expr(swap_AB):
gemm(tiled_mma, acc, tCrB, tCrA, zero_init=zero_init, wg_wait=wg_wait, swap_AB=False)
else:
warpgroup.fence()
# We make a new mma_atom since we'll be modifying its attribute (accumulate).
# Otherwise the compiler complains "operand #0 does not dominate this use"
mma_atom = cute.make_mma_atom(tiled_mma.op)
mma_atom.set(warpgroup.Field.ACCUMULATE, not zero_init)
for k in cutlass.range_constexpr(cute.size(tCrA.shape[2])):
cute.gemm(mma_atom, acc, tCrA[None, None, k], tCrB[None, None, k], acc)
mma_atom.set(warpgroup.Field.ACCUMULATE, True)
warpgroup.commit_group()
if const_expr(wg_wait >= 0):
warpgroup.wait_group(wg_wait)
def gemm_zero_init(
tiled_mma: cute.TiledMma,
shape: cute.Shape,
tCrA: cute.Tensor,
tCrB: cute.Tensor,
A_idx: Optional[Int32] = None,
B_idx: Optional[Int32] = None,
wg_wait: int = -1,
swap_AB: bool = False,
) -> cute.Tensor:
if const_expr(swap_AB):
return gemm_zero_init(
tiled_mma, shape[::-1], tCrB, tCrA, B_idx, A_idx, wg_wait, swap_AB=False
)
else:
acc = cute.make_rmem_tensor(tiled_mma.partition_shape_C(shape), Float32)
rA = tCrA if const_expr(A_idx is None) else tCrA[None, None, None, A_idx]
rB = tCrB if const_expr(B_idx is None) else tCrB[None, None, None, B_idx]
gemm(tiled_mma, acc, rA, rB, zero_init=True, wg_wait=wg_wait)
return acc
def gemm_w_idx(
tiled_mma: cute.TiledMma,
acc: cute.Tensor,
tCrA: cute.Tensor,
tCrB: cute.Tensor,
zero_init: Boolean,
A_idx: Optional[Int32] = None,
B_idx: Optional[Int32] = None,
wg_wait: int = -1,
swap_AB: bool = False,
) -> None:
if const_expr(swap_AB):
gemm_w_idx(tiled_mma, acc, tCrB, tCrA, zero_init, B_idx, A_idx, wg_wait, swap_AB=False)
else:
rA = tCrA if const_expr(A_idx is None) else tCrA[None, None, None, A_idx]
rB = tCrB if const_expr(B_idx is None) else tCrB[None, None, None, B_idx]
gemm(tiled_mma, acc, rA, rB, zero_init=zero_init, wg_wait=wg_wait)
def partition_fragment_ABC(
thr_mma: cute.ThrMma,
shape_mnk: cute.Shape,
sA: Optional[cute.Tensor],
sB: Optional[cute.Tensor],
swap_AB: bool = False,
):
is_rs = thr_mma.op.a_src == warpgroup.OperandSource.RMEM
if const_expr(not swap_AB):
acc = cute.make_rmem_tensor(thr_mma.partition_shape_C(shape_mnk[:2]), Float32)
if const_expr(not is_rs):
assert sA is not None
tCrA = thr_mma.make_fragment_A(thr_mma.partition_A(sA))
else:
tCrA = thr_mma.make_fragment_A(thr_mma.partition_shape_A((shape_mnk[0], shape_mnk[2])))
assert sB is not None
tCrB = thr_mma.make_fragment_B(thr_mma.partition_B(sB))
else:
acc = cute.make_rmem_tensor(
thr_mma.partition_shape_C((shape_mnk[1], shape_mnk[0])), Float32
)
if const_expr(not is_rs):
assert sB is not None
tCrB = thr_mma.make_fragment_A(thr_mma.partition_A(sB))
else: # B in rmem
tCrB = thr_mma.make_fragment_A(thr_mma.partition_shape_A((shape_mnk[1], shape_mnk[2])))
assert sA is not None
tCrA = thr_mma.make_fragment_B(thr_mma.partition_B(sA))
return acc, tCrA, tCrB