Skip to content

Fused pipelines

Examples assume an initialized engine; see getting started.

Compile and run a plan

Compile explicit operation nodes once and reuse them for synchronous execution:

ts
const pipeline = engine.compilePipeline({
  dtype: 'f32',
  nodes: [
    { op: 'mul', operand: 2 },
    { op: 'add', operand: 1 },
    { op: 'clamp', lower: 0, upper: 8 },
  ],
})
const input = new Float32Array([-2, 0, 3, 5])
pipeline.run(input) // [0, 1, 7, 8]
pipeline.run(input, [], { out: input })

engine.scope(arena => {
  const samples = arena.f32.from(new Float32Array([-2, 0, 3, 5]))
  return arena.runPipeline(pipeline, samples, [], { out: samples }).toArray()
})

const serialized = JSON.stringify(pipeline.plan)
const restored = engine.compilePipeline(JSON.parse(serialized))
console.log(pipeline.capability, engine.getPipelineCacheInfo())

Inputs and supported operations

Each node consumes the previous result. Binary operands can be constants or { input: 0 }, referring to the first extra vector in run(input, [extra]). Extra vectors must have the same dtype and length. Slots start at zero without gaps, with at most 8 extras and 64 nodes. Default outputs are independent; exact aliases with any input are allowed, and partial overlaps fail before writing.

All eight numeric dtypes support add/sub/mul/square/min/max/clamp. Signed types also support abs/neg; floats additionally support div. Other operations are rejected. Every node keeps its original precision, integer wrap and IEEE rules; there is no FMA, reordering or fast-math. f32 uses scalar or the selected explicit SIMD kernel; other types report scalar fallback. Constant mul/add/clamp chains have a specialized loop, while other supported chains use a bounded interpreter. Both traverse the input once without full-size intermediate arrays.

Serialization and lifetime

The immutable plan records its format, operation version, dtype and strict precision. Special constants use JSON-safe strings: NaN, Infinity, -Infinity, and -0. Each engine caches at most 32 normalized plans using LRU; evicted objects remain usable until engine disposal. Plans are portable data; compiled objects and resident handles belong to their engine. The cache stores validated bytecode, with bounded Rust decoding on each invocation. Wasm resident execution transfers only small instruction and pointer tables per run. See the pipeline contract for exact validation rules and performance guidance for choosing workloads.

Released under the MIT License.