Three changes that together make the GPU primitive viable for the
go-gpu/bend pattern:
1. Binary portal format (length-prefixed raw bytes) — eliminates the
hex-string parse that ate 99% of wall time. Old text portal at
262 MB workload spent 421 sec parsing; binary format = native
speed. New flag + daemon command:
shake256-fanout --binary <in.bin> <out.bin>
daemon: process-bin <in.bin> <out.bin>
Wire (in): u32 out_bytes | u32 n | (u32 len | len bytes) × n
Wire (out): u32 n | u32 out_bytes | n × out_bytes
2. bend primitive (Lisp-smart GPU dispatch). Picked 'bend' over
{go, spark, cast, fan} per fox — HVM2 lineage, fits the
'reshape compute for GPU' mental model.
(bend (cuda-shake-fanout inputs 32))
→ runtime inspects expr; routes to GPU worker if cost-est
exceeds threshold AND worker reachable; else evaluates
locally in original lexical scope
(bend! expr)
→ force GPU, error if no worker available
Implementation files:
bend.lsp — macro + cost-estimator-based router
gpu-worker.lsp — TCP listener, dispatches over warm daemons
DESIGN-go-gpu.md — full architecture (already shipped)
Tier-specific helpers (tcp-*, spawn-process-stdio, sexp->string)
are noted as TODO per tier — Python uses subprocess + socket,
C uses fork + portal, asm uses syscall fork + sock_stream.
3. bench_binary.py — combined daemon + binary format benchmark.
GPU wins every cell of the grid by 1.5–10×:
in_sz N total host dev speedup
32 1,000,000 32 MB 470 ms 47 ms 10.11x
32 100,000 3.2 MB 47 ms 5 ms 9.95x
1024 100,000 102 MB 177 ms 79 ms 2.24x
16384 10,000 164 MB 231 ms 124 ms 1.86x
262144 1,000 262 MB 363 ms 231 ms 1.57x
Same workloads that lost 0.00× at hex+per-spawn now win 10× at
binary+daemon. 4000× relative perf swing from fixing wire format
and warming the context.
The peak 10× at small-input × high-N is the natural shape of crypto
protocols (commitments, Fiat-Shamir, PoW search). That's the win
zone for cuda-shake-fanout. README updated with the full table.