examples/cuda-fanout: DESIGN-ecdsa-integration.md
Sketches how bend would wire into ecdsafail-challenge candidate
search loop on the foxhop.net side:
ecdsa/lumbda/search.lsp
→ (bend!-call '(cuda-sim-ops-bin ops-path 141))
→ gpu-worker.lsp routes to demo_ops --portal
→ S-exp result back to lumbda, scoring proceeds
Identifies the two pieces missing before this lands:
1. `system`-equivalent primitive in lumbda (or spawn+wait via
existing spawn-process-stdio)
2. Phase B step 7 (Solinas mod-mul) so lumbda emits real-scale
ops.bin variants worth bending
Once both close, this is a half-day wire-up.
Cross-references:
~/git/www.foxhop.net/ecdsa/cuda/ — the CUDA prototype
~/git/www.foxhop.net/ecdsa/lumbda/search.lsp — current search loop
examples/cuda-fanout/DESIGN-go-gpu.md — the broader bend RPC design
This commit is contained in:
parent
07a8a4aaf7
commit
aa428cdeb2
1 changed files with 126 additions and 0 deletions
126
examples/cuda-fanout/DESIGN-ecdsa-integration.md
Normal file
126
examples/cuda-fanout/DESIGN-ecdsa-integration.md
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
# Integrating bend → ecdsa lumbda search loop
|
||||
|
||||
The motivating workload behind `bend` is ecdsafail-challenge candidate
|
||||
search: the lumbda search loop (`ecdsa/lumbda/search.lsp` in
|
||||
www.foxhop.net) emits circuit variants, scores each, picks the lowest.
|
||||
At toy scale it runs in lumbda's own simulator (`sim.lsp`). At
|
||||
upstream scale (12.8M ops, 1,355 qubits, 1.3M bits) it needs the CUDA
|
||||
prototype (`ecdsa/cuda/demo_upstream`, byte-identical to upstream Rust
|
||||
`eval_circuit`).
|
||||
|
||||
`bend` is the glue.
|
||||
|
||||
## Where things stand
|
||||
|
||||
In www.foxhop.net's `ecdsa/cuda/`:
|
||||
|
||||
| binary | purpose | upstream byte-parity? |
|
||||
|--------|---------|----------------------|
|
||||
| `demo` | hand-crafted 21-op circuit, CPU↔GPU smoke | n/a |
|
||||
| `demo_ops` | ops.bin loader, LFSR RNG, scoring | gate counts ✓ |
|
||||
| `demo_upstream` | SHAKE + secp256k1 register init | full (every digit) |
|
||||
| `demo_multi` | multi-candidate batch driver, S-exp portal output | per candidate |
|
||||
|
||||
Each writes an S-expression portal lumbda can ingest directly.
|
||||
|
||||
## The new GPU op for bend's registry
|
||||
|
||||
Add a `cuda-sim-ops-bin` op (analogous to today's `cuda-shake-fanout`):
|
||||
|
||||
```scheme
|
||||
;; in bend.lsp
|
||||
(define (bend-sim-cost args)
|
||||
"(cuda-sim-ops-bin path n-batches) — cost = n-batches × 12.8M ops
|
||||
approx 100 ns/op host."
|
||||
(let ((n-batches (car (cdr args))))
|
||||
(* n-batches 12788119 100)))
|
||||
|
||||
(bend-register-op! 'cuda-sim-ops-bin bend-sim-cost)
|
||||
```
|
||||
|
||||
## Worker handler
|
||||
|
||||
```scheme
|
||||
;; in gpu-worker.lsp
|
||||
(define (handle-cuda-sim-ops-bin args)
|
||||
(let* ((ops-path (car args))
|
||||
(n-batches (car (cdr args)))
|
||||
(portal-out (gensym-path "/tmp/bend-cuda-sim" ".portal"))
|
||||
(cmd (string-append
|
||||
"/home/fox/git/www.foxhop.net/ecdsa/cuda/demo_ops "
|
||||
ops-path
|
||||
" --batches " (number->string n-batches)
|
||||
" --portal " portal-out)))
|
||||
(system cmd) ; or spawn-process-stdio + wait
|
||||
(let ((result (read-from-string (file->string portal-out))))
|
||||
(delete-file portal-out)
|
||||
(list 'ok result))))
|
||||
```
|
||||
|
||||
Note: `system` doesn't exist as a lumbda primitive today; either add
|
||||
one (~10 LoC per tier) or spawn through `spawn-process-stdio` and
|
||||
read stdout to confirm completion before reading the portal.
|
||||
|
||||
## Search-loop side
|
||||
|
||||
`ecdsa/lumbda/search.lsp` currently does:
|
||||
|
||||
```scheme
|
||||
(define (eval-variant variant-id cases)
|
||||
(let ((circ (emit-variant variant-id ...)))
|
||||
(simulate circ) ; in-process lumbda sim.lsp
|
||||
...))
|
||||
```
|
||||
|
||||
With bend:
|
||||
|
||||
```scheme
|
||||
(load "bend.lsp")
|
||||
(define (eval-variant-cuda variant-id ops-bin-path)
|
||||
(let* ((result (bend!-call
|
||||
(list 'cuda-sim-ops-bin ops-bin-path 141))))
|
||||
;; result shape from demo_ops's portal:
|
||||
;; (cuda-multi-result (ops-path …) (status OK)
|
||||
;; (totals (clifford N) (toffoli N))
|
||||
;; (timing-ms …))
|
||||
(let ((totals (section result 'totals)))
|
||||
(list variant-id
|
||||
(car (cdr (assoc 'toffoli totals)))
|
||||
(car (cdr (assoc 'clifford totals)))))))
|
||||
```
|
||||
|
||||
Each variant emits its own `ops.bin` (the upstream binary format we
|
||||
parse with `ops_loader.c`), the search loop bends it to a GPU worker,
|
||||
worker calls `demo_ops`, returns the portal, lumbda picks the
|
||||
winner.
|
||||
|
||||
## What's missing before this lands
|
||||
|
||||
1. `system` or equivalent primitive in lumbda (Python/C/asm) — one of:
|
||||
- synchronous subprocess wait
|
||||
- `spawn-process-stdio` + wait via reading "done" line
|
||||
2. Lumbda's emitter side needs to produce upstream-format `ops.bin`
|
||||
files. Toy 4-bit circuits don't need this; real secp256k1 circuits
|
||||
would require Phase B step 7+ (Solinas mod-mul + Bernstein-Yang
|
||||
mod-inv) to close before there are interesting variants to bend.
|
||||
3. The search-loop scoring rule needs adaptation: today it scores
|
||||
`avg_toffoli × peak_qubits`; the CUDA portal returns Σ counts over
|
||||
141 batches × 64 shots, so dividing by 9024 gives the
|
||||
per-shot avg upstream uses.
|
||||
|
||||
## Why this design
|
||||
|
||||
- `bend` already does the routing decision: small toy circuits stay
|
||||
in lumbda's in-process `sim.lsp`; large ones bend to GPU.
|
||||
- Wire protocol identical to `cuda-shake-fanout` — no new primitive
|
||||
beyond a Scheme registration entry.
|
||||
- `demo_ops --portal` output already matches lumbda's S-expression
|
||||
ingestion contract (see `ecdsa/cuda/main_ops.c` portal writer).
|
||||
- Worker pool elasticity: any GPU host can register
|
||||
`cuda-sim-ops-bin` and become eligible to receive candidate
|
||||
evaluations. Coordinator's load-aware dispatch (`DESIGN-go-gpu.md`)
|
||||
handles fan-out across multiple GPU hosts.
|
||||
|
||||
This is a half-day's wire-up once Phase B step 7 closes and lumbda
|
||||
gains a `system`-equivalent primitive. Until then, the architecture
|
||||
is documented; the integration waits.
|
||||
Loading…
Add table
Add a link
Reference in a new issue