GizStack
View .mdOpen in ChatGPTOpen in Claude

gizai:llm/engine

the Engine, which runs steps of many sequences at once: its slots, KV pages, scheduler state and devices.

gizlang
import * as Engine from "gizai:llm/engine";

Types

Engine

gizlang
type Engine = { model: Model; slots: i64; context: i64; rows: i64; lengths: Vec<i64>; kv: KvFormat; host: HostState; device: DeviceState; draft: Drafting; queue: Queue; prefix: PrefixCache; pieces: Vec<bytes>; flash: Flash; stages: Vec<Engine>; exact: bool; }

The engine of a model: slots sequences of at most context positions, steps of at most rows rows.

  • model: M51.Model
  • slots: i64
  • context: i64
  • rows: i64
  • lengths: Vec<i64>
  • kv: _gizlang_lib_ai__llm__kvformat.KvFormat
  • host: M50.HostState
  • device: M50.DeviceState
  • draft: M50.Drafting
  • queue: M50.Queue
  • prefix: M50.PrefixCache
  • pieces: Vec<bytes> — The bytes of each token (Tokenizer.tokenBytes), read at the first request with a grammar.
  • flash: M51.Flash
  • stages: Vec<M50.Engine>
  • exact: bool — Linears give x to the GEMMs as the F32 the model computes (rounded to F16 there): no gemm16Kernel, whose 16-bit weights take x in their own type (BF16 for BF16 weights, as other servers' activations). Off: the faster.

Rows

gizlang
type Rows = { tokens: Vec<i64>; slots: Vec<i64>; positions: Vec<i64>; ropes: Vec<i64>; grid: Vec<i64>; own: i64; wanted: Vec<i64>; segments: Vec<i64>; drafts: Vec<i64>; layerInputs?: Vec<f32>; }

A step: per row its token, slot, position and rotary position (or three: grid, Visual.grid), the rows whose logits are wanted, per sequence its slot, first row and row count, and per sequence its drafts (its last rows, see Engine.generate). A row sees the keys before its position, and its own when own is 1 (0: a padding row, see Engine.padding).

  • tokens: Vec<i64>
  • slots: Vec<i64>
  • positions: Vec<i64>
  • ropes: Vec<i64>
  • grid: Vec<i64>
  • own: i64
  • wanted: Vec<i64>
  • segments: Vec<i64>
  • drafts: Vec<i64>
  • layerInputs: _gizlang_sdk_core.Option<Vec<f32>>

Visual

gizlang
type Visual = { rows: Vec<i64>; embeds: Vec<f32>; deep: Vec<Vec<f32>>; grid: Vec<i64>; }

Rows of a step that hold no token's embedding (Qwen3-VL's pictures): rows of the step, their embeddings (dim floats a row, in turn), deep the features added to them after each of the first layers (Qwen3-VL's deepstack, rows as embeds), and grid every row's three rotary positions (time, height, width; a text row's three are its position: see ropeTable).

  • rows: Vec<i64>
  • embeds: Vec<f32>
  • deep: Vec<Vec<f32>>
  • grid: Vec<i64>

Functions

partCapacity

gizlang
function partCapacity(rows: i64): i64

The parts the parts buffer holds for an engine of rows rows.

Effects: fail.

partSplits

gizlang
function partSplits(e: Engine, n: i64): i64

The most splits of a row, a power of two of at most SPLITS, whose parts of n rows the parts buffer holds.

Effects: fail.

attendSplits

gizlang
function attendSplits(e: Engine, g: Gpu, n: i64): i64

The splits of a row that attendKernel takes for a step of n rows on g.

Effects: fail, read, write, console, io.

attentionLayers

gizlang
function attentionLayers(a: Arch): i64

The attention layers of a.

Effects: fail.

recurrentLayers

gizlang
function recurrentLayers(a: Arch): i64

The recurrent (non-attention) layers of a.

Effects: fail.

drafting

gizlang
function drafting(e: Engine): bool

Whether generate drafts with the model's MTP layer (on a model in stages, the last stage's: headOf).

Effects: fail.

looksUp

gizlang
function looksUp(e: Engine): bool

Whether generate drafts by lookup (a model without an MTP layer; not on an NPU, which reads a token a step).

Effects: fail.

mtpOn

gizlang
function mtpOn(e: Engine): bool

Whether this engine's own model runs the MTP layer: its buffers and KV pages hold it.

Effects: fail.

poolLayers

gizlang
function poolLayers(e: Engine): i64

Attention layers in the KV pages: the model's, and its MTP layer's when generate drafts with it.

Effects: fail.

pageBytes

gizlang
function pageBytes(e: Engine): i64

The bytes of a KV page: keys and values of PAGE positions in each pool layer.

Effects: fail.

layerArch

gizlang
function layerArch(e: Engine, wide: bool): Arch

The Arch of a layer's attention: its head shape's with its region of the KV pages (kvViews).

Effects: fail.

hostWidth

gizlang
function hostWidth(e: Engine, l: i64): i64

Floats of a position's keys (or values) in pool layer l (Layer.at) on the host.

Effects: fail.

shapeLayers

gizlang
function shapeLayers(e: Engine, wide: bool): i64

The pool layers of the wide head shape, or of the other one.

Effects: fail.

widestInput

gizlang
function widestInput(a: Arch): i64

Floats of the widest input of a linear and of the widest output.

Effects: fail.

widestOutput

gizlang
function widestOutput(a: Arch): i64

Floats of the widest output of a linear, rounded up to 16.

Effects: fail.

attentionWidth

gizlang
function attentionWidth(a: Arch): i64

Floats of the widest attention output of a row: heads times the widest head.

Effects: fail.

wantedRows

gizlang
function wantedRows(e: Engine): i64

The most rows of a step whose logits a GPU engine gives.

Effects: fail.

forward

gizlang
function forward(e: mut Engine, sys: System, tokens: Vec<i64>, slots: Vec<i64>, wanted: Vec<i64>, drafts: Vec<i64> = [], taps: Vec<i64> = [], padding: i64 = -1, visual: Option<Visual> = undefined): Forward throws string

drafts: per slot its drafts in the step, its last rows (none when empty; see Engine.step). taps: the layers after which the step keeps the residual stream (Engine.hidden). padding: the rotary position of the step's one row, which then sees the slot's keys but not its own and leaves the slot as it was (Engine.padding; -1: none).

Effects: fail, read, write, console, io.

interleaved

gizlang
function interleaved(states: Vec<Vec<f32>>, rows: i64, dim: i64): Vec<f32>

Per row the rows of each of states (rows of dim floats each), in turn.

Effects: fail.

embedded

gizlang
function embedded(e: Engine, sys: System, tokens: Vec<i64>): Vec<f32> throws string

The embedding rows of the tokens, read from the model file.

Effects: fail, io.

ropeTable

gizlang
function ropeTable(a: Arch, positions: Vec<i64>, grid: Vec<i64> = [], table: i64 = GLOBAL): Vec<f32>

The rotary cosines and sines of each row's position in rotary table table (GLOBAL, LOCAL): rotary/2 pairs a row, times Arch.ropeScale on the global table, of the long frequencies from Arch.longFrom on. With a grid (three positions a row: time, height, width) frequency j takes height's where j % 3 is 1 and width's where it is 2, within 3 times their sections (a.sections), time's elsewhere: Qwen3-VL's interleaved multimodal rotary positions.

Effects: fail.

Methods

Engine.reset

gizlang
function Engine.reset(self: mut Engine, slot: i64): void

Empties a slot for a new sequence.

Effects: fail, read, write, console, io.

Engine.length

gizlang
function Engine.length(self: Engine, slot: i64): i64

Positions held by a slot.

Effects: fail.

Engine.step

gizlang
function Engine.step(self: mut Engine, sys: System, tokens: Vec<i64>, slots: Vec<i64>, wanted: Vec<i64>, drafts: Vec<i64> = [], visual: Option<Visual> = undefined): Vec<f32> throws string

Reads tokens into their slots (the rows of a slot together and in order, after what the slot holds) and returns the logits of the rows wanted (vocab floats each, in that order). On an engine that drafts (Engine.depth), a slot's last drafts[slot] rows (none when drafts is empty) are drafts of the tokens after its row before them: they wait for Engine.accept, which the slot's next step needs first. With visual, some rows are a picture's (Visual, as Engine.hidden), and every row takes its three rotary positions from it.

Effects: fail, read, write, console, io.

Engine.accept

gizlang
function Engine.accept(self: mut Engine, slot: i64, kept: i64): bool throws string

Keeps the first kept of a slot's drafts of its last step and drops the others.

Effects: fail, read, write, console, io.

Engine.hidden

gizlang
function Engine.hidden(self: mut Engine, sys: System, tokens: Vec<i64>, slots: Vec<i64>, layers: Vec<i64> = [], visual: Option<Visual> = undefined): Vec<f32> throws string

Reads tokens into their slots as Engine.step does and returns the residual stream of each row after each of layers (counted from 1; none: the model's last), dim floats a row and layer: Hugging Face's hidden_states[l] for each l, before the final norm (Hugging Face norms the whole model's last hidden state). With visual, some rows are a picture's (Visual), not their tokens' embeddings.

Effects: fail, read, write, console, io.

Engine.padding

gizlang
function Engine.padding(self: mut Engine, sys: System, slot: i64, token: i64, position: i64, layers: Vec<i64> = []): Vec<f32> throws string

The hidden states (as Engine.hidden) of one row of token at rotary position position that sees the keys of the slot's tokens but not its own, and leaves the slot as it was: a padding row of a Hugging Face batch, whose mask hides the padding keys from every row. Every padding row of a sequence is this one row (FLUX.3 reads Qwen3-VL's, at position 1). Models of attention layers only.

Effects: fail, read, write, console, io.

Engine.expertCache

gizlang
function Engine.expertCache(self: Engine): ExpertCache

The expert cache counts of the engine.

Engine.generate

gizlang
function Engine.generate(self: mut Engine, sys: System, requests: Vec<Request>): Vec<Vec<i64>> throws string

Generates for every request and returns each one's new tokens (without the stop token): Engine.add of each, then Engine.advance until none is in turn.

Effects: fail, read, write, console, io.

Engine.warm

gizlang
function Engine.warm(self: mut Engine, sys: System): bool throws string

Runs once each kind of step a server meets first: a long prompt read in parts, a prompt of each size its linears tune by (delta.giz linear: powers of 2 below GEMM_ROWS, then 128 rows each up to the step's rows), then 1 to slots sequences that read a prompt and write tokens. The first run of a step shape compiles, tunes and records its kernels (seconds for a large model), so a server warms before it takes requests.

Effects: fail, read, write, console, io.

Engine.add

gizlang
function Engine.add(self: mut Engine, request0: Request, mark: i64 = 0, head: i64 = 0): i64 throws string

Puts a request in turn and returns its id, which Engine.advance's results name. A free slot that holds the start of its prompt (an earlier request's prompt and answer) takes it and reads only the rest; so does a slot that takes back such a start from the host, where a slot keeps what it held when another request takes it (Prefix). After mark tokens of the prompt (0: none) its slot also keeps the recurrent states, so a later prompt that starts with those tokens but not with all the slot read reads only the rest too; for a chat that is where its messages end (Model.chatTokens). The prompt's first head tokens (0: none; for a chat its system turn with the tools), cut to whole KV pages and when at least SHARED_MIN, become a start that later prompts share (Shared): a slot whose prompt starts with it reads only the rest, and on a GPU all such slots read one copy of its keys and values.

Effects: fail.

Engine.cancel

gizlang
function Engine.cancel(self: mut Engine, id: i64): bool

Takes a request out of turn; false when it is not in turn (it ended). Its slot keeps what it read.

Effects: fail.

Engine.busy

gizlang
function Engine.busy(self: Engine): bool

Whether requests are in turn.

Effects: fail.

Engine.advance

gizlang
function Engine.advance(self: mut Engine, sys: System): Vec<Progress> throws string

One step of the requests in turn, and what each gained. First free slots take waiting requests (Engine.add). The step reads the next token of every generating sequence and, in the rows left, the next piece of the prompts not read yet. When the KV pool has no room for the step, a free slot gives its pages, else the request that came last waits again from where it is (its prompt and answer so far).

A drafting engine (Engine.depth) also reads each generating sequence's drafts of the tokens after that: each row judges the draft after it (kept when it is the token picked; when sampling, kept with its probability and otherwise a token other than it is picked, which gives the same distribution as without drafts) up to the first rejected, and when all are kept the last row gives one more token, so a step reading weights once can give 1 + depth tokens. The step reads them as drafts (Engine.step) and keeps those judged right (Engine.accept). Then the MTP layer reads every row kept, with the token after it, and where drafts gave tokens faster for as many generating sequences (EXPLORE), drafts after each sequence's last; it reads each draft again, with its own hidden state for it, for the next.

Effects: fail, read, write, console, io.

Engine.complete

gizlang
function Engine.complete(self: mut Engine, sys: System, prompt: string, limit: i64, s: Sampling): string throws string

The text the model writes after prompt (special tokens in it read as such), at most limit tokens.

Effects: fail, read, write, console, io.

Constants

SPLITS

gizlang
const SPLITS = 16

Splits of the keys that attention reads at once: a step by tiles takes partSplits; attendKernel (fewer rows) more, up to two waves of its workgroups on the GPU (Gpu.slots; ATTEND_GROUPS where the driver does not say) within the parts buffer (partCapacity), each split of at least SPAN keys. (One row's 4 kv heads in 16 splits kept 64 workgroups on 76 multiprocessors: 60K keys took 0.8 ms a layer, nine times what the memory takes to read them.)

SPAN

gizlang
const SPAN = 64

The fewest keys of a split.

ATTEND_GROUPS

gizlang
const ATTEND_GROUPS = 512

The workgroups of attention's two waves where the driver does not say (Gpu.slots).

PART_ROWS

gizlang
const PART_ROWS = 256

The parts buffer (W_PARTS) holds SPLITS parts of PART_ROWS rows (or of the engine's rows when fewer), and at least one part of each row: a step of more rows takes fewer splits a row (partSplits).

GEMV_ROWS

gizlang
const GEMV_ROWS = 8

The most rows a GPU linear reads its weights for at once on CUDA cores; from GEMM_ROWS rows a linear runs on matrix cores where the GPU has them.

GEMM_ROWS

gizlang
const GEMM_ROWS = 32

The fewest rows a linear runs on matrix cores for.

EXPLORE

gizlang
const EXPLORE = 256

An engine drafts with an MTP layer, or by lookup without one, where that gives tokens faster (Engine.paces): drafting pays where the GPU waits on weights (few sequences), and a step with drafts reads more rows and reads and writes a slot's recurrent states once more (replayDrafts). Every EXPLORE steps each count of sequences runs the other way twice, to measure it again.

DRAFTS

gizlang
const DRAFTS = 8

The tokens an engine drafts per sequence and step by default: the n-th draft is kept less often than the one before, and each costs a row (and with an MTP layer a step of it and the head).

DRAFT_SHARE

gizlang
const DRAFT_SHARE = 8

A draft reads one DRAFT_SHARE-th of the head's blocks of 16 rows (as FR-Spec, arXiv 2502.14856, which takes the frequent tokens of a corpus): the first half of them always (a BPE vocabulary's first ids are its frequent tokens), the other half the last blocks of the tokens the engine read, so the language of a prompt comes in with it.

RECORDINGS

gizlang
const RECORDINGS = 64

The most step shapes an engine keeps recorded.

RECORD_ROOM

gizlang
const RECORD_ROOM = 50_331_648

The device memory free before a new recording at least (one of q27-4's steps took 6 MiB).