liangsu9988's picture
Publish GROOT N1.7 Thor kernel sources
ad7437c verified
|
Raw History Blame
6.36 kB
# adaptive-layernorm-producers
FlashRT native CUDA producer kernels for DiT/Wan-style adaptive LayerNorm
blocks.
This package fuses the producer side of the block:
```text
LayerNorm / adaptive LayerNorm modulation -> low-precision activation
```
into a single Kernel Hub operator. It is intended for transformer and diffuser
runtimes where the following GEMM already consumes FP8 or NVFP4 activations.
Without this fusion, the runtime pays for separate normalization, modulation,
BF16 materialization, and quantization launches before the GEMM.
The source kernels are derived from the production FlashRT runtime:
- `official/FlashRT/csrc/quantize/ada_layer_norm_fp8.cu`
- `official/FlashRT/csrc/kernels/dit_bf16.cu::layer_norm_no_affine_fp8_static_bf16`
The full FlashRT model runtime and serving pipeline live upstream at
[LiangSu8899/FlashRT](https://github.com/LiangSu8899/FlashRT).
## Available Functions
- `ada_layer_norm_quant_fp8_bf16(x, scale, shift, act_scale, eps=1e-5, out=None)`
- `ada_layer_norm_quant_fp8_ptok_bf16(x, scale, shift, act_scale, eps=1e-5, out=None)`
- `ada_layer_norm_quant_fp8_ptok_table_bf16(x, temb, table, act_scale, shift_idx, scale_idx, eps=1e-5, out=None)`
- `ada_layer_norm_quant_fp8_modfp8_bf16(x, scale_fp8, shift_fp8, scale_deq, shift_deq, act_scale, eps=1e-5, out=None)`
- `awq_ada_layer_norm_quant_fp8_bf16(x, scale, shift, inv_s, act_scale, eps=1e-5, out=None)`
- `ada_layer_norm_quant_nvfp4_swizzled_bf16(x, scale, shift, eps=1e-5, packed=None, sf_swizzled=None)`
- `ada_layer_norm_quant_nvfp4_swizzled_modfp8_bf16(x, scale_fp8, shift_fp8, scale_deq, shift_deq, eps=1e-5, packed=None, sf_swizzled=None)`
- `layer_norm_no_affine_quant_fp8_static_bf16(x, act_scale, eps=1e-5, out=None)`
- `layer_norm_no_affine_quant_nvfp4_swizzled_bf16(x, eps=1e-5, packed=None, sf_swizzled=None)`
- `adaln_modulation6_bf16(adaln_params, layer_modulation, out=None)`
- `swizzled_sf_size(rows, dim)`
## Tensor Contract
- `x`: contiguous CUDA `torch.bfloat16`, shape `(rows, dim)`.
- Broadcast `scale`, `shift`, and `inv_s`: contiguous CUDA
`torch.bfloat16`, shape `(dim,)`.
- Per-token `scale` and `shift`: contiguous CUDA `torch.bfloat16`, shape
`(rows, dim)`.
- Table form `temb`: contiguous CUDA `torch.bfloat16`, shape
`(rows, chunks, dim)`; `table`: contiguous CUDA `torch.float32`, shape
`(chunks, dim)`.
- `scale_fp8`, `shift_fp8`: contiguous CUDA `torch.float8_e4m3fn`, shape `(dim,)`.
- `scale_deq`, `shift_deq`, `act_scale`: CUDA `torch.float32` scalar tensors.
- FP8 outputs use `torch.float8_e4m3fn`, shape `(rows, dim)`.
- NVFP4 packed output uses `torch.uint8`, shape `(rows, dim // 2)`.
- NVFP4 scale output uses the FlashRT/CUTLASS 128x4 swizzled uint8 scale
layout. Allocate with `swizzled_sf_size(rows, dim)`.
- `dim` must be even for FP8 outputs and divisible by 16 for NVFP4 outputs.
- The package targets CUDA 12.8+ and Blackwell-class deployment paths.
- `adaln_modulation6_bf16` takes FP32 `(batch, sequence, 6, dim)` parameters
plus FP32 `(6, dim)` layer modulation and returns six BF16
`(batch, sequence, dim)` tensors.
## Minimal Usage
```python
from kernels import get_kernel
import torch
ops = get_kernel("flashrt/adaptive-layernorm-producers", version=1, trust_remote_code=True)
rows, dim = 2520, 3072
x = torch.randn((rows, dim), device="cuda", dtype=torch.bfloat16)
scale = torch.zeros((dim,), device="cuda", dtype=torch.bfloat16)
shift = torch.zeros((dim,), device="cuda", dtype=torch.bfloat16)
act_scale = torch.tensor([0.025], device="cuda", dtype=torch.float32)
x_fp8 = ops.ada_layer_norm_quant_fp8_bf16(x, scale, shift, act_scale)
```
Per-token modulation without materializing a broadcast buffer:
```python
ptok_scale = torch.zeros_like(x)
ptok_shift = torch.zeros_like(x)
x_fp8 = ops.ada_layer_norm_quant_fp8_ptok_bf16(
x, ptok_scale, ptok_shift, act_scale
)
```
Fused host modulation table add and chunk selection:
```python
chunks = 6
temb = torch.zeros((rows, chunks, dim), device="cuda", dtype=torch.bfloat16)
table = torch.zeros((chunks, dim), device="cuda", dtype=torch.float32)
x_fp8 = ops.ada_layer_norm_quant_fp8_ptok_table_bf16(
x, temb, table, act_scale, shift_idx=0, scale_idx=1
)
```
Static-buffer usage for CUDA Graph capture:
```python
out = torch.empty_like(x, dtype=torch.float8_e4m3fn)
ops.ada_layer_norm_quant_fp8_bf16(x, scale, shift, act_scale, out=out)
```
NVFP4 producer:
```python
packed, sf = ops.ada_layer_norm_quant_nvfp4_swizzled_bf16(x, scale, shift)
# GROOT N1.7 pre-FFN producer on Thor.
packed_ln, sf_ln = ops.layer_norm_no_affine_quant_nvfp4_swizzled_bf16(x)
```
Six-way DiT modulation:
```python
params = torch.randn((1, rows, 6, dim), device="cuda", dtype=torch.float32)
modulation = torch.randn((6, dim), device="cuda", dtype=torch.float32)
outputs = ops.adaln_modulation6_bf16(params, modulation)
```
## Validation
```bash
python adaptive-layernorm-producers/tests/test_adaptive_layernorm_producers.py --backend source --mode full
python adaptive-layernorm-producers/benchmarks/benchmark.py --backend source --iters 100
```
The validation suite checks exact FP8 output for small producer shapes, exact
NVFP4 packed/scalefactor output against the native staged BF16-norm plus FP4
quantizer contract on SM110, and strict FP8
boundary accounting for long video shapes. The long-shape policy requires
`p99_abs == 0` and only a tiny count of adjacent FP8-code boundary differences
against the eager reference.
See `VALIDATION.md` and `benchmarks/RESULTS.md` for the current local RTX 5090
source-build results.
The SM110 FP4 producer uses the native GROOT N1.7 contract from FlashRT commit
`24df793f4fa2d50780aea03b644208c6e0cb4162`. Its scale conversion and FP4 bin
boundaries intentionally differ from the older SM120 producer; release tests
compare each architecture against its own production contract.
The aarch64 release variant `torch211-cxx11-cu130-aarch64-linux` contains
native SM87 and SM110a code objects. Its SM110a path was validated on NVIDIA
Thor from the exact Hub-downloaded artifact over decode, DiT, vision, and
2K/4K video rows. The two per-token entry points were also compared directly
with their raw registered ops using A-B-B-A timing; all six wrapper/raw rows
were bit-exact and the measured ratio was `0.997-1.000`. SM87 runtime
validation remains pending on Jetson AGX Orin hardware.