code wiki / (root) / nx_bench_stress_autoreg_test.nx

nx_bench_stress_autoreg_test.nx source

↩ module page · 145 lines · 6004 B

1// nx_bench_stress_autoreg_test.nx -- 10-iteration REAL transformer 2// stress test with wall-clock measurement. 3// 4// Where nx_actor_role_llm_v2_real_autoreg_test does 3 iterations 5// for correctness, this smoke does 10 to exercise the substrate 6// under load + capture honest wall-clock numbers. 7// 8// Each iteration drives the v2 LLM actor through INIT -> RUN (full 9// Llama-class transformer forward via nx_llm_generate_one_v2) -> 10// EMIT. Real embedding lookup + RMSNorm + multi-head attention + 11// SwiGLU FFN + output projection + sample. Listener mailbox 12// receives 10 LLM_TOKEN messages. 13// 14// Substrate invariants verified under load: 15// * All 10 iterations succeed (every runner_result >= 0) 16// * All 10 tokens are in [0, vocab) 17// * Listener mailbox correctly handles 10 messages 18// * Scheduler counters scale linearly (30 actor steps, 30000us 19// cumulative runtime) 20// * Wall-clock elapsed > 0 (substrate actually ran wall-time work) 21// 22// HONEST SCOPE: wall-clock under qemu-riscv64 isn't physical-hardware 23// time. When Phase E + a physical-board arc land, this same smoke 24// will produce defensible numbers without code changes. 25 26import "nx_syscalls.nx" 27import "nx_tier.nx" 28import "nx_clock.nx" 29import "nx_actor.nx" 30import "nx_message.nx" 31import "nx_session.nx" 32import "nx_bench_companion.nx" 33import "nx_bench_companion_timed.nx" 34import "nx_gguf_fixture_tiny.nx" 35import "nx_actor_role_llm_v2.nx" 36 37func main() -> i64 { 38 let now: nx_size = 1000000 39 let N_ITERS: nx_int = 10 40 41 // ===== Fixture + session ===== 42 let fix: *NxGgufFixtureBundle = nx_gft_build_tiny_llama(0xfeed) 43 if nx_gft_is_built(fix) != 1 { return 1 } 44 let s: *NxSession = nx_session_new_default(now) 45 if nx_session_is_ready(s) != 1 { return 2 } 46 let LLM: nx_int = 8001 47 let LIS: nx_int = 8099 48 nx_session_spawn_actor(s, LLM, 1, 80, 0, now) 49 nx_session_spawn_actor(s, LIS, 5, 50, 0, now) 50 nx_session_subscribe(s, LIS, NX_MS_KIND_LLM_TOKEN) 51 52 let prompt: *u8 = sys_mmap(1) 53 prompt[0] = 0x61 // 'a' 54 let ctx: *NxLlmV2ActorCtx = nx_lv_actor_new( 55 fix.spec, fix.gguf_buf, fix.hdr, fix.bpe, 56 prompt, 1, 57 1024, 4, fix.prng_state, 10000, 724) 58 if (ctx as i64) == 0 { return 3 } 59 60 // ===== Pre-capture for paired-delta ===== 61 let r_before: *NxBenchReport = nx_bc_report_new() 62 nx_bc_capture(s, r_before, 11, now) 63 64 // ===== Start wall-clock timer ===== 65 let base: *NxBenchReport = nx_bc_report_new() 66 let timed: *NxBenchTimedReport = nx_bctm_new(base) 67 timed.wallclock_start_ns = nx_clock_monotonic_ns() 68 69 // ===== Drive 10 autoregressive iterations ===== 70 let history: *u8 = sys_mmap(N_ITERS * 8) 71 let hist: *i64 = history as *i64 72 var iter: nx_int = 0 73 var tick: nx_size = now + 100 74 while iter < N_ITERS { 75 if nx_lv_actor_step(ctx, s.scheduler, s.bus, LLM, tick) != NX_LV_V_STEPPED { return 10 + iter } 76 tick = tick + 50 77 let v_run: nx_int = nx_lv_actor_step(ctx, s.scheduler, s.bus, LLM, tick) 78 if ctx.runner_result < 0 { return 20 + iter } 79 if ctx.runner_result >= fix.vocab_size { return 30 + iter } 80 if ctx.runner_verdict != NX_LR2_OK { return 40 + iter } 81 if v_run != NX_LV_V_STEPPED { return 50 + iter } 82 tick = tick + 50 83 let v_emit: nx_int = nx_lv_actor_step(ctx, s.scheduler, s.bus, LLM, tick) 84 if v_emit != NX_LV_V_COMPLETED { return 60 + iter } 85 if ctx.current_phase != NX_LV_PHASE_DONE { return 70 + iter } 86 let tok: nx_int = ctx.runner_result 87 hist[iter] = tok as i64 88 tick = tick + 50 89 90 if iter < (N_ITERS - 1) { 91 let new_byte: nx_int = nx_gft_vocab_byte(fix, tok) 92 if new_byte < 0 { return 80 + iter } 93 prompt[0] = new_byte as u8 94 if nx_lv_actor_reset_for_next_token(ctx, s.scheduler, LLM, prompt, 1) != NX_LV_V_STEPPED { return 90 + iter } 95 } 96 iter = iter + 1 97 } 98 99 // ===== Stop wall-clock timer + capture substrate counters ===== 100 if nx_bctm_capture_finish(timed, s, 11) != NX_BCTM_OK { return 100 } 101 102 // ===== Substrate invariants under load ===== 103 // 104 // Per iteration: 3 actor steps (INIT, RUN, EMIT). 10 iterations 105 // = 30 cooperative steps for the LLM actor. 106 if base.total_actor_steps != 30 { return 101 } 107 // Each step accumulates 1000us substrate runtime. 108 if base.cumulative_runtime_us != 30000 { return 102 } 109 // LLM actor reached COMPLETED on the FINAL iteration (no reset). 110 if base.actors_completed != 1 { return 103 } 111 if base.actors_failed != 0 { return 104 } 112 // Listener (still READY) + LLM (COMPLETED) = 2 actors 113 if base.n_actors != 2 { return 105 } 114 115 // ===== Wall-clock invariants ===== 116 if timed.wallclock_elapsed_us < 0 { return 106 } 117 if timed.wallclock_end_ns < timed.wallclock_start_ns { return 107 } 118 if nx_bctm_verdict(timed) != NX_BCTM_OK { return 108 } 119 120 // ===== Listener received exactly N_ITERS LLM_TOKEN messages ===== 121 if nx_ms_pending(s.bus, LIS) != N_ITERS { return 109 } 122 123 // ===== Drain + verify each token matches history ===== 124 var drained: nx_int = 0 125 while drained < N_ITERS { 126 let m: *NxMessage = nx_ms_receive(s.bus, LIS) 127 if (m as i64) == 0 { return 200 + drained } 128 if m.kind != NX_MS_KIND_LLM_TOKEN { return 210 + drained } 129 if m.sender_actor_id != LLM { return 220 + drained } 130 let recv_tok: nx_int = m.payload_handle as nx_int 131 if recv_tok != (hist[drained] as nx_int) { return 230 + drained } 132 if recv_tok < 0 { return 240 + drained } 133 if recv_tok >= fix.vocab_size { return 250 + drained } 134 drained = drained + 1 135 } 136 137 // ===== Paired delta with pre-capture ===== 138 let delta: *NxBenchReport = nx_bc_report_new() 139 nx_bc_diff(r_before, base, delta) 140 if delta.total_actor_steps != 30 { return 300 } 141 if delta.cumulative_runtime_us != 30000 { return 301 } 142 if delta.actors_completed != 1 { return 302 } 143 144 return 0 145}