@@ -45,6 +45,7 @@ def kernel(
4545 shared_storage : cutlass .Constexpr ,
4646 tile_shape : cutlass .Constexpr ,
4747 dtype : cutlass .Constexpr ,
48+ row_count : cutlass .Constexpr ,
4849 ):
4950 smem = cutlass .utils .SmemAllocator ()
5051 storage = smem .allocate (shared_storage )
@@ -97,17 +98,19 @@ def kernel(
9798 )
9899 for row_step in cutlass .range (self .rows_per_cta , unroll = 1 ):
99100 load_pipeline .consumer_wait (consumer_state )
100- dst_tile = dst_tiles [(None , (batch_idx , row_base + row_step , 0 ))]
101101 stage_smem_tile = smem_tile [(consumer_state .index , None , None , None )]
102- block_copy (
103- store_atom ,
104- cute .group_modes (stage_smem_tile , 0 , 3 ),
105- cute .group_modes (dst_tile , 0 , 1 ),
106- )
107- cute .arch .cp_async_bulk_commit_group ()
108- cute .arch .cp_async_bulk_wait_group (0 )
109- cute .arch .fence_view_async_shared ()
110- cute .arch .sync_warp ()
102+ # Tail CTAs may TMA-load full-OOB rows as zero-filled stages; skip their stores.
103+ if row_base + row_step < row_count :
104+ dst_tile = dst_tiles [(None , (batch_idx , row_base + row_step , 0 ))]
105+ block_copy (
106+ store_atom ,
107+ cute .group_modes (stage_smem_tile , 0 , 3 ),
108+ cute .group_modes (dst_tile , 0 , 1 ),
109+ )
110+ cute .arch .cp_async_bulk_commit_group ()
111+ cute .arch .cp_async_bulk_wait_group (0 )
112+ cute .arch .fence_view_async_shared ()
113+ cute .arch .sync_warp ()
111114 load_pipeline .consumer_release (consumer_state )
112115 consumer_state .advance ()
113116
@@ -139,6 +142,7 @@ def __call__(self, src: cute.Tensor, dst: cute.Tensor):
139142 shared_storage ,
140143 tile_shape ,
141144 src .element_type ,
145+ src .shape [1 ],
142146 ).launch (
143147 grid = [src .shape [0 ], cute .ceil_div (src .shape [1 ], self .rows_per_cta ), 1 ],
144148 block = [threads , 1 , 1 ],
@@ -161,9 +165,8 @@ def interface(self, src: torch.Tensor) -> torch.Tensor:
161165 raise ValueError (f"Expected a 3D tensor, got rank { src .ndim } " )
162166 if src .data_ptr () % 16 != 0 :
163167 raise ValueError ("Input tensor must be 16-byte aligned" )
164- if src .shape [1 ] % self .rows_per_cta != 0 :
165- raise ValueError ("Input row dimension must be divisible by rows_per_cta" )
166-
168+ if src .shape [2 ] * src .element_size () % 16 != 0 :
169+ raise ValueError ("Input innermost dimension must span a multiple of 16 bytes" )
167170 dst = torch .empty_like (src )
168171 if dst .data_ptr () % 16 != 0 :
169172 raise ValueError ("Output tensor must be 16-byte aligned" )
0 commit comments