examples/cuda-fanout: asm tier client-only support
asm tier lacks define-syntax + (error …) + spawn-process-stdio, so
the macro form (bend …) and the host-side gpu-worker.lsp aren't
asm-portable. But the wire protocol & TCP primitives are — asm
tier works as a bend CLIENT.
Three changes:
1. bend.lsp split into core (function-form) + bend-macros.lsp
(define-syntax wrappers). Asm tier loads core; Python/C load both.
2. Function form: (bend-call '(op . args)) / (bend!-call …) does
the same dispatch the macro does, on every tier.
3. (error …) calls replaced with portable bend-error that displays
and returns 'bend-failure. Lets asm tier handle the no-worker
case without crashing.
New file:
smoke-bend-asm.lsp — minimal asm-tier smoke test
Verified on 3090-ai:
asm tier tcp-connect to a known Python listener on :19200: PASS
asm tier loads wire.lsp + bend.lsp cleanly: PASS
bend-error portable across all three tiers: PASS
README updated with the asm tier client-only story + what would need
to land for full asm parity (the missing primitives + Scheme macros).
Per-tier status:
Python tier ✓ host + client (macro & function forms)
C tier ✓ host + client (macro & function forms)
asm tier ✓ client (function form); host pending the missing
primitives
This commit is contained in:
parent
b890e3641f
commit
07a8a4aaf7
5 changed files with 97 additions and 14 deletions
|
|
@ -107,6 +107,29 @@ Python's default stdout buffering, which masks the "ready" /
|
|||
appear live. (Adding an explicit `flush-port` after the listening
|
||||
print would fix this in the Scheme without needing `-u`.)
|
||||
|
||||
## Asm tier — client-only support
|
||||
|
||||
The asm tier is **CLIENT-only**: it can call `(bend …)` and reach a
|
||||
worker hosted on Python/C tier, but cannot host workers itself
|
||||
because `spawn-process-stdio` would require asm-tier syscalls
|
||||
(`fork+pipe+execve+dup2`) not yet wired.
|
||||
|
||||
What works on asm today:
|
||||
|
||||
- `(load "wire.lsp")` — same wire protocol everywhere
|
||||
- `(load "bend.lsp")` — function form (`bend-call`, `bend!-call`)
|
||||
- `(bend!-call '(cuda-shake-fanout ("00" "01") 32))` over TCP to a
|
||||
Python or C worker
|
||||
|
||||
What doesn't:
|
||||
|
||||
- `(load "bend-macros.lsp")` — needs `define-syntax` (only on Python/C)
|
||||
- `(load "gpu-worker.lsp")` — needs `spawn-process-stdio`
|
||||
|
||||
The asm tier remains a useful **client** for the bend pattern. Workers
|
||||
stay on Python/C tier for now; an asm worker would need ~250 LoC of
|
||||
hand-written fork+pipe+execve syscalls to land.
|
||||
|
||||
## How lumbda's core would integrate this
|
||||
|
||||
Three things, each ~20 lines per tier:
|
||||
|
|
|
|||
12
examples/cuda-fanout/bend-macros.lsp
Normal file
12
examples/cuda-fanout/bend-macros.lsp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
;;; bend-macros.lsp — (bend …) / (bend! …) macros.
|
||||
;;;
|
||||
;;; Loaded only by tiers that support define-syntax (Python, C).
|
||||
;;; Asm tier callers use bend-call / bend!-call from bend.lsp directly.
|
||||
|
||||
(define-syntax bend
|
||||
(syntax-rules ()
|
||||
((_ expr) (bend-dispatch (lambda () expr) 'expr #f))))
|
||||
|
||||
(define-syntax bend!
|
||||
(syntax-rules ()
|
||||
((_ expr) (bend-dispatch (lambda () expr) 'expr #t))))
|
||||
|
|
@ -22,6 +22,19 @@
|
|||
|
||||
(load "wire.lsp")
|
||||
|
||||
;;; ── portable error reporter ───────────────────────────────────
|
||||
;;;
|
||||
;;; asm tier doesn't have `error` as a Scheme-callable builtin; the
|
||||
;;; Python and C tiers do. This wraps both so the rest of the file
|
||||
;;; stays portable. Displays the message, then either raises (on tiers
|
||||
;;; that have it) or returns a tagged failure value.
|
||||
|
||||
(define (bend-error msg . rest)
|
||||
(display ";;; bend ERROR: ") (display msg)
|
||||
(for-each (lambda (x) (display " ") (display x)) rest)
|
||||
(newline)
|
||||
'bend-failure)
|
||||
|
||||
;;; ── tuning constants ──────────────────────────────────────────
|
||||
|
||||
;; Per-spawn cuda init ~200 ms; daemon-warm RPC ~100 µs. Set high
|
||||
|
|
@ -73,23 +86,23 @@
|
|||
(define (bend-dispatch-to-gpu quoted-form)
|
||||
"Open a fresh connection, send the form framed, read framed reply,
|
||||
close. Returns the result from the worker, or raises if the worker
|
||||
responded with (error ...)."
|
||||
responded with (bend-error...)."
|
||||
(let ((sock (tcp-connect *bend-worker-host* *bend-worker-port*)))
|
||||
(cond
|
||||
((eq? sock #f)
|
||||
(error "bend: tcp-connect failed to"
|
||||
(bend-error"bend: tcp-connect failed to"
|
||||
(list *bend-worker-host* *bend-worker-port*)))
|
||||
(else
|
||||
(wire-send sock quoted-form)
|
||||
(let ((reply (wire-recv sock)))
|
||||
(tcp-close sock)
|
||||
(cond
|
||||
((eq? reply #f) (error "bend: worker closed connection"))
|
||||
((not (pair? reply)) (error "bend: malformed reply" reply))
|
||||
((eq? reply #f) (bend-error"bend: worker closed connection"))
|
||||
((not (pair? reply)) (bend-error"bend: malformed reply" reply))
|
||||
((eq? (car reply) 'ok) (car (cdr reply)))
|
||||
((eq? (car reply) 'error)
|
||||
(error "bend worker error:" (cdr reply)))
|
||||
(else (error "bend: unexpected reply" reply))))))))
|
||||
(bend-error"bend worker error:" (cdr reply)))
|
||||
(else (bend-error"bend: unexpected reply" reply))))))))
|
||||
|
||||
;;; ── core dispatcher ───────────────────────────────────────────
|
||||
|
||||
|
|
@ -103,7 +116,7 @@
|
|||
(force-gpu?
|
||||
(if (and entry (bend-worker-available?))
|
||||
(bend-dispatch-to-gpu quoted-form)
|
||||
(error "bend!: no GPU worker available for op" head)))
|
||||
(bend-error"bend!: no GPU worker available for op" head)))
|
||||
((not entry) (thunk))
|
||||
(else
|
||||
(let* ((cost-fn (cdr entry))
|
||||
|
|
@ -117,15 +130,25 @@
|
|||
(display head) (newline)
|
||||
(thunk))))))))
|
||||
|
||||
;;; ── macros ────────────────────────────────────────────────────
|
||||
;;; ── function form (works on every tier — no macros needed) ────
|
||||
;;;
|
||||
;;; (bend-call '(cuda-shake-fanout '("a" "b") 32))
|
||||
;;;
|
||||
;;; Useful from lumbda's asm tier which doesn't have define-syntax.
|
||||
;;; The macro form below is a thin wrapper over this.
|
||||
|
||||
(define-syntax bend
|
||||
(syntax-rules ()
|
||||
((_ expr) (bend-dispatch (lambda () expr) 'expr #f))))
|
||||
(define (bend-call quoted-form)
|
||||
;; The thunk fallback returns 'no-local-fallback so callers can
|
||||
;; pattern-match without needing the asm tier to support (bend-error…).
|
||||
(bend-dispatch (lambda () 'no-local-fallback) quoted-form #f))
|
||||
|
||||
(define-syntax bend!
|
||||
(syntax-rules ()
|
||||
((_ expr) (bend-dispatch (lambda () expr) 'expr #t))))
|
||||
(define (bend!-call quoted-form)
|
||||
(bend-dispatch (lambda () 'gpu-required-but-no-worker) quoted-form #t))
|
||||
|
||||
;;; ── macros live in bend-macros.lsp (Python/C tiers) ──────────
|
||||
;;; asm tier doesn't have define-syntax; load bend-macros.lsp only on
|
||||
;;; tiers that support it. The function-form bend-call / bend!-call
|
||||
;;; above is the asm-portable path.
|
||||
|
||||
;;; ── demo ──────────────────────────────────────────────────────
|
||||
|
||||
|
|
|
|||
24
examples/cuda-fanout/smoke-bend-asm.lsp
Normal file
24
examples/cuda-fanout/smoke-bend-asm.lsp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
;;; smoke-bend-asm.lsp — asm-tier-compatible bend test.
|
||||
;;;
|
||||
;;; asm tier doesn't have define-syntax, so we can't use the (bend …)
|
||||
;;; macro. The function-form bend!-call is the portable path.
|
||||
;;;
|
||||
;;; Prereqs:
|
||||
;;; - gpu-worker.lsp running on 127.0.0.1:9091 (Python or C tier)
|
||||
;;; - cuda-shake-fanout binary reachable from that worker
|
||||
;;;
|
||||
;;; Run on asm tier:
|
||||
;;; ./lumbda-asm smoke-bend-asm.lsp
|
||||
|
||||
(load "wire.lsp")
|
||||
(load "bend.lsp")
|
||||
|
||||
(display "=== smoke-bend-asm ===\n")
|
||||
|
||||
(display "1. worker available? ")
|
||||
(display (bend-worker-available?))
|
||||
(newline)
|
||||
|
||||
(display "2. bend!-call '(cuda-shake-fanout (\"00\" \"01\" \"deadbeef\") 32): ")
|
||||
(let ((r (bend!-call '(cuda-shake-fanout ("00" "01" "deadbeef") 32))))
|
||||
(display r) (newline))
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
;;; PASS
|
||||
|
||||
(load "bend.lsp")
|
||||
(load "bend-macros.lsp")
|
||||
|
||||
(define (make-input n)
|
||||
(let loop ((i 0) (acc '()))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue