code wiki / _hdl_build / nx_embed_bench.nx
nx_embed_bench.nx
buildroot/runtime/_hdl_build/nx_embed_bench.nx
about
nx_embed_bench.nx -- IN-PROCESS m-SWEEP: is prefill actually BATCHING?
v1 measured cross-run and DISAGREED WITH ITSELF: 8tok=606ms/tok, 32tok=673, 125tok=403 (non-monotonic).
Two causes, both avoidable: it raced continuous sibling build load, and it re-loaded a 491MB model
every run (measured load variance alone 16554..20767ms, ~25%). nx_llm_forward_profile's own header
already warned this host is too noisy for cross-run attribution below 20% -- I hit a limitation the
ecosystem had already written down.
LAW: WHEN A MEASUREMENT DISAGREES WITH ITSELF ACROSS RUNS, FIX THE INSTRUMENT BEFORE INTERPRETING IT.
v2 loads the model ONCE and sweeps m INSIDE one process, so load variance and cross-run drift cancel
and only the m-dependence remains. Two reps per m are printed so the reader SEES the noise instead of
trusting one sample.
FLAT ms_per_token across m => prefill is NOT batching (wire the m>1 packed path in lazy_matmul)
FALLING ms_per_token => batching works; the cost lives elsewhere
Compare against the m=1 DECODE cost of 350ms/token from nx_llm_forward_profile.
license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 11 imports · 0 importers
diagram shows first 10 each side; +1 more imports, +0 more importers in the complete lists below.
imports: nx_syscalls.nxnx_itoa_lib.nxnx_tier.nxnx_bpe.nxnx_gguf.nxnx_gguf_load.nxnx_gguf_meta.nxnx_f32_llm_read_dims.nxnx_f32_bpe_load.nxnx_f32.nxnx_f32_llm_v4.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 29 | const EB_MAXTOK: i64 = 1024 |
| 30 | const EB_KV_SLOTS: i64 = 1024 |
| 31 | const EB_EPS: i64 = 0x358637BD |
| 32 | const EB_ATTN_SCALE: i64 = 0x3E000000 |
| 33 | const EB_ROPE_BASE: i64 = 0x415D0EAB |
| 34 | const EB_VOCAB_BYTES: i64 = 67108864 |
| 35 | const EB_VOCAB_IDS: i64 = 262144 |
| 36 | const EB_VOCAB_MERGES: i64 = 524288 |
| 37 | const EB_NPOINTS: i64 = 5 |
| 38 | const EB_REPS: i64 = 2 |
functions
| 40 | func eb_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 44 | func eb_n(v: i64) -> i64 { nxi_out(v); return 0 } |
| 45 | func eb_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } called by 1: main |
| 47 | func main(argc: i64, argv: *i64) -> i64 |