code wiki / (root) / nx_gelu.nx

nx_gelu.nx

buildroot/runtime/nx_gelu.nx

6726 B201 linesdepth 5pulls 7 transitivereach 0 importersview sourcekind tool
docsdependenciesstructsconstsfunctions

about

nx_gelu.nx -- Gaussian Error Linear Unit activation. The activation used by every non-Llama transformer family: GPT-2 / GPT-3 / GPT-Neo / GPT-J BERT / RoBERTa / DistilBERT / ALBERT T5 / mT5 / ByT5 ViT / DeiT / Swin / CLIP / SigLIP PaLM, Gemma (uses GeGLU variant = GELU * linear gate) Llama / Mistral / Qwen use SiLU instead (closely related; nx_silu.nx already ships). Substrate now ships both -- model loader picks per-config. ===== Math ======================================================= Exact GELU (Hendrycks & Gimpel 2016 eq. 1): GELU(x) = x * Phi(x) = x * 0.5 * (1 + erf(x / sqrt(2))) Exact requires erf, which we don't ship. Two practical approximations: 1. Tanh form (most common): GELU(x) ~= 0.5 * x * (1 + tanh(sqrt(2/pi) * (x + 0.044715*x^3))) 2. Sigmoid form (Hendrycks 2016 alt): GELU(x) ~= x * sigmoid(1.702 * x) We use form #2 because nx_sigmoid_q10 already ships in nx_silu.nx and it's a one-multiply + sigmoid composition. Max relative error vs exact GELU is ~0.5% across [-5, 5] -- well within substrate quantization budget. Tanh-form upgrade queued -- needs nx_tanh.nx primitive. For q4_K-quant transformer inference the sigmoid form is more than sufficient. Q-format: x in Q10, output in Q10. Constant 1.702 in Q10 = 1743.

dependencies 5 imports · 0 importers

nx_syscalls.nx nx_tier.nx nx_loop.nx nx_tensor.nx nx_silu.nx nx_gelu.nx

imports: nx_syscalls.nxnx_tier.nxnx_loop.nxnx_tensor.nxnx_silu.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main nx_gelu_q10 nx_sigmoid_q10 nx_exp_q10_neg _nx_exp_table_get sys_mmap nx_t_alloc nx_dt_is_valid nx_dt_element_bytes sys_mmap ↻ nx_t_compute_strides_rowma nx_gelu_forward nx_t_is_contiguous nx_gelu_q10 ↻ nx_gelu_verdict_is_valid

structs

none

consts

61const NX_MAGIC_1024: i64 = 1024
62const NX_MAGIC_10240: i64 = 10240
63const NX_MAGIC_2048: i64 = 2048
65const NX_GELU_Q10: nx_int = 1024
66const NX_GELU_K_1_702_Q10: nx_int = 1743 // 1.702 in Q10 = 1.702 * 1024 = 1742.85
70const NX_GELU_OK: nx_int = 0
71const NX_GELU_ERR_BAD_DTYPE: nx_int = 1
72const NX_GELU_ERR_SHAPE_MISMATCH: nx_int = 2
73const NX_GELU_ERR_NOT_CONTIGUOUS: nx_int = 3
74const NX_GELU_N_VERDICTS: nx_int = 4

functions

76func nx_gelu_verdict_is_valid(v: nx_int) -> nx_int
called by 1: main
89func nx_gelu_q10(x_q10: nx_int) -> nx_int
called by 2: nx_gelu_forwardmain calls 1: nx_sigmoid_q10
99func nx_gelu_forward(x: *NxTensor, out: *NxTensor) -> nx_int
called by 1: main calls 2: nx_t_is_contiguousnx_gelu_q10
147func main() -> i64