nx_dual_real_llm_emit_test.nx source
↩ module page · 141 lines · 5650 B
1// nx_dual_real_llm_emit_test.nx -- two concurrent v2 LLM actors driving
2// REAL transformer forward, with wall-clock measurement AND stdout TSV
3// emission so operators see the actual numbers the substrate produces.
4//
5// Same workload as nx_dual_real_llm_compose_test (5 iterations per actor,
6// 2 actors interleaved cooperatively). Adds:
7// * Wall-clock measurement around the workload
8// * stdout TSV header + data row labeled "dual_real_v2_5iter"
9// * stdout wallclock_elapsed_us line
10//
11// Substrate ships numbers; smoke driver shows PASS; operator reads the
12// stdout to see real measurement.
13
14import "nx_syscalls.nx"
15import "nx_tier.nx"
16import "nx_clock.nx"
17import "nx_actor.nx"
18import "nx_message.nx"
19import "nx_stream_multiplexer.nx"
20import "nx_session.nx"
21import "nx_bench_companion.nx"
22import "nx_bench_companion_timed.nx"
23import "nx_bench_companion_tsv.nx"
24import "nx_gguf_fixture_tiny.nx"
25import "nx_actor_role_llm_v2.nx"
26
27func _emit_dec_i64(fd: i64, n: i64) -> i64 {
28 let scratch: *u8 = sys_mmap(32)
29 var v: i64 = n
30 if v < 0 { v = 0 - v }
31 var k: i64 = 0
32 if v == 0 {
33 scratch[0] = 0x30 as u8
34 k = 1
35 }
36 while v > 0 {
37 scratch[k] = (0x30 + (v - (v / 10) * 10)) as u8
38 v = v / 10
39 k = k + 1
40 }
41 let rev: *u8 = sys_mmap(32)
42 var j: i64 = 0
43 while j < k { rev[j] = scratch[k - 1 - j]; j = j + 1 }
44 rev[k] = 0x0A as u8
45 sys_write(fd, rev, k + 1)
46 return 0
47}
48
49func main() -> i64 {
50 let now: nx_size = 1000000
51 let N_ITERS: nx_int = 5
52
53 // ===== Fixtures + session =====
54 let fixA: *NxGgufFixtureBundle = nx_gft_build_tiny_llama(0x11111111)
55 let fixB: *NxGgufFixtureBundle = nx_gft_build_tiny_llama(0x22222222)
56 let s: *NxSession = nx_session_new_default(now)
57 if nx_session_is_ready(s) != 1 { return 1 }
58 let NARR: nx_int = 8001
59 let NPC: nx_int = 8002
60 let LIS: nx_int = 8099
61 nx_session_spawn_actor(s, NARR, 1, 80, 0, now)
62 nx_session_spawn_actor(s, NPC, 1, 60, 0, now)
63 nx_session_spawn_actor(s, LIS, 5, 50, 0, now)
64 nx_session_subscribe(s, LIS, NX_MS_KIND_LLM_TOKEN)
65
66 let prompt_n: *u8 = sys_mmap(1); prompt_n[0] = 0x61
67 let prompt_p: *u8 = sys_mmap(1); prompt_p[0] = 0x63
68 let ctxN: *NxLlmV2ActorCtx = nx_lv_actor_new(
69 fixA.spec, fixA.gguf_buf, fixA.hdr, fixA.bpe, prompt_n, 1,
70 1024, 4, fixA.prng_state, 10000, 724)
71 let ctxP: *NxLlmV2ActorCtx = nx_lv_actor_new(
72 fixB.spec, fixB.gguf_buf, fixB.hdr, fixB.bpe, prompt_p, 1,
73 1024, 4, fixB.prng_state, 10000, 724)
74
75 // ===== Wall-clock start =====
76 let base: *NxBenchReport = nx_bc_report_new()
77 let timed: *NxBenchTimedReport = nx_bctm_new(base)
78 timed.wallclock_start_ns = nx_clock_monotonic_ns()
79
80 // ===== Cooperative interleaving across 5 iterations =====
81 var iter: nx_int = 0
82 var tick: nx_size = now + 100
83 while iter < N_ITERS {
84 nx_lv_actor_step(ctxN, s.scheduler, s.bus, NARR, tick); tick = tick + 50
85 nx_lv_actor_step(ctxN, s.scheduler, s.bus, NARR, tick); tick = tick + 50
86 nx_lv_actor_step(ctxN, s.scheduler, s.bus, NARR, tick); tick = tick + 50
87 let tokN: nx_int = ctxN.runner_result
88
89 nx_lv_actor_step(ctxP, s.scheduler, s.bus, NPC, tick); tick = tick + 50
90 nx_lv_actor_step(ctxP, s.scheduler, s.bus, NPC, tick); tick = tick + 50
91 nx_lv_actor_step(ctxP, s.scheduler, s.bus, NPC, tick); tick = tick + 50
92 let tokP: nx_int = ctxP.runner_result
93
94 if iter < (N_ITERS - 1) {
95 prompt_n[0] = nx_gft_vocab_byte(fixA, tokN) as u8
96 prompt_p[0] = nx_gft_vocab_byte(fixB, tokP) as u8
97 nx_lv_actor_reset_for_next_token(ctxN, s.scheduler, NARR, prompt_n, 1)
98 nx_lv_actor_reset_for_next_token(ctxP, s.scheduler, NPC, prompt_p, 1)
99 }
100 iter = iter + 1
101 }
102
103 if nx_bctm_capture_finish(timed, s, 11) != NX_BCTM_OK { return 2 }
104
105 // ===== Emit TSV header + data row =====
106 let buf: *u8 = sys_mmap(512)
107 let n_hdr: nx_int = nx_bc_emit_tsv_header(buf, 512)
108 if n_hdr <= 0 { return 3 }
109 sys_write(1, buf, n_hdr as i64)
110
111 // Label: "dual_real_v2_5iter" (18 bytes)
112 let label: *u8 = sys_mmap(18)
113 label[0]=0x64 as u8; label[1]=0x75 as u8; label[2]=0x61 as u8; label[3]=0x6C as u8
114 label[4]=0x5F as u8; label[5]=0x72 as u8; label[6]=0x65 as u8; label[7]=0x61 as u8
115 label[8]=0x6C as u8; label[9]=0x5F as u8; label[10]=0x76 as u8; label[11]=0x32 as u8
116 label[12]=0x5F as u8; label[13]=0x35 as u8; label[14]=0x69 as u8; label[15]=0x74 as u8
117 label[16]=0x65 as u8; label[17]=0x72 as u8
118 let n_row: nx_int = nx_bc_emit_tsv_row(buf, 512, base, label, 18)
119 if n_row <= 0 { return 4 }
120 sys_write(1, buf, n_row as i64)
121
122 // ===== "wallclock_elapsed_us\t<value>\n" line =====
123 let elab: *u8 = sys_mmap(21)
124 elab[0]=0x77 as u8; elab[1]=0x61 as u8; elab[2]=0x6C as u8; elab[3]=0x6C as u8
125 elab[4]=0x63 as u8; elab[5]=0x6C as u8; elab[6]=0x6F as u8; elab[7]=0x63 as u8
126 elab[8]=0x6B as u8; elab[9]=0x5F as u8; elab[10]=0x65 as u8; elab[11]=0x6C as u8
127 elab[12]=0x61 as u8; elab[13]=0x70 as u8; elab[14]=0x73 as u8; elab[15]=0x65 as u8
128 elab[16]=0x64 as u8; elab[17]=0x5F as u8; elab[18]=0x75 as u8; elab[19]=0x73 as u8
129 elab[20]=0x09 as u8
130 sys_write(1, elab, 21)
131 _emit_dec_i64(1, timed.wallclock_elapsed_us)
132
133 // ===== Substrate invariants =====
134 if base.total_actor_steps != 30 { return 5 }
135 if base.actors_completed != 2 { return 6 }
136 if base.actors_failed != 0 { return 7 }
137 if nx_ms_pending(s.bus, LIS) != 10 { return 8 }
138 if timed.wallclock_elapsed_us < 0 { return 9 }
139
140 return 0
141}