Guides

Execution model

TypeNN owns the Tensor graph and its meaning. TypeShade owns kernel compilation and program execution.

Tensor calls build a deferred graph

Operations such as matmul(), add(), and relu() do not compute. Each one records a node that holds a TypeShade kernel function, the input Tensors, the scalars the kernel takes by value, and the gradient rule.

\1 title="A small Tensor graph" file="model.ts" code=const input = device.tensor(values, { shape: [batch, features] }); const logits = input.matmul(weights).add(bias); const output = logits.relu(); // This is the materialization boundary. const result = await output.data(); />

Each data() call runs one fuse scope

When data() is requested, TypeNN collects the nodes under the Tensor that have no array yet, makes one resident array for each, and uploads each leaf. It then calls TypeShade fuse with a body that calls each node's kernel function in graph order, and reads the Tensor back once.

TypeNN

Shape checks · graph nodes · autograd · kernel functions

TypeShade

fuse scope plan · dispatches · backend tiers · runtime resources

Backends and limits

TierSelectionCurrent note
CPUAuto fallback or explicitRuns the same kernel functions, one call after the other. Suited to correctness and fallback.
WebGPUAuto or explicitNative GPU compute when the browser exposes an adapter. Elementwise chains fuse into one dispatch.
WebGL2ExplicitRuns the same kernel functions apart, one call after the other. A call it cannot run goes to the CPU tier.

One active TypeNN Device is supported per JavaScript context because TypeShade call-layer configuration is process-global.

Read the plan in device.lastReport

The compiler puts consecutive kernel calls in one dispatch when TypeShade's fusion rules hold. On WebGPU, a.add(b).mul(c).relu() runs as one dispatch. A reduction, a read at another index, or too many storage buffers starts a new dispatch. After a read, device.lastReport shows the tier, the dispatches, the submissions, and the groups of calls. On the CPU tier the report has no dispatches and one group for each call.

Read how a read runs ↗