Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
36bb704
fix(rmsnorm): use custom eps in quantized forward kernels
cschenjunlin Jul 27, 2026
bc5d374
perf(rmsnorm): extend vec8 coverage in forward kernels
cschenjunlin Jul 27, 2026
d6bb83f
fix(layernorm): use custom eps in forward kernels
cschenjunlin Jul 27, 2026
0f2d86c
perf(layernorm): extend vec8 coverage in forward kernels
cschenjunlin Jul 27, 2026
38ba12f
test(rmsnorm): diagnose gfx1201 SmoothQuant scale paths
cschenjunlin Jul 29, 2026
2ab9c00
test(rmsnorm): re-enable SmoothQuant on gfx1201
cschenjunlin Jul 29, 2026
d07bf28
test(rmsnorm): cover exact gfx1201 SmoothQuant regression
cschenjunlin Jul 31, 2026
6b7a130
test(rmsnorm): quarantine SmoothQuant on gfx1201
cschenjunlin Jul 31, 2026
85471e6
docs(norm): clarify SmoothQuant scale contract
cschenjunlin Jul 31, 2026
b47a4d0
restore pre-diagnostic SmoothQuant baseline
cschenjunlin Aug 4, 2026
2aefe4a
Merge remote-tracking branch 'origin/main' into cjl/norm_perf
cschenjunlin Aug 12, 2026
39d3897
perf(rmsnorm): vectorize unaligned large-N rows
cschenjunlin Aug 18, 2026
6487994
[Fix] Barrier the LDS scratch reuse between successive block reductions
cschenjunlin Aug 19, 2026
d42e571
refactor: separate base and forward shape configurations
cschenjunlin Aug 20, 2026
b256468
Merge remote-tracking branch 'origin/main' into cjl/norm_perf
cschenjunlin Aug 20, 2026
72aaa42
test: remove gfx1201 quant norm quarantine
cschenjunlin Aug 20, 2026
c5c8afd
perf(rmsnorm): restore runtime M dispatch for small N
cschenjunlin Aug 25, 2026
bbdde41
perf(rmsnorm): optimize wide BF16 rows on gfx942
cschenjunlin Aug 25, 2026
b98ff76
Remove RMSNorm benchmark script from tracking
cschenjunlin Sep 1, 2026
cae767d
restore the RNA semantic to RNE
cschenjunlin Sep 3, 2026
7f2b9aa
Merge remote-tracking branch 'origin/main' into cjl/norm_perf
cschenjunlin Sep 8, 2026
21c0eae
perf(rmsnorm): dispatch gfx95x BF16 NT cache policy on row count
cschenjunlin Sep 11, 2026
cf1151b
perf(rmsnorm): extend vec8 coverage to fused-add and quant variants
cschenjunlin Sep 17, 2026
0ad9aff
fix(norm): assert the implicit quantized-norm dtype ABI
cschenjunlin Sep 17, 2026
9f2357f
refactor(norm): load and store single elements by direct indexing
cschenjunlin Sep 18, 2026
fc799d9
fix(norm): anchor the quantized-norm dtype guard to the builder dtype…
cschenjunlin Sep 21, 2026
8c63e3b
docs(norm): resync the LayerNorm and RMSNorm guide sections with the …
cschenjunlin Sep 24, 2026
175cf1c
Merge branch 'main' into cjl/norm_perf
jhinpan Sep 24, 2026
da396b8
fix(norm): guard IR assertions against cache-loaded artifacts
cschenjunlin Sep 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 44 additions & 23 deletions docs/prebuilt_kernels_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,28 @@ executor = build_layernorm_module(N=8192, dtype_str="bf16")
| Constant | Value | Description |
|---|---|---|
| `BLOCK_THREADS` | 256 | Threads per block |
| `WARP_SIZE` | 64 | AMD wavefront size |
| `WARP_SIZE` | 64 on CDNA, 32 on RDNA | Wavefront size, resolved from the target arch |
| `VEC_WIDTH` | 8 | Vector load/store width |
| `VEC_ALIGN` | 16 | Alignment for vector ops (bytes) |
| `EPS` | 1e-5 | Numerical stability epsilon |
| `USE_NONTEMPORAL` | True | Non-temporal stores for output |

**Algorithm:**
- **Two-pass normalization**: Pass 1 computes mean and variance, Pass 2 applies affine transform
- **Fast path**: When `N == BLOCK_THREADS * VEC_WIDTH * 4` (for example, N=8192), uses fully register-resident computation with no scalar tail
- **Generic path**: Handles arbitrary N with vector body + scalar tail
- **Vectorized path**: When the element type is 16-bit and `N % VEC_WIDTH == 0`, the row is covered by `N / VEC_WIDTH` vector tiles with no scalar tail
- **Scalar path**: FP32, or any `N` not divisible by `VEC_WIDTH`, falls back to a fully scalar two-pass implementation
- **bf16 handling**: Software round-to-nearest-even (RNE) pack on gfx942; hardware `cvt_pk_bf16_f32` on gfx950+
- **Warp reduction**: XOR-shuffle-based intra-wave reduction (shifts: 32, 16, 8, 4, 2, 1), then LDS-based cross-wave synchronization

**Kernel signature** (using `@flyc.kernel` API):
```
GPU_MODULE_NAME = "layernorm_module"

@kernel
layernorm_kernel(self, Input, Gamma, Beta, Output, m_in)
**Kernel signature:**
```python
@flyc.kernel
layernorm_kernel(Input, Gamma, Beta, Output, Mean, Rstd)

@jit
__call__(self, Input, Gamma, Beta, Output, m_in)
@flyc.jit
launch_layernorm(Input, Gamma, Beta, Output, m_in, stream=...)
# store_stats=True inserts Mean and Rstd before m_in
```
The builder returns the `launch_layernorm` closure. The row count `m_in` is a
runtime launch argument, not a kernel parameter.

### 1.2 RMSNorm (`kernels/norm/rmsnorm_kernel.py`)

Expand All @@ -70,11 +69,19 @@ executor = build_rmsnorm_module(N=8192, dtype_str="bf16", store_rstd=False)
```

`build_rmsnorm_module(N, dtype_str, store_rstd=False, eps=EPS,
BLOCK_THREADS=BLOCK_THREADS, weight_dtype_str=None)` optionally writes the
BLOCK_THREADS=None, weight_dtype_str=None)` optionally writes the
per-row reciprocal std (`rstd`) for use by the backward pass.
`weight_dtype_str` defaults to `dtype_str`; FP16/BF16 activations additionally
support FP32 weights.

**Quantized variants:** The DynamicQuant and SmoothQuant builders emit int8
`Output` and fp32 per-row `YScale`. `Input` must use the element dtype named by
the builder's `dtype_str`, and every other operand — `Gamma`, the fused-add
`ResidualIn`/`ResidualOut`, and SmoothQuant `XScale` — must match it. The
launchers raise `ValueError` on a mismatch, so a wrong dtype fails at compile
time rather than silently producing corrupted scales. Unlike the plain forward,
the quantized builders do not accept FP32 weights with FP16/BF16 activations.

**Backward:** `build_rmsnorm_bwd_module(N, dtype_str,
weight_dtype_str=None)` builds the fused RMSNorm backward kernel (grid `(M,)`,
one block per row). Kernel signature
Expand All @@ -84,19 +91,33 @@ grad). The forward bakes `eps` into `Rstd`, so the backward does not need it.
The public plain and fused-add training wrappers return `dweight` in the
original weight dtype.

**Configuration constants:** Same as LayerNorm (BLOCK_THREADS=256, VEC_WIDTH=8, etc.)
**Configuration constants:**
| Constant | Value | Description |
|---|---|---|
| `BLOCK_THREADS` | 256; 512 on gfx95x when `N >= 8192` | Resolved by `default_block_threads(N, arch)` when the builder argument is left at `None` |
| `WARP_SIZE` | 64 on CDNA, 32 on RDNA | Wavefront size, resolved from the target arch |
| `VEC_WIDTH` | 8 | Vector load/store width |
| `EPS` | 1e-5 | Numerical stability epsilon |

**Algorithm (2-pass, row cached in registers):**
1. **Pass 1**: One vectorized global read per row; the input stays in registers
and the sum of squares is accumulated in the same pass. A scalar tail covers
the `N % VEC_WIDTH` leftover elements.
2. **Pass 2**: Normalize, multiply by gamma, and store, reusing the registers
from pass 1. `Gamma` is preloaded during pass 1 on the gfx942 BF16 fast path.

**Algorithm (3-pass with LDS caching):**
1. **Pass 0**: Global → LDS row cache (one-pass global read, vectorized)
2. **Pass 1**: Sum-of-squares computation from LDS row cache
3. **Pass 2**: Normalize + gamma multiply + store with software pipeline for Gamma prefetch
LDS holds only the cross-wave reduction slots, sized by the wave count rather
than by `N`; the row itself never passes through shared memory. The quantized
builders add a third pass that applies the per-row scale.

**Kernel signature:**
```
GPU_MODULE_NAME = "rmsnorm_module"
```python
@flyc.kernel
rmsnorm_kernel(Input, Gamma, Rstd, Output)

@kernel
rmsnorm_kernel(self, Input, Gamma, Output, m_in)
@flyc.jit
launch_rmsnorm(Input, Gamma, Output, m_in, stream=...)
# store_rstd=True inserts Rstd between Output and m_in
```

---
Expand Down
Loading
Loading