TensorTonic
Problems
Split-K Matmul in Triton
Linear AlgebraGPU Programming
Hard

Reimplement tiled matmul with a split-K parallelization that adds a third axis to the grid along the reduction dimension. For each output entry:

C[i,j]=∑k=0K−1A[i,k]⋅B[k,j]C[i, j] = \sum_{k=0}^{K-1} A[i, k] \cdot B[k, j]C[i,j]=k=0∑K−1​A[i,k]⋅B[k,j]

The standard 2D-grid matmul has one program per output tile. When MMM and NNN are small relative to KKK (a tall-skinny GEMM), this leaves most SMs idle. Split-K fixes the under-utilization by letting each (pid_m,pid_n,pid_k)(\text{pid\_m}, \text{pid\_n}, \text{pid\_k})(pid_m,pid_n,pid_k) program compute a partial sum over its KKK slice and atomic-add it into the shared output tile.

With SPLIT_K=4\texttt{SPLIT\_K}=4SPLIT_K=4 on a four-tile output grid, the launch goes from four programs to sixteen, which is the difference between five percent and twenty percent SM occupancy on a modern GPU. This is the standard fix called out in the Triton matmul tutorial for skinny GEMMs.

Loading visualization...

Examples

Input: A = [[1, 2], [3, 4]], B = [[5, 6], [7, 8]]

Output: [[19, 22], [43, 50]]

Input: A = [[1, 0, 1], [0, 1, 0]], B = [[1, 2], [3, 4], [5, 6]]

Output: [[6, 8], [3, 4]]

Hint 1

Pack the three program IDs into a 1D grid of size ⌈M/BLOCK_M⌉⋅⌈N/BLOCK_N⌉⋅SPLIT_K\lceil M/\text{BLOCK\_M} \rceil \cdot \lceil N/\text{BLOCK\_N} \rceil \cdot \texttt{SPLIT\_K}⌈M/BLOCK_M⌉⋅⌈N/BLOCK_N⌉⋅SPLIT_K and decode pid_k\text{pid\_k}pid_k, pid_m\text{pid\_m}pid_m, pid_n\text{pid\_n}pid_n inside the kernel.

Hint 2

Each program walks kkk over only its slice: from pid_k⋅(K/SPLIT_K)\text{pid\_k} \cdot (K / \texttt{SPLIT\_K})pid_k⋅(K/SPLIT_K) to (pid_k+1)⋅(K/SPLIT_K)(\text{pid\_k}+1) \cdot (K / \texttt{SPLIT\_K})(pid_k+1)⋅(K/SPLIT_K). Accumulate a partial (BLOCK_M,BLOCK_N)(\text{BLOCK\_M}, \text{BLOCK\_N})(BLOCK_M,BLOCK_N) tile.

Hint 3

Replace the final tl.store\texttt{tl.store}tl.store with \texttt{tl.atomic_add} so partials from every pid_k\text{pid\_k}pid_k for the same output tile combine correctly. The launcher must zero out\texttt{out}out first.

Requirements

  • Add a SPLIT_K\texttt{SPLIT\_K}SPLIT_K axis to the grid so each program reduces only its KKK slice
  • Atomic-add each program's partial into the shared output tile
  • Pre-zero out\texttt{out}out on the host so atomics start from a clean slate
  • Mask the loads and stores on the MMM, NNN, and KKK tails
  • The solve\texttt{solve}solve signature must not change
  • use ieee precision for consistent float32 accuracy across gpus.

Constraints

  • 1≤M,N,K≤7681 \le M, N, K \le 7681≤M,N,K≤768.
  • All tensors are torch.float32 on cuda.
  • Tolerance: atol=1e-2 + rtol=1e-2 * abs(expected) for K≥128K \ge 128K≥128. The tolerance is intentionally loose because tl.atomic_add accumulation order across programs is non-deterministic, so partial sums combine in fp32 in a different order than the torch reference.
Try Similar Problems
Grouped Program-ID Matmul in TritonHardBlock-Pointer Matmul in TritonMediumScaled Dot-Product Attention in TritonMediumAutotuned Matrix Multiplication in TritonMediumTiled Transpose in TritonMediumGEMV: Matrix Vector Product in TritonMediumFused Matmul + Bias + ReLU in TritonMediumTiled Matrix Multiplication in TritonMediumTiled Matrix Multiplication as a CUDA KernelHardScaled Dot-Product Attention in CUDAHardFused Tiled Matmul and ReLUHardVector Addition in TritonEasy

Accepts: array

Accepts: array

You must run your code first.

Kernel performance

Submit a correct solution to see your kernel performance.

Split-K Matmul in Triton

Split-K Matmul in Triton

Linear AlgebraGPU Programming
Hard

Reimplement tiled matmul with a split-K parallelization that adds a third axis to the grid along the reduction dimension. For each output entry:

C[i,j]=∑k=0K−1A[i,k]⋅B[k,j]C[i, j] = \sum_{k=0}^{K-1} A[i, k] \cdot B[k, j]C[i,j]=k=0∑K−1​A[i,k]⋅B[k,j]

The standard 2D-grid matmul has one program per output tile. When MMM and NNN are small relative to KKK (a tall-skinny GEMM), this leaves most SMs idle. Split-K fixes the under-utilization by letting each (pid_m,pid_n,pid_k)(\text{pid\_m}, \text{pid\_n}, \text{pid\_k})(pid_m,pid_n,pid_k) program compute a partial sum over its KKK slice and atomic-add it into the shared output tile.

With SPLIT_K=4\texttt{SPLIT\_K}=4SPLIT_K=4 on a four-tile output grid, the launch goes from four programs to sixteen, which is the difference between five percent and twenty percent SM occupancy on a modern GPU. This is the standard fix called out in the Triton matmul tutorial for skinny GEMMs.

Loading visualization...

Examples

Input: A = [[1, 2], [3, 4]], B = [[5, 6], [7, 8]]

Output: [[19, 22], [43, 50]]

Input: A = [[1, 0, 1], [0, 1, 0]], B = [[1, 2], [3, 4], [5, 6]]

Output: [[6, 8], [3, 4]]

Hint 1

Pack the three program IDs into a 1D grid of size ⌈M/BLOCK_M⌉⋅⌈N/BLOCK_N⌉⋅SPLIT_K\lceil M/\text{BLOCK\_M} \rceil \cdot \lceil N/\text{BLOCK\_N} \rceil \cdot \texttt{SPLIT\_K}⌈M/BLOCK_M⌉⋅⌈N/BLOCK_N⌉⋅SPLIT_K and decode pid_k\text{pid\_k}pid_k, pid_m\text{pid\_m}pid_m, pid_n\text{pid\_n}pid_n inside the kernel.

Hint 2

Each program walks kkk over only its slice: from pid_k⋅(K/SPLIT_K)\text{pid\_k} \cdot (K / \texttt{SPLIT\_K})pid_k⋅(K/SPLIT_K) to (pid_k+1)⋅(K/SPLIT_K)(\text{pid\_k}+1) \cdot (K / \texttt{SPLIT\_K})(pid_k+1)⋅(K/SPLIT_K). Accumulate a partial (BLOCK_M,BLOCK_N)(\text{BLOCK\_M}, \text{BLOCK\_N})(BLOCK_M,BLOCK_N) tile.

Hint 3

Replace the final tl.store\texttt{tl.store}tl.store with \texttt{tl.atomic_add} so partials from every pid_k\text{pid\_k}pid_k for the same output tile combine correctly. The launcher must zero out\texttt{out}out first.

Requirements

  • Add a SPLIT_K\texttt{SPLIT\_K}SPLIT_K axis to the grid so each program reduces only its KKK slice
  • Atomic-add each program's partial into the shared output tile
  • Pre-zero out\texttt{out}out on the host so atomics start from a clean slate
  • Mask the loads and stores on the MMM, NNN, and KKK tails
  • The solve\texttt{solve}solve signature must not change
  • use ieee precision for consistent float32 accuracy across gpus.

Constraints

  • 1≤M,N,K≤7681 \le M, N, K \le 7681≤M,N,K≤768.
  • All tensors are torch.float32 on cuda.
  • Tolerance: atol=1e-2 + rtol=1e-2 * abs(expected) for K≥128K \ge 128K≥128. The tolerance is intentionally loose because tl.atomic_add accumulation order across programs is non-deterministic, so partial sums combine in fp32 in a different order than the torch reference.
Try Similar Problems
Grouped Program-ID Matmul in TritonHardBlock-Pointer Matmul in TritonMediumScaled Dot-Product Attention in TritonMediumAutotuned Matrix Multiplication in TritonMediumTiled Transpose in TritonMediumGEMV: Matrix Vector Product in TritonMediumFused Matmul + Bias + ReLU in TritonMediumTiled Matrix Multiplication in TritonMediumTiled Matrix Multiplication as a CUDA KernelHardScaled Dot-Product Attention in CUDAHardFused Tiled Matmul and ReLUHardVector Addition in TritonEasy

Accepts: array

Accepts: array

You must run your code first.

Kernel performance

Submit a correct solution to see your kernel performance.

Problems
Loading...
1 / 1