bend is a Lumbda primitive that decides per call whether to evaluate locally or ship to a CUDA worker over our wire protocol. Tiny inputs stay local; heavy inputs bend to a worker that holds a warm CUDA context across requests. The decision uses a cost estimator on the argument shape, not the operation name.
This page documents the protocol, the wire numbers we measured, and a catalog of forms — standalone CUDA binaries with published speedups that bend can dispatch to.
Start a GPU worker
# On any host with nvcc + a CUDA-capable GPU:
make gpu-worker
# → builds examples/cuda-fanout/shake256-fanout
# → builds the C tier (~10× faster wire orchestration than Python)
# → launches gpu-worker.lsp on port 9091
# Override tier or port:
make gpu-worker LUMBDA=python PORT=9001 # easier debugging
make gpu-worker LUMBDA=asm # smallest footprint
Call it from any tier
;; bend works on every tier — Python, C, asm — through the same
;; tcp-* + portal primitives lumbda already ships.
(load "examples/cuda-fanout/wire.lsp")
(load "examples/cuda-fanout/bend.lsp")
(load "examples/cuda-fanout/bend-macros.lsp") ; Python/C only — asm uses bend-call
;; Tiny — cost below threshold, evaluates locally
(bend (cuda-shake-fanout '("00" "01" "deadbeef") 32))
;; Heavy — cost above threshold, ships to the GPU worker
(bend (cuda-shake-fanout one-million-inputs 32))
On a single RTX 3090 with a warm daemon, SHAKE256 fan-out matched hashlib.shake_256 byte-for-byte and won by 1.5–10× across the workloads we measured. Below the break-even (~100 MB of bulk hash work) host CPU stays faster — the cost estimator picks correctly.
Wire protocol — two modes
The CUDA kernel runs inside the leaf binary; what the tier choice affects is wire orchestration. The wire has two modes: S-expression text (the default — hex strings inside a Scheme list) and binary (magic BSHK header + raw bytes, identical layout to the daemon's binary portal). Binary mode bypasses S-expression parsing entirely:
| workload | Py S-exp | Py binary | C S-exp | C binary |
|---|---|---|---|---|
| 100 × 16 B | 3.43 ms | 0.74 ms | 0.40 ms | 0.15 ms |
| 1k × 16 B | 23.24 ms | 0.76 ms | 2.77 ms | 0.22 ms |
| 10k × 16 B | 218.82 ms | 1.27 ms | CLIFF | 0.88 ms |
| 100k × 16 B | 2,219 ms | 10.18 ms | CLIFF | 10.35 ms |
| 1M × 16 B | 23,811 ms | 159 ms | CLIFF | 157 ms |
Binary mode wins by 30–200× over S-expression mode at scale. At 1 M × 16 B inputs, C tier binary is 157 ms end-to-end versus 23,811 ms for the S-exp path — a 150× speedup. The CUDA kernel itself on this 3090 runs in ~47 ms; binary wire adds ~110 ms of file I/O + framing on top, a 2.5× multiplier instead of the 500× multiplier the S-exp path imposed.
Critically, at huge workloads bend now beats host hashlib: host SHAKE256 over 1 M tiny inputs is ~2 s on a single Python core; bend via binary worker is 157 ms — a 12× speedup of host. The cost estimator in bend.lsp should be updated to know about the binary path so the routing decision picks GPU at this scale instead of staying local.
Binary mode lives behind the BSHK magic byte in the wire payload. S-expression callers see no change; binary callers prepend the magic and send raw bytes. See examples/cuda-fanout/bench_tiers.py --binary for the protocol implementation.
Three tiers, three operating points (S-expression mode): C tier wins at small & medium scales (8× faster than Python); asm tier hits 0.21 ms at very small inputs (~30% behind C, 6× faster than Python, 70 KB statically linked, zero libc); Python tier scales linearly (~22 µs per input) all the way through 1 M inputs but runs slowly on a single core. The S-exp CLIFFs at 10k (C) and 1k (asm) are tier-internal reader limits — binary mode bypasses them entirely.
The CUDA toolchain stays isolated to the leaf binary the worker spawns. No tier links libcudart; no tier requires nvcc at build time. Asm tier hosts workers through hand-written pipe2 + fork + execve syscalls — no libc anywhere on the chain.
Real workload — ecdsafail search
Beyond hash fan-out, bend now dispatches quantum-reversible circuit scoring for our secp256k1 point-addition challenge work at foxhop.net/ecdsa. Lumbda emits an upstream-format ops.bin from a Phase B Roetteler 12-step circuit, calls (bend!-call '(cuda-sim-ops-bin path 141)), & receives Σ Clifford / Σ Toffoli totals back from a GPU worker over our binary wire — same cross-tier validation, same byte-identical portal contract the hash demo proves. Search loops on any host tier ship candidate scoring to whichever fleet node holds a warm CUDA context.
Measured on a 3090 against HEAD's 12.8 M-op kickmix ops.bin (716 MB):
| n_batches | shots | wire-s | cpu-ms | gpu-ms | gpu/cpu |
|---|---|---|---|---|---|
| 1 | 64 | 5.5 | 42 | 5,107 | 0.008 |
| 16 | 1,024 | 7.3 | 850 | 5,800 | 0.146 |
| 64 | 4,096 | 11.4 | 3,444 | 6,216 | 0.553 |
| 128 | 8,192 | 17.1 | 7,060 | 6,604 | 1.07 |
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.
Form catalog
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.
Status legend
live— binary built, worker dispatches it, numbers recorded on our hardwaresurveyed— published benchmark cited, prototype binary not yet wrapped; speedup claims need verification on our fleet before promotion toliveplanned— design slot reserved, no binary
The catalog grows continuously. Each form below carries enough metadata for anyone to start a port: canonical reference, reported speedup, target hardware, sketch wire shape. Forms with HIGH relevance to our active missions (foxhop ECDSA work, undefect defect-scanning, unsandbox / unturf permacomputer infrastructure) move up the build queue.
Live forms
| form | status | hardware | speedup vs CPU | wire shape |
|---|---|---|---|---|
cuda-shake-fanout |
live | RTX 3090 | 12× over host hashlib at 1 M × 16 B inputs | (cuda-shake-fanout '(hex ...) out-bytes) + BSHK binary |
cuda-sim-ops-bin |
live | RTX 3090 | 1.07× at 128 batches (8192 shots); crossover ~115 batches | (cuda-sim-ops-bin "path/to/ops.bin" n-batches) |
Surveyed forms (published precedent, build queued)
A. cuda-secp256k1-batched-mul — batched secp256k1 scalar / point ops
Speedup: gECC 4.94× on unknown-point mul, 5.56× on ECDSA verify vs CPU. VanitySearch forks hit 6.5 Gkeys/s on RTX 4090, 8.6 Gkeys/s on RTX 5090, 2.65 Gkeys/s on RTX 3080. Endomorphism + Montgomery batch-inversion (one mod-inv per N points instead of N) carries the kernel.
Wire: (secp-mul-batch (scalars . blob<N×32B>) (base-point . blob<64B>)) → (points . blob<N×64B>)
References: gECC paper · VanitySearch · VanitySearch-Bitcrack fork
B. cuda-bignum-cgbn — 256-bit modular arithmetic primitives
Speedup: 100×+ on dense mul vs Xeon-20c + GMP + OpenMP on V100 (midsize-int study).
Wire: (cgbn-batch (op . mod-mul|mod-inv|mod-add) (modulus . blob<32B>) (a . blob<N×32B>) (b . blob<N×32B>)) → blob<N×32B>
References: NVlabs CGBN · midsize-int benchmarks
C. cuda-rho-pollard-walk — Pollard rho / kangaroo walks
Speedup: 87.7 M ops/sec on RTX 2070 Super for ECCp79 (Certicom challenge solved in ~3 hours). Original CUDA Pollard paper reports > 7.2 M points/sec at 256 threads on older HW.
Wire: (rho-walk-batch (start-points . blob<W×64B>) (steps . N) (distinguished-mask . blob<32B>)) → (distinguished . blob<K×96B>)
References: atlomak/CUDA-rho-pollard · oritwoen/kangaroo
D. cuda-clifford-stabilizer — tableau stabilizer simulator (Stim-on-GPU)
Speedup: 186× over Stim (CPU SOTA) on equivalence-checking. STABSim a first GPU stabilizer sim to scale better than CPU on QEC workloads.
Wire: (stab-sim-batch (n-qubits . k) (circuit . blob) (n-shots . S)) → (samples . blob<S×ceil(k/8)>)
References: STABSim · Qimax · equivalence-checking
E. cuda-bernstein-yang-inv — batched modular inverse (safegcd)
Speedup: 3–10× per inversion over Fermat on CPU. No published dedicated CUDA implementation found — gECC uses Montgomery's batched-inversion trick instead. Standalone Bernstein-Yang-on-CUDA holds novel territory.
Wire: (modinv-batch (modulus . blob<32B>) (xs . blob<N×32B>)) → blob<N×32B>
References: safegcd · Jumping for Bernstein-Yang
F. cuda-ntt-poly — Number Theoretic Transform
Speedup: Up to 123× over CPU; 21× on RTX 3070; cuFFT-comparable kernel structure.
Wire: (ntt (mod . p) (omega . root) (xs . blob<N×8B>)) → blob<N×8B>
References: NTTSuite · FHE NTT
G. cuda-radix-sort / cuda-prefix-scan — reduction primitives
Speedup: 1.4 G keys/sec on Titan; 20–50× over CPU merge sort; 257× over Intel Xeon Phi for scan.
Wire: (sort-u64 (xs . blob<N×8B>)) → blob<N×8B>
References: NVIDIA CUB · Onesweep
Wave 2 — broader surveyed forms (2026-06-05)
Sorted by reported speedup vs CPU descending. Speedups quoted from published benchmarks on the cited hardware; numbers labelled surveyed have not yet run on our fleet, so this table calls a paper a paper and a measurement a measurement.
| form | speedup | hardware | relevance | ref |
|---|---|---|---|---|
cuda-minhash-weighted | 600–1000× vs numpy+MKL | Titan X vs 12-core Xeon E5-1650 | HIGH — undefect corpus dedup, CVE shard clustering | src-d/minhashcuda |
cuda-cuckoo-filter | 378× insert, 258× delete | A100 (TCF on Perlmutter) | HIGH — foxhop ECDSA candidate-pruning, undefect URL-seen filter | arXiv:2603.15486 |
cuda-aes-ctr-chacha20 | 211–400 GB/s (ChaCha8 / ChaCha20) | single GPU (RTX 3070 sustaining 672 Gbps Poly1305) | HIGH — AEAD on lumbda portal envelopes between tiers | AsyncGBP |
cuda-suffix-array-skew | 30–242× vs CPU SA-IS | Tesla K20 | MEDIUM — substring search for undefect source-corpus scans | Liu/Luo |
cuda-kdtree-build | 30–242× build, 1.6–200× kNN | RTX (RT cores) | MEDIUM — spatial index for unsandbox fleet locality | Zhou et al. |
cuda-sat-paraFROST-elim | 93× peak, 48× avg on variable elim | NVIDIA + CADICAL/Kissat baseline | HIGH — ECDSA / reversible-circuit equivalence checking via CNF | ParaFROST |
cuda-aho-corasick-pfac | ~50–100× (IDS pkt-inspect) | GTX-class | HIGH — secret/CVE-string scan across OSS source mirrors | PFAC |
cuda-dilithium-pqsig | 57.7× keygen+sign+verify vs single CPU thread | RTX 3090 Ti | HIGH — PQ migration for unsandbox TLS, foxhop disclosure signing | IACR 2024/1365 |
cuda-mc-options-pricing | 25–152× (barrier-call kernel 152×) | Tesla C1060 / modern | LOW — calibration form, well-understood arithmetic | GPU Gems Ch.45 |
cuda-cuFFT-batched-1D | 8–32× vs MKL; tcFFT 1.1–3.2× vs cuFFT | V100 / A100 | MEDIUM — spectrogram dispatch for punters-cc audio correlation | tcFFT |
cuda-blake3-tree | ~5–20× (tree mode) | Blaze-3 CUDA | HIGH — content-addressed lumbda portal frames, foxhop attachments | Blaze-3 |
cuda-bloom-filter-modern | ~6× CPU; 3.4 B inserts/s | B200 / Perlmutter | HIGH — foxhop candidate-pruning, undefect scan-target known-set | arXiv:2512.15595 |
cuda-gemm-batched-FP8 | 4.8× FP8 vs A100; 716 TFLOPS H100 | H100 SXM | LOW — calibration form, lattice-PQC matrix substrate | cuBLAS 12.0 |
cuda-batched-matrix-inverse | 4.3–16.8× vs MAGMA | P100 (650–800 GF SP) | LOW — linear-algebra verifiers on reversible-circuit checking | Superfri 2018 |
cuda-hash-join-radix | 4 B tuples/s single; 1.8 T tuples/s on 1024 A100 | A100 cluster | MEDIUM — undefect CVE↔commit↔package joins | ADMS-21 |
cuda-kmer-count | 4–6× vs KMC2; ~2× Jellyfish/KMC1 | RapidGKC, Gerbil | LOW — bioinformatics adjacency; identical bend-portal shape | RapidGKC |
cuda-cgraph-traversal | 38 B TEPS; PageRank half-billion nodes in seconds | DGX2 | MEDIUM — undefect dependency-DAG analytics, upstream call-graphs | cuGraph |
cuda-triangle-count-TRUST | ~1 T TEPS (first trillion-TEPS triangle counter) | multi-A100 | MEDIUM — community-structure detection for twitter-x-punters | TRUST |
cuda-ldpc-bp-decoder | 10 Gbps with early-termination | GPGPU | LOW — PQ-KEM noise modelling, SDR experiments on radio nodes | MDPI Electronics 2022 |
cuda-nvcomp-zstd | 2.2× decompress (zstd); 1.4× LZ4; 1.9× snappy | H100 / A100 | HIGH — undefect corpus shards, lumbda portal envelopes, permacomputer ingest | nvCOMP |
Wave 3 — surveyed 2026-06-05
15 additional forms spanning ZK / SNARK provers, pairing crypto, tensor network contraction, sparse linear algebra, CV primitives, numerical solvers, generic belief propagation, MD/CFD kernels, convex optimization, DSP beyond cuFFT, DB aggregations, graph theory beyond triangle/PageRank. Sorted by reported speedup or absolute throughput descending.
| form | speedup / throughput | hardware | relevance | ref |
|---|---|---|---|---|
cuda-fluidx3d-lbm | 100–200× vs ANSYS Fluent / OpenFOAM; 8,799 MLUPS single A100 | A100 | unsandbox MEDIUM (HPC reproducibility, OpenCL backend matches our fleet) | FluidX3D |
cuda-mfcc-spectral | ~97× CPU MFCC; STFT ~75× via cuSignal vs SciPy | GTX 580 / RTX 30-series | unsandbox HIGH — punters-cc, BT-DISC forensics, real-time CC pipeline | cuSignal |
cuda-batched-lp-simplex | 95× over CPLEX; 5× over GLPK on a batch of 100K LPs | GTX 980-class | unsandbox HIGH — resource scheduling, Prime Mission workstation balancing | arXiv 1802.08557 |
cuda-betweenness-centrality-weighted | 30–150× warp-centric weighted BC | GTX onwards | undefect HIGH — workaholic-node detection on dependency DAG, directly matches MOAD-0001 model | arXiv 1701.05975 |
cuda-cudasift-orb-ransac | ~60× SIFT CPU→GPU (11 fps 1920×1440); 1.2 ms on GTX 1060; ORB 11.3× | GTX 1060+ | unsandbox MEDIUM (visual evidence pipeline for incident reports) | CudaSift |
cuda-cudasw-gasal2 | CUDASW++4.0 16.2× over v3.0; 134× over ADEPT; 5.71 TCUPS on H100; GASAL2 packing 750× vs NVBio | H100 (TCUPS) | undefect MEDIUM (binary-diff & patch-similarity at scale: SW reduces to opcode-sequence diff) | CUDASW++4.0 |
cuda-loopy-bp-mrf | 45× over CPU LBP for stereo MRF inference | GTX 280-class+ | undefect HIGH — LBP substrate for FuzzingBrain-style probabilistic program analysis | arXiv 2509.22337 |
cuda-sgm-stereo | 42 fps at 640×480 with 128 disparities on Tegra X1; 46 fps on discrete GPUs | Tegra X1 / discrete | unsandbox MEDIUM (embedded ARM+CUDA matches our edge node profile) | arXiv 1610.04121 |
cuda-hungarian-lap | 10–50× class; 400 M-variable LAP in ~13 s | NVIDIA GPU | unsandbox HIGH — workstation-to-queue balancing per Prime Mission; defect-cluster ↔ patch-bundle assignment for undefect | ScienceDirect |
cuda-msm-bls12-381 | 27.86× over Pippenger (RELIC) AVX baseline; 60% of Groth16 prover time on single GPU | A100 / RTX 4090 | ECDSA HIGH — Pippenger bucket sort + multi-G1 arithmetic shares branchless modmul shape with our reversible secp256k1 inner loop | SimdMSM TCHES |
cuda-pdwt-lifting | 15.9× over best optimized CPU DWT (lifting scheme) | GTX / Tesla | unsandbox MEDIUM (audio-IPC payload analysis, BT signal denoising) | PDWT |
cuda-tensornet-contract | 8–20× vs CuPy on contraction; tensor QR ~100× vs Xeon 8480+; tensor SVD ~10× | A100 | ECDSA HIGH — alternative to stabilizer/kickmix sim path; MPS/PEPS evaluates reversible secp256k1 circuits beyond Clifford | cuTensorNet |
cuda-ega-gpu-aggregation | 6.45–29.12× over CPU multi-pass EGA; group-by hash 19.4× | NVIDIA GPU | undefect HIGH — defect-corpus aggregation at planetary scale; unsandbox HIGH — telemetry queue aggregation | VLDB Top-k EGA |
cuda-bicgstab-ilu-spmv | SpTRSV 10.7×; ILU0 BiCGSTAB 3.2× vs cuSPARSE on MI210; GMRES(30) block-ISAI 1.4–6.9× | V100 / MI210 | ECDSA MEDIUM (sparse LA over GF(p) underpins lattice / index-calc); undefect MEDIUM (spectral analysis on DAG) | arXiv 2508.04917 |
cuda-icicle-snark-groth16 | ICICLE-Snark fastest Groth16 today; Mina GPU 3× over libsnark; NTT 91% of prover at large sizes | RTX 4090 / A100 | ECDSA MEDIUM (zk + MSM stack shares finite-field discipline); undefect MEDIUM (zk-prover defect scanning) | ICICLE-Snark |
Wave 3 filter-outs: AMGX algebraic multigrid (2–5×), GROMACS GPU (2–3×), NVOFA optical flow (7–10× borderline, dedicated hardware unit), Junction-tree BP per-message (0.68–9.18×), batched L-BFGS (134× single-case, not generalized). All below 10× or insufficiently general; revisit when shape changes.
Skipped — revisit when shape changes
- Argon2 / scrypt: ~1000 H/s on Tesla K20X is the whole point of memory-hard KDFs. Not a speedup story; only worth listing in an attack-surface doc.
- cuRAND alone: already bundled inside Monte Carlo + ChaCha20 forms; not a wire-protocol form by itself.
- GP regression / variational inference: current GPU wins are 2–4×, below Pareto-frontier threshold for public catalog.
- Generic ML inference: out of scope for this catalog — covered better by upstream frameworks.
- cuda-batched-mcts: 25–40× on Go-style rollouts; wrong shape for our current candidate search.
- cuda-faiss-ann: 5–12× over CPU FAISS; no embedding workload today.
Why a form earns its slot
A form is GPU-worth-it when at least one of:
- Embarrassingly parallel. N independent items, no cross-item dependency. SHAKE fan-out, batched mod-mul, bulk point-add — each thread owns one item.
- Dense, branch-free inner loop. Same operation on every element. Matrix-vector, convolution, bit-twiddling sweeps.
- Reduction-friendly. Tree-reduce / prefix-sum / parallel-scan patterns GPU hardware accelerates natively.
- Big batch amortizes fixed kernel overhead. Our
cuda-sim-ops-binshows ~5 s kernel overhead; only worth it past ~115 batches.
When none of these hold, do not force the problem onto GPU. Find a different decomposition: parallelize on a different axis (per-candidate instead of per-shot), or stay on CPU & fan out across fleet hosts.
Recommended build order
- A —
cuda-secp256k1-batched-mul: biggest immediate win. VanitySearch's CUDA secp256k1 kernel hits 6.5 Gkeys/s on a 4090; bend gets a GPU-rate point-mul oracle for candidate validation. - D —
cuda-clifford-stabilizer: the right axis fix for our 1.07×cuda-sim-ops-binceiling. Reshape circuit-sim per-candidate-parallel; targets a Clifford fragment via STABSim-style tableau. - B —
cuda-bignum-cgbn: foundational layer. Generic 256-bit vocabulary lumbda calls without committing to a curve.
Forms E, C, G follow once A–D give us measured numbers on our hardware. F & below revisit when our shape changes.
Source & specs
examples/cuda-fanout/ — wire contract, daemon protocol, bench data, per-tier integration sketch.
CATALOG.md — canonical source for form metadata; this page renders from the same data.