code wiki / _hdl_build / nx_parallel_ingest.nx

nx_parallel_ingest.nx source

↩ module page · 57 lines · 2698 B

1// nx_parallel_ingest.nx -- ingest many exceeds/capabilities IN PARALLEL without running out 2// of resources. The mechanism is three guarantees: 3// 1. BOUNDED CONCURRENCY -- a worker pool of at most K live forks at any instant (never a 4// fork-bomb); items stream through the pool, K busy at a time, the rest queued. 5// 2. PROCESS ISOLATION -- each worker is a fork; its scratch memory lives in ITS address 6// space and is reclaimed by the kernel on exit, so the parent's memory never grows with 7// the work. Per-item RAM is O(1) in the parent, not O(n). 8// 3. COMPACT SHARED BANK -- results are fixed-size records in ONE shared mmap (MAP_SHARED, 9// 0x21, so children write what the parent reads); the bank is O(n) bytes, not O(n) machine code. 10// So total resource use = K*(worker RAM) + n*(record size), both bounded and tunable -- you 11// can ingest thousands of exceeds with a handful of cores and a few KB. license_tier: ORIGINAL 12 13import "nx_syscalls.nx" // __syscall, SYS_MMAP, sys_fork, sys_wait4, sys_exit 14import "nx_boolsynth.nx" // per-item work: synthesize a minimal circuit 15 16// a SHARED anonymous mapping (visible across fork) -- the result bank. 17func par_mmap_shared(size: i64) -> *u8 { 18 let r: i64 = __syscall(SYS_MMAP, 0, size, 3, 0x21, 0 - 1, 0) 19 return r as *u8 20} 21 22// the per-item work a worker does: synthesize the minimal boolean circuit for truth table i 23// (pure compute, all scratch in the worker's own address space). returns its gate count. 24func par_work(i: i64) -> i64 { 25 let op: *i64 = sys_mmap(8 * 12) as *i64 26 let a: *i64 = sys_mmap(8 * 12) as *i64 27 let b: *i64 = sys_mmap(8 * 12) as *i64 28 let L: i64 = bl_find(i, op, a, b, 6) 29 if L < 0 { return 99 } 30 return L 31} 32 33// BOUNDED-PARALLEL ingest of items 0..n: at most K live workers; each writes bank[i]. The 34// parent only ever holds K child PIDs + the bank -- memory stays flat as n grows. 35func par_ingest(n: i64, K: i64, bank: *u8) -> i64 { 36 var next: i64 = 0 37 var live: i64 = 0 38 let status: *i64 = sys_mmap(16) as *i64 39 var done: i64 = 0 40 while done == 0 { 41 var fill: i64 = 1 42 while fill == 1 { 43 if live >= K { fill = 0 } else { if next >= n { fill = 0 } else { 44 let pid: i64 = sys_fork() 45 if pid == 0 { 46 bank[next] = par_work(next) as u8 // CHILD: compute + write shared, then exit 47 sys_exit(0) 48 } 49 live = live + 1 50 next = next + 1 51 } } 52 } 53 if live > 0 { sys_wait4(0 - 1, status, 0); live = live - 1 } 54 if next >= n { if live <= 0 { done = 1 } } 55 } 56 return 0 57}