nx_sampler.nx
buildroot/runtime/nx_sampler.nx
about
nx_sampler.nx -- DPM++ 2M scheduler (substrate-native, no CUDA).
Ships VRAM-track B-001 per docs/VRAM_OPTIMIZATION_REALISTIC_TRACKING.md:
DPM++ 2M Karras at 8 steps replaces Euler at 12 steps in the
Z-Image inference loop. Same or slightly better quality at ~30-40%
lower latency. Working memory savings come from fewer kept-around
step buffers; VRAM-bytes-per-step is unchanged but step-count drops.
Per the sovereign-from-bits-up cardinal: pure NishiLang, no
PyTorch / diffusers / sdcpp dependency. Composes against
nx_tensor envelopes and the caller's i64+Q10 model evaluation.
===== Math reference =============================================
DPM-Solver++ second-order multi-step (Lu et al. 2022,
arXiv:2211.01095, "DPM-Solver++: Fast Solver for Guided Sampling
of Diffusion Probabilistic Models").
In σ-only parameterisation (α_t = 1 schedule, "model_x" prediction):
λ_t = -log(σ_t)
h_i = λ_{i+1} - λ_i = log(σ_i / σ_{i+1})
r_i = h_{i-1} / h_i
D_i = model_x(x_i, σ_i) -- caller-supplied
D'_i = (1 + 1/(2r_i)) D_i - (1/(2r_i)) D_{i-1}
x_{i+1} = (σ_{i+1}/σ_i) x_i + (1 - σ_{i+1}/σ_i) D'_i (2nd order)
First step has no D_{i-1}, so D'_0 := D_0:
x_1 = (σ_1/σ_0) x_0 + (1 - σ_1/σ_0) D_0 (Euler)
===== Log-uniform σ spacing collapses r_i to 1 ==================
If σ_i is geometric (σ_{i+1} = k σ_i for a constant ratio k < 1)
then log(σ_i/σ_{i+1}) = -log k is constant, so all h_i are equal
and r_i = 1 for every step. The 2nd-order update simplifies:
D'_i = (1 + 1/2) D_i - (1/2) D_{i-1} = 1.5 D_i - 0.5 D_{i-1}
And σ_{i+1}/σ_i = k everywhere, so the linear-interp coefficient
dependencies 4 imports · 1 importers
imports: nx_syscalls.nxnx_tier.nxnx_tensor.nxnx_root.nx
imported by: nx_diffusion_loop.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 85 | const NX_SMP_Q10_ONE: nx_int = 1024 |
| 86 | const NX_SMP_Q14_ONE: nx_int = 16384 |
| 90 | const NX_SMP_OK: nx_int = 0 |
| 91 | const NX_SMP_ERR_BAD_NX: nx_int = 1 // n_lanes <= 0 |
| 92 | const NX_SMP_ERR_BAD_RATIO: nx_int = 2 // ratio not in (0, Q10_ONE) |
| 93 | const NX_SMP_ERR_BAD_N_STEPS: nx_int = 3 |
| 94 | const NX_SMP_ERR_NULL_BUF: nx_int = 4 |
| 95 | const NX_SMP_N_VERDICTS: nx_int = 5 |
| 128 | const NX_SMP_PRESET8_SIGMA0_Q14: nx_int = 239206 |
| 129 | const NX_SMP_PRESET8_RATIO_Q10: nx_int = 428 // ≈ 0.418 in Q10 |
| 130 | const NX_SMP_PRESET8_N_STEPS: nx_int = 8 |
| 188 | const NX_SMP_KARRAS_RHO: i64 = 7 |
| 189 | const NX_SMP_Q14_ONE: i64 = 16384 |
functions
| 97 | func nx_smp_verdict_is_valid(v: nx_int) -> nx_int |
| 134 | func _q10_lerp(a: i64, b: i64, t_q10: i64) -> i64 |
| 146 | func nx_sampler_fill_schedule_log_uniform( |
| 191 | func nx_sampler_fill_schedule_karras( |
| 222 | func nx_sampler_step_euler( |
| 251 | func nx_sampler_step_2nd( |
| 289 | func _q10_mul(a: i64, b: i64) -> i64 { return (a * b) / NX_SMP_Q10_ONE } called by 1: main |
| 291 | func main() -> i64 |