Each gpu-worker.lsp now listens on both wire-TCP (existing :8320) and HTTP/1.1+CORS (new :8321), sharing one handle-request dispatcher. Lets a tab on https://lumbda.com/playground/ POST to its own machine via http://localhost:8321/ — browsers permit localhost from HTTPS origins without TLS, so no proxy, no cert, no fox-owned infra required for the decentralized run-your-own-bend story. main() forks at startup: child runs http-run-loop on :8321, parent keeps existing run-loop on :8320. Adding a new op-head to handle-request exposes it over both transports automatically. Binary modes (BSHK/BCGB/BSCP/BSRT/BSB3) stay wire-only — they exist for native callers who already cache the binary locally; browser callers send S-expression recipes the worker dispatches the same way. Two latent defects fixed to make CPU-only and Python-tier hosts work: - vram-used-mib now file-exists? guards /usr/bin/nvidia-smi. Python tier's spawn-process-stdio raises FileNotFoundError on missing binary, not returning #f as the prior code expected, which crashed every worker on a CPU-only laptop. - fork-self return discriminated via (number? pid) not (eq? pid 0). Python tier's (eq? 0 #f) returns #t because == conflates int 0 with bool False; pre-existing run-loop has the same risk but C/asm tier (identity eq?) masks it for the production case. Phase 2 (server-side factory ops: compile uploaded .lsp recipes into .bin before bending — the foxhop champion-circuit workflow) deferred until authentication lands; today a worker on the public internet would let any caller occupy our GPU. Operational Caddy + DNS proposals in plans/bend-http-deploy.md cover the personal-remote-access endpoint chain (proxy.unturf.com edge → ai.foxhop.net Caddy → 3090-ai:8321) gated by trusted-IP allowlist — applied separately. Also codifies the playground "CSS Grid only, never flexbox" rule in CLAUDE.md: all www/ and wasm/ stylesheets are already grid-only; documenting the invariant so future edits don't drift. Tests: smoke-bend-http.sh — (ping)→(ok pong), unknown-op fallback, OPTIONS CORS preflight — all PASS. Wire path unchanged, verified round-trip via 8-digit-prefix framing.
104 lines
4.6 KiB
Makefile
104 lines
4.6 KiB
Makefile
# shake256-fanout — Makefile.
|
|
#
|
|
# Builds the reference cuda fan-out worker. Each lumbda tier (Python,
|
|
# C, asm) spawns this binary via its existing process-spawn primitive
|
|
# & talks to it through input + output portal files. No tier links
|
|
# against libcudart directly — the CUDA toolchain dependency stays
|
|
# isolated to this directory.
|
|
#
|
|
# Build:
|
|
# make all — compile shake256-fanout (needs nvcc)
|
|
# make test — round-trip test (host + device produce identical
|
|
# SHAKE256 outputs over a small synthetic input set)
|
|
# make bench — bench device vs host throughput at N = 100k
|
|
|
|
NVCC ?= nvcc
|
|
NVCCFLAGS ?= -O3 -arch=sm_86 -Xcompiler="-O3 -Wall -Wextra"
|
|
NVCC_PATH ?= $(shell which nvcc 2>/dev/null || echo /usr/local/cuda/bin/nvcc)
|
|
|
|
all: shake256-fanout cgbn-batch-worker secp256k1-batch-mul radix-sort blake3-fanout
|
|
|
|
shake256-fanout: shake256-fanout.cu
|
|
$(NVCC) $(NVCCFLAGS) -o $@ $<
|
|
|
|
# Wave-2 form `cuda-blake3-tree` — BLAKE3 batched-hash fan-out.
|
|
# One CUDA thread per input, internal Merkle tree walked on-device.
|
|
# Compression primitives vendored from Blaze-3/BLAKE3-gpu (MIT, see
|
|
# vendor/blake3-gpu/{LICENSE,NOTICE}); wire wrapper AGPLv3.
|
|
# Wire: BSB3 request → BSR3 response, distinct from BSHK/BCGB/BSCP/BSRT.
|
|
blake3-fanout: blake3-fanout.cu vendor/blake3-gpu/blake3_device.cuh
|
|
$(NVCC) $(NVCCFLAGS) -o $@ $<
|
|
|
|
blake3-test: blake3-fanout test_blake3_known_answers.py
|
|
python3 -u test_blake3_known_answers.py ./blake3-fanout --quick
|
|
|
|
blake3-test-full: blake3-fanout test_blake3_known_answers.py
|
|
python3 -u test_blake3_known_answers.py ./blake3-fanout
|
|
|
|
blake3-bench: blake3-fanout test_blake3_known_answers.py
|
|
python3 -u test_blake3_known_answers.py ./blake3-fanout --n 1000000 --mode fixed-64
|
|
|
|
# bend form G — batched u64 radix sort via NVIDIA CUB
|
|
# (header-only, ships with CUDA Toolkit so no extra deps).
|
|
# Wire: BSRT (sort-u64-asc) request → BSRR sorted-keys response.
|
|
radix-sort: radix-sort.cu
|
|
$(NVCC) $(NVCCFLAGS) --expt-relaxed-constexpr -o $@ $<
|
|
|
|
radix-sort-test: radix-sort test_radix_sort_known_answers.py
|
|
python3 -u test_radix_sort_known_answers.py ./radix-sort
|
|
|
|
radix-sort-bench: radix-sort test_radix_sort_known_answers.py
|
|
python3 -u test_radix_sort_known_answers.py ./radix-sort --bench
|
|
|
|
# bend form A — secp256k1 batched scalar*G via VanitySearch-Bitcrack
|
|
# vendored GPUMath.h (AGPL-3.0). Per-thread Jacobian double-and-add,
|
|
# per-thread inversion to affine. See vendor/vanity-search-bitcrack/NOTICE.
|
|
NVCCFLAGS_SECP ?= -O3 -arch=sm_86 -Xcompiler="-O3 -Wall"
|
|
secp256k1-batch-mul: secp256k1-batch-mul.cu vendor/vanity-search-bitcrack/GPUMath.h
|
|
$(NVCC) $(NVCCFLAGS_SECP) -o $@ $<
|
|
|
|
secp256k1-test: secp256k1-batch-mul test_secp256k1_known_answers.py
|
|
python3 -u test_secp256k1_known_answers.py ./secp256k1-batch-mul
|
|
|
|
secp256k1-bench: secp256k1-batch-mul test_secp256k1_known_answers.py
|
|
python3 -u test_secp256k1_known_answers.py ./secp256k1-batch-mul --n 100000
|
|
|
|
# bend form B — CGBN bignum batch worker.
|
|
# CGBN_INC must point at a checkout of https://github.com/NVlabs/CGBN/include
|
|
# (header-only consumption; CGBN headers are BSD-3-Clause, our wrapper
|
|
# binary stays AGPLv3 — license noted at the top of cgbn-batch-worker.cu).
|
|
CGBN_INC ?= $(HOME)/CGBN/include
|
|
cgbn-batch-worker: cgbn-batch-worker.cu
|
|
@if [ ! -d "$(CGBN_INC)/cgbn" ]; then \
|
|
echo "ERROR: CGBN headers not found at $(CGBN_INC)/cgbn"; \
|
|
echo " Install: git clone https://github.com/NVlabs/CGBN $(HOME)/CGBN"; \
|
|
echo " Or pass: make cgbn-batch-worker CGBN_INC=/path/to/CGBN/include"; \
|
|
exit 1; \
|
|
fi
|
|
$(NVCC) $(NVCCFLAGS) --extended-lambda -I$(CGBN_INC) -o $@ $<
|
|
|
|
cgbn-test: cgbn-batch-worker test_cgbn_known_answers.py
|
|
python3 test_cgbn_known_answers.py ./cgbn-batch-worker
|
|
|
|
# round-trip: feed (cuda-shake-fanout (output-bytes 32) (inputs ...))
|
|
# through the binary, compare against an external SHAKE256 reference
|
|
# (Python hashlib.shake_256).
|
|
test: shake256-fanout test_roundtrip.py
|
|
@printf '(cuda-shake-fanout\n (output-bytes 32)\n (inputs\n' > /tmp/cf-in.portal
|
|
@printf ' "00"\n "01"\n "deadbeef"\n "%s"\n' \
|
|
"$$(python3 -c 'print("ab" * 100)')" >> /tmp/cf-in.portal
|
|
@printf '))\n' >> /tmp/cf-in.portal
|
|
./shake256-fanout /tmp/cf-in.portal /tmp/cf-out.portal
|
|
python3 test_roundtrip.py /tmp/cf-in.portal /tmp/cf-out.portal
|
|
|
|
bench: shake256-fanout bench.py
|
|
python3 bench.py ./shake256-fanout
|
|
|
|
# Dual-port smoke: gpu-worker.lsp boots on test wire+http port pair,
|
|
# curl POSTs (ping) + OPTIONS preflight, asserts response + CORS.
|
|
# No CUDA deps; runs anywhere lumbda runs.
|
|
smoke-bend-http: gpu-worker.lsp http-listener.lsp smoke-bend-http.sh
|
|
./smoke-bend-http.sh
|
|
|
|
clean:
|
|
rm -f shake256-fanout /tmp/cf-in.portal /tmp/cf-out.portal
|