nx_f32_adaln.nx
buildroot/runtime/nx_f32_adaln.nx
about
nx_f32_adaln.nx -- software-f32 adaptive LayerNorm (adaLN / adaLN-Zero) modulation, the DiT-specific brick.
sd-server -> Nishi migration: this is what turns a plain transformer block into a DIFFUSION transformer
(DiT) block (Peebles & Xie 2023 "Scalable Diffusion Models with Transformers"; Z-Image uses it). A small
MLP maps the conditioning vector (timestep + pooled text) to per-block modulation params
{shift, scale, gate} for each sublayer; the block then applies:
modulate(norm(x), shift, scale) = norm(x) * (1 + scale) + shift (broadcast over tokens)
x = x + gate * sublayer(modulate(...)) (gated residual; adaLN-Zero starts gate=0)
This file owns the two elementwise ops (modulate + gated-residual). The conditioning MLP that produces
shift/scale/gate is a plain linear (nx_f32_matmul) the caller supplies. Composes nx_f32_add/mul + cvt.
x, out, res, h: flat *i64 f32 bits [n_tokens, D]. scale, shift, gate: [D] f32 (per-feature, token-broadcast).
license_tier: ORIGINAL
dependencies 3 imports · 1 importers
imports: nx_syscalls.nxnx_f32.nxnx_f32_cvt.nx
imported by: nx_f32_dit_block_tiny.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 19 | const NX_F32ADALN_OK: i64 = 0 |
| 20 | const NX_F32ADALN_ERR: i64 = 1 |
functions
| 23 | func nx_f32_adaln_modulate(x: *i64, n_tokens: i64, D: i64, scale: *i64, shift: *i64, out: *i64) -> i64 |
| 42 | func nx_f32_adaln_gate(res: *i64, h: *i64, n_tokens: i64, D: i64, gate: *i64, out: *i64) -> i64 |
| 62 | func main() -> i64 |