diff --git a/www/bend.html b/www/bend.html index c29fbea..8268e29 100644 --- a/www/bend.html +++ b/www/bend.html @@ -92,6 +92,57 @@ make gpu-worker LUMBDA=asm # smallest footprint
Crossover at ~115 batches. GPU kernel carries ~5,070 ms of fixed overhead (init + alloc + upload) plus ~12 ms per batch; CPU runs ~55 ms per batch. The kickmix circuit's conditional ops cause branch divergence — this is one form where GPU does not dominate. Honest numbers go in the catalog below.
+bend runs on a 2-host LAN cluster today. The worker on each box is a lumbda C-tier process; daemons stay warm across requests. Round-robin selection lives in bend.lsp via *bend-workers* & the BEND_WORKERS environment variable.
| host | GPU | arch | port | daemons live | coexists with |
|---|---|---|---|---|---|
3090-ai.foxhop.net | RTX 3090 (24 GB) | sm_86 | 9091 | shake / cgbn / secp / sim-ops-bin / sim-axis-flip | idle |
ai.foxhop.net | RTX 4090 (24 GB) | sm_89 | 9092 | shake / cgbn / secp | qwen LLM serving on ports 9090 + 9091 (Erlang Cowboy, uid 992) |
The 4090 box shares the GPU with a qwen LLM (vllm) serving on the same machine. Our bend kernels fit alongside qwen comfortably because the secp256k1 / CGBN workloads burn the SMs only for milliseconds at a time, then release. The qwen server keeps its model weights resident; our kernels allocate transient VRAM for the per-call batch, run, free, return. 24 GB VRAM is enough for both.
+ +Single-call kernel time at n=100k CGBN 256-bit mod-mul:
| host | kernel ms | wall ms (incl. PCIe + wire) | Mops/s (wall) |
|---|---|---|---|
| 3090-ai | 0.07–0.10 | 336 (median) | 0.30 |
| ai (4090) | 0.07–0.10 | 362 (median) | 0.28 |
At n=100k, kernels finish faster than the per-call PCIe transfer (6.4 MB tx) + LAN wire round trip. Both GPUs run the same workload in the same kernel time because neither saturates — both starve between calls. The 4090's raw FLOPS advantage shows up only when the kernel runs long enough to amortize wire overhead.
| workload | solo (1 host) | cluster (2 hosts) | speedup |
|---|---|---|---|
200 × n=1k CGBN mod-mul | 0.052 Mops/s | 0.084 Mops/s | 1.6× |
6 × n=100k CGBN mod-mul | 0.15 Mops/s | 0.18 Mops/s | 1.2× |
Speedup caps at 1.6× instead of 2× because the dispatching client serializes one call at a time. An async fan-out client unlocks the remaining 2× headroom. Workers themselves never block each other.
+ +The first end-to-end run through the full lumbda → emit-ops-bin walker → bend → demo_ops pipeline landed today at runs/lumbda-sweep-001/. Two of six lever variants emitted & scored at p=11 point-add width:
| variant | n_ops | Σ Clifford | Σ Toffoli |
|---|---|---|---|
| Solinas + Fermat textbook B-Y | 48,763 | 1,687,232 | 749,056 |
| Solinas + refined B-Y (Phase B step 10) | 32,333 | 1,237,440 | 475,648 |
Refined Bernstein-Yang cuts Σ Toffoli by 36.5% at production-relevant width. Our small-fixture lever screen predicted −56% at p=5, & the p=251 ground-truth reference predicted −40%. Measured −36.5% sits within 3 percentage points of the larger-width prediction. The small-fixture lever screen earns its keep as a faithful predictor: sweep cheap at p=11, filter to winners, promote only winners to p=251 production cost.
Four remaining variants still emitting (the lumbda walker is CPU-bound on the local box at full Phase B width); dispatch-sweep.py auto-resumes against new .bin files as they land.
The binary handlers (handle-binary-shake, handle-binary-cgbn, handle-binary-secp) used to call delete-file unconditionally after daemon failure — if the daemon errored before writing the output portal, the missing-file raise crashed the entire listener. 12 guard lines across 6 sites ((if (file-exists? PATH) (delete-file PATH))) closed the gap. Fix held under sustained sweep traffic with zero crashes since deployment.
A form earns a slot here only after we have published a benchmark or measured one on our hardware. "I think this would be fast" does not earn a slot — the form-status column says planned until numbers exist.