TensorTonic
Problems
Online Softmax Kernel in Triton
Activation FunctionsTransformersGPU Programming
Medium

Implement row-wise softmax with the online (one-pass) algorithm. For each row iii and column jjj:

out[i,j]=exp⁡(x[i,j]−mi)li\texttt{out}[i, j] = \frac{\exp(x[i, j] - m_i)}{l_i}out[i,j]=li​exp(x[i,j]−mi​)​

The standard implementation makes two passes over each row: one for the max, one for the normalized sum. The online formulation walks the row in chunks, maintaining a running max mmm and a running denominator lll, updating both per chunk:

mnew=max⁡(m,max⁡j∈chunkxj),lnew=l⋅em−mnew+∑j∈chunkexj−mnewm_\text{new} = \max(m, \max_{j \in \text{chunk}} x_j), \quad l_\text{new} = l \cdot e^{m - m_\text{new}} + \sum_{j \in \text{chunk}} e^{x_j - m_\text{new}}mnew​=max(m,j∈chunkmax​xj​),lnew​=l⋅em−mnew​+j∈chunk∑​exj​−mnew​

This is the core trick behind FlashAttention's softmax, isolated as a self-contained kernel. Each program handles one row in a single forward pass over the chunks, then a second pass writes the normalized output.

Loading visualization...

Examples

Input: x = [[1.0, 2.0, 3.0]]

Output: [[0.0900, 0.2447, 0.6652]]

Input: x = [[0.0, 0.0], [1.0, 1.0]]

Output: [[0.5, 0.5], [0.5, 0.5]]

Hint 1

First pass: walk the row in chunks. For each chunk, compute mnew=max⁡(m,mchunk)m_\text{new} = \max(m, m_\text{chunk})mnew​=max(m,mchunk​), rescale lll by exp⁡(m−mnew)\exp(m - m_\text{new})exp(m−mnew​), add the chunk contribution, then update mmm.

Hint 2

Second pass: walk the row again with the same chunk loop and write exp⁡(chunk−m)/l\exp(\text{chunk} - m) / lexp(chunk−m)/l at the chunk offsets.

Hint 3

Mask both passes with offsets < N\texttt{offsets < N}offsets < N. For the max pass, load with other=-float(’inf’)\texttt{other=-float('inf')}other=-float(’inf’) so padded lanes never drag the max down.

Requirements

  • Use one Triton program per row; walk the row in chunks instead of holding it whole in registers
  • Maintain a running max and a running denominator across chunks using the online softmax update
  • Make a second pass over the same chunks to write the normalized output
  • Mask each chunk so non-power-of-two row widths are correct
  • The solve\texttt{solve}solve signature must not change

Constraints

  • 1≤M≤20481 \le M \le 20481≤M≤2048, 1≤N≤1310721 \le N \le 1310721≤N≤131072.
  • All tensors are torch.float32 on cuda.
  • Tolerance: combined atol=1e-2 + rtol=1e-2 * abs(expected) for N≥64N \ge 64N≥64 due to multi-stage reduction drift.
Try Similar Problems
Scaled Dot-Product Attention in TritonMediumRotary Position Embedding in TritonMediumKV Cache Append in TritonEasyFlashAttention Forward Kernel in TritonHardFused Row-Wise Softmax in TritonMediumFused Matmul + Bias + ReLU in TritonMediumGELU in TritonEasyReLU in TritonEasySiLU in TritonEasySoftmax as a CUDA KernelMediumTriton Row-Wise SoftmaxMediumImplement Swish (SiLU) as a CUDA KernelEasy

Accepts: array

You must run your code first.

Kernel performance

Submit a correct solution to see your kernel performance.

Online Softmax Kernel in Triton

Online Softmax Kernel in Triton

Activation FunctionsTransformersGPU Programming
Medium

Implement row-wise softmax with the online (one-pass) algorithm. For each row iii and column jjj:

out[i,j]=exp⁡(x[i,j]−mi)li\texttt{out}[i, j] = \frac{\exp(x[i, j] - m_i)}{l_i}out[i,j]=li​exp(x[i,j]−mi​)​

The standard implementation makes two passes over each row: one for the max, one for the normalized sum. The online formulation walks the row in chunks, maintaining a running max mmm and a running denominator lll, updating both per chunk:

mnew=max⁡(m,max⁡j∈chunkxj),lnew=l⋅em−mnew+∑j∈chunkexj−mnewm_\text{new} = \max(m, \max_{j \in \text{chunk}} x_j), \quad l_\text{new} = l \cdot e^{m - m_\text{new}} + \sum_{j \in \text{chunk}} e^{x_j - m_\text{new}}mnew​=max(m,j∈chunkmax​xj​),lnew​=l⋅em−mnew​+j∈chunk∑​exj​−mnew​

This is the core trick behind FlashAttention's softmax, isolated as a self-contained kernel. Each program handles one row in a single forward pass over the chunks, then a second pass writes the normalized output.

Loading visualization...

Examples

Input: x = [[1.0, 2.0, 3.0]]

Output: [[0.0900, 0.2447, 0.6652]]

Input: x = [[0.0, 0.0], [1.0, 1.0]]

Output: [[0.5, 0.5], [0.5, 0.5]]

Hint 1

First pass: walk the row in chunks. For each chunk, compute mnew=max⁡(m,mchunk)m_\text{new} = \max(m, m_\text{chunk})mnew​=max(m,mchunk​), rescale lll by exp⁡(m−mnew)\exp(m - m_\text{new})exp(m−mnew​), add the chunk contribution, then update mmm.

Hint 2

Second pass: walk the row again with the same chunk loop and write exp⁡(chunk−m)/l\exp(\text{chunk} - m) / lexp(chunk−m)/l at the chunk offsets.

Hint 3

Mask both passes with offsets < N\texttt{offsets < N}offsets < N. For the max pass, load with other=-float(’inf’)\texttt{other=-float('inf')}other=-float(’inf’) so padded lanes never drag the max down.

Requirements

  • Use one Triton program per row; walk the row in chunks instead of holding it whole in registers
  • Maintain a running max and a running denominator across chunks using the online softmax update
  • Make a second pass over the same chunks to write the normalized output
  • Mask each chunk so non-power-of-two row widths are correct
  • The solve\texttt{solve}solve signature must not change

Constraints

  • 1≤M≤20481 \le M \le 20481≤M≤2048, 1≤N≤1310721 \le N \le 1310721≤N≤131072.
  • All tensors are torch.float32 on cuda.
  • Tolerance: combined atol=1e-2 + rtol=1e-2 * abs(expected) for N≥64N \ge 64N≥64 due to multi-stage reduction drift.
Try Similar Problems
Scaled Dot-Product Attention in TritonMediumRotary Position Embedding in TritonMediumKV Cache Append in TritonEasyFlashAttention Forward Kernel in TritonHardFused Row-Wise Softmax in TritonMediumFused Matmul + Bias + ReLU in TritonMediumGELU in TritonEasyReLU in TritonEasySiLU in TritonEasySoftmax as a CUDA KernelMediumTriton Row-Wise SoftmaxMediumImplement Swish (SiLU) as a CUDA KernelEasy

Accepts: array

You must run your code first.

Kernel performance

Submit a correct solution to see your kernel performance.

Problems
Loading...
1 / 1