bend demo: 100M secp256k1 — epic 160x GPU win, ~33 minutes of CPU work

Replaces the small cuda-shake-fanout step and the modest kickmix
4x demo with a single dispatch you can feel: 100,000,000 secp256k1
scalar*G batched multiplications.

Numbers measured end-to-end through https://bend.unturf.com/ on
3090-ai:

  HTTP request size      ~32 bytes (just '(cuda-secp256k1-bench 100000000)')
  worker scalar gen      5.2 s    (/dev/urandom into 3.2 GB BSCP)
  GPU kernel             12.5 s   (7.99 Mkeys/s on 3090)
  total wall-clock       18.3 s
  CPU equivalent         ~2000 s = ~33 minutes (libsecp256k1 ref)
  speedup-est            ~160x

The 3.2 GB of random scalars never crosses the wire — the worker
synthesizes them from os.urandom and dispatches into the existing
cuda-secp256k1-batched-mul daemon. Response is a tiny S-expression
with the timing summary; no 6.4 GB result blob comes back.

Ping + health stay at the top so a visitor sees the chain warm up
before committing to the 18 s heavy run.
This commit is contained in:
russell@unturf.com 2026-06-14 19:58:57 -04:00
parent f85ef20784
commit a88cebced0
No known key found for this signature in database
2 changed files with 36 additions and 62 deletions

View file

@ -4,19 +4,18 @@
; above first. The playground guards the Run button so a customer
; machine never burns minutes on the local tiers.
;
; What you can call today (S-expression mode over HTTP):
; (ping) → (ok pong) — round-trip probe
; (health) → (ok (load-avg ...)) — worker telemetry
; (cuda-shake-fanout INPUTS OUT-BYTES)
; → (ok (HEX0 HEX1 ...)) — N SHAKE256 outputs
; (cuda-sim-ops-bin PATH N-BATCHES)
; → (ok (cuda-sim-result … (timing-ms …)))
; — kickmix circuit on the worker's bin
; Today's headline payload: 100,000,000 secp256k1 scalar*G operations
; in one HTTP POST. On a 3090 the daemon finishes in ~13 seconds;
; on a single CPU core (libsecp256k1 ~50K keys/s) the same workload
; would take ~33 minutes. That's a ~160× speedup — the kind of math
; only a GPU can do in a reasonable amount of time.
;
; Binary modes (BSHK / BCGB / BSCP / BSRT / BSB3) stream raw bytes via
; the wire-TCP path and stay native-only until Phase 2 lands server-side
; factory recipes (gated on auth — today an open recipe endpoint would
; let anyone occupy our GPU).
; The request is ~32 bytes of S-expression. The 3.2 GB of random
; scalars never crosses the wire — the worker generates them locally
; from /dev/urandom via examples/cuda-fanout/generate-bscp.py, calls
; into the existing cuda-secp256k1-batched-mul daemon, and returns
; just the timing summary. You see the GPU work happen in your
; output panel; your laptop never does the math.
(display ";; 1. probe round-trip ...") (newline)
(define r1 (bend!-call "(ping)"))
@ -28,25 +27,13 @@
(display " (health) → ") (display r2) (newline)
(newline)
(display ";; 3. small CUDA fan-out (3 inputs, 32-byte outputs) ...") (newline)
(define payload
(string-append
"(cuda-shake-fanout "
"(\"00\" \"01\" \"deadbeef\") "
"32)"))
(display " payload: ") (display payload) (newline)
(define r3 (bend!-call payload))
(display ";; 3. 100,000,000 secp256k1 scalar*G batch on the GPU") (newline)
(display ";; ~13 s on 3090 vs ~33 min on a CPU core (~160x)") (newline)
(display ";; sit tight — this is real compute, not a mock") (newline)
(define heavy "(cuda-secp256k1-bench 100000000)")
(display " payload: ") (display heavy) (newline)
(define r3 (bend!-call heavy))
(display " result : ") (display r3) (newline)
(newline)
(display ";; 4. feel the GPU win — kickmix circuit simulation") (newline)
(display ";; 14,848 ops / 58 qubits / 9024 shots / 141 batches") (newline)
(display ";; tiny HTTP payload (~70 bytes), heavy GPU work") (newline)
(display ";; CPU baseline ~1450 ms, GPU kernel ~360 ms (~4x)") (newline)
(define heavy "(cuda-sim-ops-bin \"/tmp/ecdsa-queue/out.bin\" 141)")
(display " payload: ") (display heavy) (newline)
(define r4 (bend!-call heavy))
(display " result : ") (display r4) (newline)
(newline)
(print "done")
(print "done — that math would have taken ~33 minutes on this CPU.")

View file

@ -4,19 +4,18 @@
; above first. The playground guards the Run button so a customer
; machine never burns minutes on the local tiers.
;
; What you can call today (S-expression mode over HTTP):
; (ping) → (ok pong) — round-trip probe
; (health) → (ok (load-avg ...)) — worker telemetry
; (cuda-shake-fanout INPUTS OUT-BYTES)
; → (ok (HEX0 HEX1 ...)) — N SHAKE256 outputs
; (cuda-sim-ops-bin PATH N-BATCHES)
; → (ok (cuda-sim-result … (timing-ms …)))
; — kickmix circuit on the worker's bin
; Today's headline payload: 100,000,000 secp256k1 scalar*G operations
; in one HTTP POST. On a 3090 the daemon finishes in ~13 seconds;
; on a single CPU core (libsecp256k1 ~50K keys/s) the same workload
; would take ~33 minutes. That's a ~160× speedup — the kind of math
; only a GPU can do in a reasonable amount of time.
;
; Binary modes (BSHK / BCGB / BSCP / BSRT / BSB3) stream raw bytes via
; the wire-TCP path and stay native-only until Phase 2 lands server-side
; factory recipes (gated on auth — today an open recipe endpoint would
; let anyone occupy our GPU).
; The request is ~32 bytes of S-expression. The 3.2 GB of random
; scalars never crosses the wire — the worker generates them locally
; from /dev/urandom via examples/cuda-fanout/generate-bscp.py, calls
; into the existing cuda-secp256k1-batched-mul daemon, and returns
; just the timing summary. You see the GPU work happen in your
; output panel; your laptop never does the math.
(display ";; 1. probe round-trip ...") (newline)
(define r1 (bend!-call "(ping)"))
@ -28,25 +27,13 @@
(display " (health) → ") (display r2) (newline)
(newline)
(display ";; 3. small CUDA fan-out (3 inputs, 32-byte outputs) ...") (newline)
(define payload
(string-append
"(cuda-shake-fanout "
"(\"00\" \"01\" \"deadbeef\") "
"32)"))
(display " payload: ") (display payload) (newline)
(define r3 (bend!-call payload))
(display ";; 3. 100,000,000 secp256k1 scalar*G batch on the GPU") (newline)
(display ";; ~13 s on 3090 vs ~33 min on a CPU core (~160x)") (newline)
(display ";; sit tight — this is real compute, not a mock") (newline)
(define heavy "(cuda-secp256k1-bench 100000000)")
(display " payload: ") (display heavy) (newline)
(define r3 (bend!-call heavy))
(display " result : ") (display r3) (newline)
(newline)
(display ";; 4. feel the GPU win — kickmix circuit simulation") (newline)
(display ";; 14,848 ops / 58 qubits / 9024 shots / 141 batches") (newline)
(display ";; tiny HTTP payload (~70 bytes), heavy GPU work") (newline)
(display ";; CPU baseline ~1450 ms, GPU kernel ~360 ms (~4x)") (newline)
(define heavy "(cuda-sim-ops-bin \"/tmp/ecdsa-queue/out.bin\" 141)")
(display " payload: ") (display heavy) (newline)
(define r4 (bend!-call heavy))
(display " result : ") (display r4) (newline)
(newline)
(print "done")
(print "done — that math would have taken ~33 minutes on this CPU.")