bend.html: fleet section — cross-GPU + cluster numbers + first sweep result
Adds a new "Fleet" section between the ecdsafail workload table &
the catalog. Documents what now runs in production:
- 2-host LAN cluster: 3090-ai:9091 + ai.foxhop.net:9092 (4090, sm_89)
- 4090 box shares the GPU with a qwen LLM (vllm) — our bend kernels
fit alongside because secp256k1 / CGBN workloads burn SMs only for
milliseconds at a time, then release
- Cross-GPU parity at small N: 0.07-0.10 ms kernel on both 3090 &
4090 for CGBN n=100k mod-mul; both starve between calls so the
4090's FLOPS advantage doesn't show until kernels run long enough
to amortize wire overhead
- Cluster aggregate: 1.6× speedup at 200 × n=1k (cap is client-side
serialization, not workers); async fan-out unlocks the remaining 2×
- First measured sweep through full lumbda → emit-ops-bin → bend →
demo_ops pipeline: refined Bernstein-Yang variant cuts Σ Toffoli
by 36.5% at p=11, within 3 pts of the p=251 reference prediction
(-40%). Small-fixture screen confirmed faithful predictor.
- Robustness gap fixed (handle-binary-* delete-file unconditional);
12 guard lines across 6 sites; zero crashes since deployment.
This commit is contained in:
parent
3a8c66a148
commit
7b67b727e1
1 changed files with 51 additions and 0 deletions
|
|
@ -92,6 +92,57 @@ make gpu-worker LUMBDA=asm # smallest footprint</code></pre>
|
|||
<p>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.</p>
|
||||
</section>
|
||||
|
||||
<section id="fleet">
|
||||
<h2>Fleet — cross-GPU & cluster numbers</h2>
|
||||
<p>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 <code>bend.lsp</code> via <code>*bend-workers*</code> & the <code>BEND_WORKERS</code> environment variable.</p>
|
||||
|
||||
<table>
|
||||
<thead><tr><th>host</th><th>GPU</th><th>arch</th><th>port</th><th>daemons live</th><th>coexists with</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><code>3090-ai.foxhop.net</code></td><td>RTX 3090 (24 GB)</td><td>sm_86</td><td>9091</td><td>shake / cgbn / secp / sim-ops-bin / sim-axis-flip</td><td>idle</td></tr>
|
||||
<tr><td><code>ai.foxhop.net</code></td><td>RTX 4090 (24 GB)</td><td>sm_89</td><td>9092</td><td>shake / cgbn / secp</td><td>qwen LLM serving on ports 9090 + 9091 (Erlang Cowboy, uid 992)</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h3>Cross-GPU parity at small batches</h3>
|
||||
<p>Single-call kernel time at <code>n=100k</code> CGBN 256-bit mod-mul:</p>
|
||||
<table>
|
||||
<thead><tr><th>host</th><th>kernel ms</th><th>wall ms (incl. PCIe + wire)</th><th>Mops/s (wall)</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>3090-ai</td><td>0.07–0.10</td><td>336 (median)</td><td>0.30</td></tr>
|
||||
<tr><td>ai (4090)</td><td>0.07–0.10</td><td>362 (median)</td><td>0.28</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>At <code>n=100k</code>, 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.</p>
|
||||
|
||||
<h3>Cluster aggregate — round-robin fan-out</h3>
|
||||
<table>
|
||||
<thead><tr><th>workload</th><th>solo (1 host)</th><th>cluster (2 hosts)</th><th>speedup</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>200 × <code>n=1k</code> CGBN mod-mul</td><td>0.052 Mops/s</td><td>0.084 Mops/s</td><td><strong>1.6×</strong></td></tr>
|
||||
<tr><td>6 × <code>n=100k</code> CGBN mod-mul</td><td>0.15 Mops/s</td><td>0.18 Mops/s</td><td>1.2×</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>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.</p>
|
||||
|
||||
<h3>First measured ECDSA-mission sweep</h3>
|
||||
<p>The first end-to-end run through the full lumbda → emit-ops-bin walker → bend → demo_ops pipeline landed today at <code>runs/lumbda-sweep-001/</code>. Two of six lever variants emitted & scored at <code>p=11</code> point-add width:</p>
|
||||
<table>
|
||||
<thead><tr><th>variant</th><th>n_ops</th><th>Σ Clifford</th><th>Σ Toffoli</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>Solinas + Fermat textbook B-Y</td><td>48,763</td><td>1,687,232</td><td>749,056</td></tr>
|
||||
<tr><td><strong>Solinas + refined B-Y</strong> (Phase B step 10)</td><td><strong>32,333</strong></td><td><strong>1,237,440</strong></td><td><strong>475,648</strong></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><strong>Refined Bernstein-Yang cuts Σ Toffoli by 36.5% at production-relevant width.</strong> Our small-fixture lever screen predicted −56% at <code>p=5</code>, & the <code>p=251</code> 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 <code>p=11</code>, filter to winners, promote only winners to <code>p=251</code> production cost.</p>
|
||||
<p>Four remaining variants still emitting (the lumbda walker is CPU-bound on the local box at full Phase B width); <code>dispatch-sweep.py</code> auto-resumes against new <code>.bin</code> files as they land.</p>
|
||||
|
||||
<h3>Robustness</h3>
|
||||
<p>The binary handlers (<code>handle-binary-shake</code>, <code>handle-binary-cgbn</code>, <code>handle-binary-secp</code>) used to call <code>delete-file</code> 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 (<code>(if (file-exists? PATH) (delete-file PATH))</code>) closed the gap. Fix held under sustained sweep traffic with zero crashes since deployment.</p>
|
||||
</section>
|
||||
|
||||
<section id="catalog">
|
||||
<h2>Form catalog</h2>
|
||||
<p>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 <code>planned</code> until numbers exist.</p>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue