TensorTonic
Problems
LayerNorm Backward in Triton
Neural NetworksGPU Programming
Hard

Implement the LayerNorm backward pass in Triton. Given the forward input x∈RM×Nx \in \mathbb{R}^{M \times N}x∈RM×N, the scale vector γ∈RN\gamma \in \mathbb{R}^{N}γ∈RN, and the upstream gradient dy∈RM×Ndy \in \mathbb{R}^{M \times N}dy∈RM×N, compute dxdxdx, dγd\gammadγ, and dβd\betadβ:

x^[i,j]=x[i,j]−μiσi2+ϵ,dynorm[i,j]=dy[i,j]⋅γ[j]\hat{x}[i, j] = \frac{x[i, j] - \mu_i}{\sqrt{\sigma_i^2 + \epsilon}}, \qquad dy_{\text{norm}}[i, j] = dy[i, j] \cdot \gamma[j]x^[i,j]=σi2​+ϵ​x[i,j]−μi​​,dynorm​[i,j]=dy[i,j]⋅γ[j] dx[i,j]=1σi2+ϵ⋅(dynorm[i,j]−1N∑kdynorm[i,k]−x^[i,j]⋅1N∑kdynorm[i,k]⋅x^[i,k])dx[i, j] = \frac{1}{\sqrt{\sigma_i^2 + \epsilon}} \cdot \left( dy_{\text{norm}}[i, j] - \frac{1}{N} \sum_k dy_{\text{norm}}[i, k] - \hat{x}[i, j] \cdot \frac{1}{N} \sum_k dy_{\text{norm}}[i, k] \cdot \hat{x}[i, k] \right)dx[i,j]=σi2​+ϵ​1​⋅(dynorm​[i,j]−N1​k∑​dynorm​[i,k]−x^[i,j]⋅N1​k∑​dynorm​[i,k]⋅x^[i,k]) dγ[j]=∑idy[i,j]⋅x^[i,j],dβ[j]=∑idy[i,j]d\gamma[j] = \sum_i dy[i, j] \cdot \hat{x}[i, j], \qquad d\beta[j] = \sum_i dy[i, j]dγ[j]=i∑​dy[i,j]⋅x^[i,j],dβ[j]=i∑​dy[i,j]

One program per row handles the dxdxdx computation. The reductions for dγd\gammadγ and dβd\betadβ accumulate across rows, so each program adds its row contribution into the length-NNN output buffers with an atomic add after the launcher pre-zeros them. This mirrors the structure of the official Triton tutorial for fused LayerNorm.

Loading visualization...

Examples

Input: x = [[1.0, 2.0, 3.0, 4.0]], gamma = [1, 1, 1, 1], dy = [[1, 0, 0, 0]], eps = 1e-5

Output: dx = [[0.6708, 0.2236, -0.2236, -0.6708]], dgamma = [-1.3416, -0.4472, 0.4472, 1.3416], dbeta = [1, 0, 0, 0]

Input: x = [[1, 2], [3, 4]], gamma = [1, 1], dy = [[1, 1], [1, 1]], eps = 1e-5

Output: dx = [[0, 0], [0, 0]], dgamma = [-2, 2], dbeta = [2, 2]

Hint 1

Recompute the row statistics inside the kernel; do not pass forward-pass scratch. The two row-level reductions you need are c1=1N∑kdynorm[i,k]c_1 = \tfrac{1}{N}\sum_k dy_{\text{norm}}[i,k]c1​=N1​∑k​dynorm​[i,k] and c2=1N∑kdynorm[i,k]⋅x^[i,k]c_2 = \tfrac{1}{N}\sum_k dy_{\text{norm}}[i,k] \cdot \hat{x}[i,k]c2​=N1​∑k​dynorm​[i,k]⋅x^[i,k].

Hint 2

With c1c_1c1​ and c2c_2c2​ in hand the formula collapses to dx[i,j]=rstd⋅(dynorm[i,j]−c1−x^[i,j]⋅c2)dx[i,j] = \text{rstd} \cdot (dy_{\text{norm}}[i,j] - c_1 - \hat{x}[i,j] \cdot c_2)dx[i,j]=rstd⋅(dynorm​[i,j]−c1​−x^[i,j]⋅c2​). Apply once across the row in registers.

Hint 3

dγd\gammadγ and dβd\betadβ are reductions across rows. Each program contributes its row via \texttt{tl.atomic_add} on the length-NNN buffers with the column-tail mask.

Requirements

  • Use one Triton program per row; recompute the row mean, variance, and inverse standard deviation inside the kernel
  • Accumulate dγd\gammadγ and dβd\betadβ across rows with atomic adds on the length-NNN buffers
  • Pre-zero dγd\gammadγ and dβd\betadβ on the host before launch; dxdxdx does not need zeroing
  • Mask the column tail on every load and store
  • The solve\texttt{solve}solve signature must not change

Constraints

  • 1≤M≤2561 \le M \le 2561≤M≤256, 1≤N≤10241 \le N \le 10241≤N≤1024.
  • All tensors are torch.float32 on cuda. eps is a Python float in [10−6,10−1][10^{-6}, 10^{-1}][10−6,10−1].
  • Use BLOCK_SIZE as a tl.constexpr chosen as triton.next_power_of_2(N) in the launcher.
  • Comparisons use atol = 1e-2 with rtol = 1e-2 because both the row reduction and the cross-row atomic reduction accumulate float32 error.
Try Similar Problems
LayerNorm Forward in TritonMediumRMSNorm Forward in TritonMediumDropout (Inverted Scaling) in TritonEasyCross Entropy Loss (Mean Reduction) in TritonMediumRMS Normalization as a CUDA KernelMediumLayer Normalization as a CUDA KernelMediumSplit-K Matmul in TritonHardDropout as a CUDA KernelEasyGrouped Program-ID Matmul in TritonHardFlashAttention Forward Kernel in TritonHardRow-Wise LogSumExp in TritonMediumScaled Dot-Product Attention in TritonMedium

Accepts: array

Accepts: array

Accepts: array

Accepts: number

You must run your code first.

Kernel performance

Submit a correct solution to see your kernel performance.

LayerNorm Backward in Triton

LayerNorm Backward in Triton

Neural NetworksGPU Programming
Hard

Implement the LayerNorm backward pass in Triton. Given the forward input x∈RM×Nx \in \mathbb{R}^{M \times N}x∈RM×N, the scale vector γ∈RN\gamma \in \mathbb{R}^{N}γ∈RN, and the upstream gradient dy∈RM×Ndy \in \mathbb{R}^{M \times N}dy∈RM×N, compute dxdxdx, dγd\gammadγ, and dβd\betadβ:

x^[i,j]=x[i,j]−μiσi2+ϵ,dynorm[i,j]=dy[i,j]⋅γ[j]\hat{x}[i, j] = \frac{x[i, j] - \mu_i}{\sqrt{\sigma_i^2 + \epsilon}}, \qquad dy_{\text{norm}}[i, j] = dy[i, j] \cdot \gamma[j]x^[i,j]=σi2​+ϵ​x[i,j]−μi​​,dynorm​[i,j]=dy[i,j]⋅γ[j] dx[i,j]=1σi2+ϵ⋅(dynorm[i,j]−1N∑kdynorm[i,k]−x^[i,j]⋅1N∑kdynorm[i,k]⋅x^[i,k])dx[i, j] = \frac{1}{\sqrt{\sigma_i^2 + \epsilon}} \cdot \left( dy_{\text{norm}}[i, j] - \frac{1}{N} \sum_k dy_{\text{norm}}[i, k] - \hat{x}[i, j] \cdot \frac{1}{N} \sum_k dy_{\text{norm}}[i, k] \cdot \hat{x}[i, k] \right)dx[i,j]=σi2​+ϵ​1​⋅(dynorm​[i,j]−N1​k∑​dynorm​[i,k]−x^[i,j]⋅N1​k∑​dynorm​[i,k]⋅x^[i,k]) dγ[j]=∑idy[i,j]⋅x^[i,j],dβ[j]=∑idy[i,j]d\gamma[j] = \sum_i dy[i, j] \cdot \hat{x}[i, j], \qquad d\beta[j] = \sum_i dy[i, j]dγ[j]=i∑​dy[i,j]⋅x^[i,j],dβ[j]=i∑​dy[i,j]

One program per row handles the dxdxdx computation. The reductions for dγd\gammadγ and dβd\betadβ accumulate across rows, so each program adds its row contribution into the length-NNN output buffers with an atomic add after the launcher pre-zeros them. This mirrors the structure of the official Triton tutorial for fused LayerNorm.

Loading visualization...

Examples

Input: x = [[1.0, 2.0, 3.0, 4.0]], gamma = [1, 1, 1, 1], dy = [[1, 0, 0, 0]], eps = 1e-5

Output: dx = [[0.6708, 0.2236, -0.2236, -0.6708]], dgamma = [-1.3416, -0.4472, 0.4472, 1.3416], dbeta = [1, 0, 0, 0]

Input: x = [[1, 2], [3, 4]], gamma = [1, 1], dy = [[1, 1], [1, 1]], eps = 1e-5

Output: dx = [[0, 0], [0, 0]], dgamma = [-2, 2], dbeta = [2, 2]

Hint 1

Recompute the row statistics inside the kernel; do not pass forward-pass scratch. The two row-level reductions you need are c1=1N∑kdynorm[i,k]c_1 = \tfrac{1}{N}\sum_k dy_{\text{norm}}[i,k]c1​=N1​∑k​dynorm​[i,k] and c2=1N∑kdynorm[i,k]⋅x^[i,k]c_2 = \tfrac{1}{N}\sum_k dy_{\text{norm}}[i,k] \cdot \hat{x}[i,k]c2​=N1​∑k​dynorm​[i,k]⋅x^[i,k].

Hint 2

With c1c_1c1​ and c2c_2c2​ in hand the formula collapses to dx[i,j]=rstd⋅(dynorm[i,j]−c1−x^[i,j]⋅c2)dx[i,j] = \text{rstd} \cdot (dy_{\text{norm}}[i,j] - c_1 - \hat{x}[i,j] \cdot c_2)dx[i,j]=rstd⋅(dynorm​[i,j]−c1​−x^[i,j]⋅c2​). Apply once across the row in registers.

Hint 3

dγd\gammadγ and dβd\betadβ are reductions across rows. Each program contributes its row via \texttt{tl.atomic_add} on the length-NNN buffers with the column-tail mask.

Requirements

  • Use one Triton program per row; recompute the row mean, variance, and inverse standard deviation inside the kernel
  • Accumulate dγd\gammadγ and dβd\betadβ across rows with atomic adds on the length-NNN buffers
  • Pre-zero dγd\gammadγ and dβd\betadβ on the host before launch; dxdxdx does not need zeroing
  • Mask the column tail on every load and store
  • The solve\texttt{solve}solve signature must not change

Constraints

  • 1≤M≤2561 \le M \le 2561≤M≤256, 1≤N≤10241 \le N \le 10241≤N≤1024.
  • All tensors are torch.float32 on cuda. eps is a Python float in [10−6,10−1][10^{-6}, 10^{-1}][10−6,10−1].
  • Use BLOCK_SIZE as a tl.constexpr chosen as triton.next_power_of_2(N) in the launcher.
  • Comparisons use atol = 1e-2 with rtol = 1e-2 because both the row reduction and the cross-row atomic reduction accumulate float32 error.
Try Similar Problems
LayerNorm Forward in TritonMediumRMSNorm Forward in TritonMediumDropout (Inverted Scaling) in TritonEasyCross Entropy Loss (Mean Reduction) in TritonMediumRMS Normalization as a CUDA KernelMediumLayer Normalization as a CUDA KernelMediumSplit-K Matmul in TritonHardDropout as a CUDA KernelEasyGrouped Program-ID Matmul in TritonHardFlashAttention Forward Kernel in TritonHardRow-Wise LogSumExp in TritonMediumScaled Dot-Product Attention in TritonMedium

Accepts: array

Accepts: array

Accepts: array

Accepts: number

You must run your code first.

Kernel performance

Submit a correct solution to see your kernel performance.

Problems
Loading...
1 / 1