S-exp GPU
All pages
Docs · The command lineMarkdown

Probe a tensor expression

sexpgpu probe [<file.sx>] --expr FORM evaluates a small tensor expression with the reference interpreter. The file supplies definitions and initialized models. No loader, optimizer, training contract, GPU, or metric service is required.

Arguments and output

argumentbehavior
<file.sx>loads the file, then evaluates the expression in its environment; without one, the expression sees the prelude and a require adds a library
--expr FORMexactly one expression returning a tensor or multiple values of tensors
--variant V, --set k=vselect the file's knobs before loading it
--jsonprints all tensor values in a structured document
--max-elements Ncaps the sum of intermediate and output tensor elements at N; default 100000, positive integer

Text output is each tensor's shape, dtype, and first 64 row-major values, written as that dtype writes them. JSON output is one line with every value:

$ sexpgpu probe --expr '(iota [3] :dtype :i64)' --json
{"kind":"probe","device":"reference","outputs":[{"name":"output.0","shape":[3],"dtype":"i64","values":[0,1,2]}]}

Integers and booleans retain their JSON types. Nonfinite floats are the strings "NaN", "Infinity", and "-Infinity".

A relative require in the expression resolves beside the file, or against the working directory without one. The expression sees the file's private and imported bindings, including private functions used by imported macros; its own definitions do not become file bindings. Nothing is read from standard input.

Supported state and limits

The probe initializes the parameters and buffers of models bound at the file's top level; a buffer initializer reads its parameters' starting values, as in a run. Parameter paths and random initializer streams match ordinary compilation. defrun :seed supplies the seed when present; the default is zero. A parameterized model constructed inside the expression has no root and is rejected. A parameter with :load or with-loaded requires a run.

The result must be tensors. values returns several tensors. Metrics, counters, guards, and runtime context inputs are rejected. The probe does not apply the run's precision policy, autodiff, or optimizer passes; explicit casts and gradient execute as written.

The evaluation work limit covers the loaded file and expression together. Before interpreting, the probe counts the elements of every node of every used initializer and of the expression graph, unused intermediates and the returned outputs included; --max-elements bounds that count, not time: a matrix product does more work than its element count. Keep probe dimensions small.

Examples

affine.sx has a model and no training contract:

(defknobs (width 3 "input width") (gain 2.0 "input value"))
(defmodel affine (&key (dim 3))
  (defparam weight (+ (cast (iota [dim]) :f32) 1.0))
  (defparam bias (full [dim] 0.5))
  (lambda (x) (+ (* x weight) bias)))
(defvar model (affine :dim width))

Its weight is [1 2 3] and its bias [0.5 0.5 0.5]:

$ sexpgpu probe affine.sx --expr '(model (full [width] gain))'
output.0: [3] f32 [2.5, 4.5, 6.5]
$ sexpgpu probe affine.sx --set width=4 --expr '(model (ones [width]))' --json

A library function and a derivative can also be checked without a file:

$ sexpgpu probe --expr '(progn (require "sexpgpu/nn" rms-norm) (rms-norm (full [2 3] 2.0) :eps 0.0))' --json
$ sexpgpu probe --expr '(let* ((x (cast (iota [3]) :f32)) (y (sum (* x x)))) (values y (gradient y x)))'
output.0: [] f32 [5.0]
output.1: [3] f32 [0.0, 2.0, 4.0]

Diagnostics use the standard codes. --json emits the same diagnostic array as check --json, and failures exit with code 1.