""" Diagnostic: Compare TMEM column mapping between QK C-fragment and PV A-fragment. Write the TMEM column index for each logical element to GMEM. """ import torch, cutlass, cutlass.cute as cute, cutlass.utils as utils from cutlass.cute.nvgpu import tcgen05 from cutlass import Float32, BFloat16, Int32 from cutlass.utils import LayoutEnum import cutlass.torch as ct import cuda.bindings.driver as cuda class TmemLayoutDiag: def __init__(self): self.threads_per_cta = 128 # just 1 warp for simplicity @cute.jit def __call__(self, qk_cols, pv16_cols, stream): # qk_cols: GMEM tensor (128,) to store QK C-fragment TMEM column indices # pv16_cols: GMEM tensor (128,) to store PV A-fragment TMEM column indices # Create QK MMA (128,128) qk_mma = utils.sm100.make_trivial_tiled_mma( BFloat16, BFloat16, LayoutEnum.ROW_MAJOR, LayoutEnum.ROW_MAJOR, Float32, tcgen05.CtaGroup.ONE, (128, 128), tcgen05.OperandSource.SMEM) # Create PV (128,16) MMA pv16_mma = utils.sm100.make_trivial_tiled_mma( BFloat16, BFloat16, cute.nvgpu.OperandMajorMode.K, LayoutEnum.ROW_MAJOR, Float32, tcgen05.CtaGroup.ONE, (128, 16), tcgen05.OperandSource.TMEM) qk_inst_k = int(cute.size(qk_mma.shape_mnk, mode=[2])) qk_mma_tiler = (128, 128, int(qk_inst_k * 4)) pv16_mma_tiler = (128, qk_inst_k, 128) # Create layouts p_tmem_16 = utils.sm100.make_smem_layout_a(pv16_mma, pv16_mma_tiler, BFloat16, 1) # Create tStS (QK C-fragment) qk_thr = qk_mma.get_slice(0) qk_acc = qk_thr.partition_shape_C(qk_mma_tiler[:2]) tStS = qk_thr.make_fragment_C(qk_acc) # Create tP for PV16 tP16 = cute.make_tensor(tStS.iterator, p_tmem_16.outer) pv16_thr = pv16_mma.get_slice(0) tOrP16 = pv16_thr.make_fragment_A(tP16) # Write sizes to GMEM # For thread 0 only tidx, _, _ = cute.arch.thread_idx() if tidx == 0: # Write tStS size and tP16 size qk_cols[0] = Int32(cute.size(tStS)) pv16_cols[0] = Int32(cute.size(tP16)) # Write qk_inst_k qk_cols[1] = Int32(qk_inst_k) # Write p_tmem_16 outer shape pv16_cols[1] = Int32(cute.size(p_tmem_16.outer, mode=[0])) pv16_cols[2] = Int32(cute.size(p_tmem_16.outer, mode=[1])) if p_tmem_16.outer.ndim >= 2 else Int32(0) # Write QK acc shape qk_cols[2] = Int32(qk_acc[0]) if hasattr(qk_acc, '__getitem__') else Int32(0) def run(self): qk_cols = torch.zeros(4, dtype=torch.int32, device='cuda') pv16_cols = torch.zeros(4, dtype=torch.int32, device='cuda') mQ = ct.from_dlpack(qk_cols).mark_layout_dynamic() mP = ct.from_dlpack(pv16_cols).mark_layout_dynamic() stream = cuda.CUstream(torch.cuda.current_stream().cuda_stream) print("Compiling...", flush=True) compiled = cute.compile(self, mQ, mP, stream) compiled(mQ, mP, stream) torch.cuda.synchronize() print(f"QK results: {qk_cols.tolist()}") print(f"PV16 results: {pv16_cols.tolist()}") if __name__ == "__main__": TmemLayoutDiag().run()