GizStack
View .mdOpen in ChatGPTOpen in Claude

gizai:dit

the diffusion transformer's block that every generation model shares (MiniMax H3, LTX-2.5, FLUX.3, Z-Image, Krea 2, OmniVoice). A block is an AdaLN transformer layer: modulated norms, attention over a packed sequence with rotary coordinates, and a gated MLP. This module owns its weights as stored (BF16, ComfyUI's INT8 ConvRot or FP8, H3's W4, with LoRA adapters), the packed sequence, the time embedding, the host reference and the GPU kernels, and the staging of a block's weights in pinned memory for streamed models.

gizlang
import * as Dit from "gizai:dit";

Types

Arch

gizlang
type Arch = { family: string; hidden: i64; layers: i64; refiner: i64; heads: i64; head: i64; ffn: i64; latents: i64; audio: i64; patch: Vec<i64>; textDim: i64; freqDim: i64; timeHidden: i64; timeDim: i64; eps: f64; qkEps: f64; finalEps: f64; }

What a model computes, as its family's recipe reads config.json.

  • family: string
  • hidden: i64
  • layers: i64
  • refiner: i64
  • heads: i64
  • head: i64
  • ffn: i64
  • latents: i64
  • audio: i64
  • patch: Vec<i64>
  • textDim: i64
  • freqDim: i64
  • timeHidden: i64
  • timeDim: i64
  • eps: f64
  • qkEps: f64
  • finalEps: f64

Block

gizlang
type Block = { w: Vec<Tensor>; bias: Vec<Tensor>; codes: Vec<W4>; lora: Vec<Tensor>; }

One block's weights, by the indexes below: its 4 linears [out, in] as stored, then its 4 norms (f32). On a GPU a linear is BF16, or W4 when codes holds the decoding of each (w then holds its codes); on the host it is f32 values (W4: the code bytes as numbers). bias holds the linears' biases (f32, one per output) or none; lora the A ([rank, in]) and B ([out, rank]) of each linear's LoRA, applied beside it (BF16 on a GPU; a W4 block's A there is INT8 as N.int8Rows makes it, its row scales in B's columns), or none. UP's rows are the gate's and the up projection's in pairs (gluRows; SwiGLU: silu(gate) times up).

  • w: Vec<M45.Tensor>
  • bias: Vec<M45.Tensor>
  • codes: Vec<M41.W4>
  • lora: Vec<M45.Tensor>

Sequence

gizlang
type Sequence = { rows: i64; map: Tensor; cos: Tensor; sin: Tensor; exact: bool; group: i64; runs: Vec<i64>; queries: i64; boost: Vec<N.Boost>; }

The rows of one packed sequence: per row its modulation row (map, as f32 values), and the cosines and sines of its rotary angles (per axis its frequencies: H3's t, h and w; FLUX.3's four). Tensors where the block runs. exact: its attention in BF16 where 8-bit matrix cores would take it (the reference of N.attentionRows quantized). boost: keys whose attention weights some queries multiply (N.Boost; Krea 2's edit).

  • rows: i64
  • map: M45.Tensor
  • cos: M45.Tensor
  • sin: M45.Tensor
  • exact: bool
  • group: i64
  • runs: Vec<i64>
  • queries: i64
  • boost: Vec<M36.Boost>

Modulation

gizlang
type Modulation = { attn: Vec<Tensor>; mlp: Vec<Tensor>; }

A block's modulation: shift, scale and gate of the attention, then of the MLP, each [modulation rows, hidden] f32.

  • attn: Vec<M45.Tensor>
  • mlp: Vec<M45.Tensor>

Staged

gizlang
type Staged = { host: Pinned; bytes: i64; parts: Vec<Part>; counts: Vec<i64>; }

A block in page-locked host memory: the bytes of its GPU tensors (blockParts) one after another, each from a multiple of 256, copied to a slot on the GPU ahead of each use (Gpu.copyAhead). counts: Block's lists' lengths.

  • host: M10.Pinned
  • bytes: i64
  • parts: Vec<M23.Part>
  • counts: Vec<i64>

Part

gizlang
type Part = { shape: Vec<i64>; dtype: i64; at: i64; size: i64; host: Tensor; }

A tensor of a staged block: its shape, type, and bytes from at; a host tensor (at -1) stays as host.

  • shape: Vec<i64>
  • dtype: i64
  • at: i64
  • size: i64
  • host: M45.Tensor

Work

gizlang
type Work = { gpu: Gpu; x: Buffer; q: Buffer; s: Buffer; down: Buffer; mid: Buffer; w: Buffer; }

Device memory a block's forward reuses for each chunk of rows (gpuForward): the input rows of a linear (BF16), their INT8 values and scales, its LoRA's down product, SwiGLU, and the INT8 weights of the linears of a W4 block (the largest two).

  • gpu: M10.Gpu
  • x: M10.Buffer
  • q: M10.Buffer
  • s: M10.Buffer
  • down: M10.Buffer
  • mid: M10.Buffer
  • w: M10.Buffer

RefSlot

gizlang
type RefSlot = { first: i64; count: i64; rows: Tensor; record: bool; }

A joint block's reference rows kept across steps (Flux.sample's refresh): their keys and values, [count, 2 width] BF16 in rows. A step that records copies them from rows first to first + count of the block's qkv; the others, which update only the rows before first, put them back there.

  • first: i64
  • count: i64
  • rows: M45.Tensor
  • record: bool

Functions

blockTensors

gizlang
function blockTensors(): Vec<string>

The names of the tensors of a block, in the order of the indexes, and whether each is a linear.

Effects: fail.

gluRows

gizlang
function gluRows(t: Tensor): Tensor

The rows of t ([gate; up] along its first axis, 2 ffn of them) interleaved as UP holds them: gate j at 2 j, up j at 2 j + 1, the pairs of the products' SwiGLU (Lazy.gluInto). Its type unchanged.

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

weightAt

gizlang
function weightAt(sys: System, named: Map<string, Stored>, lora: Map<string, Stored>, name: string, gpu: Option<Gpu>, linear: bool, head: i64 = 0): Tensor throws string

Weight name where it runs (as storedOn), plus its LoRA's update B A when lora has one (W + B A, as the adapters of H3 apply). With head > 0 the weight is a fused QKV projection stored as H3's checkpoints hold it, a head's query, key and value rows together (heads, 3, head); its rows are reordered to all queries, all keys, all values first, the order of the LoRA's rows and of this module's attention.

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

loadBlock

gizlang
function loadBlock(sys: System, named: Map<string, Stored>, lora: Map<string, Stored>, prefix: string, gpu: Option<Gpu>, interleaved: bool): Block throws string

Block prefix (as "blocks.3.") of the checkpoint's tensors on gpu when there is one, with the LoRA lora (an empty map: none): W4 or ComfyUI's INT8 ConvRot as stored when the checkpoint holds it so (w4Block, int8Block), else BF16 with the LoRA merged, its QKV rows a head at a time when interleaved (see weightAt; production's files hold them grouped). ComfyUI's scaled FP8 is quantized to INT8 (Block.quantized) after the merge: as BF16 it would take twice the GPU memory.

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

rawAt

gizlang
function rawAt(sys: System, s: Stored, gpu: Option<Gpu>, dtype: i64): Tensor throws string

A stored tensor of bytes (U8 or I8 codes, or E4M3 scales) where it runs: its bytes as dtype on a GPU, their values on the host (codes as unsigned bytes).

Effects: fail, read, write, io.

runsOf

gizlang
function runsOf(map: Vec<i64>): Vec<i64>

The runs of rows of one modulation row of map: (first, end, row) each, for products that gate in their epilogue (gatedInto).

Effects: fail.

sequence

gizlang
function sequence(positions: Vec<f64>, map: Vec<i64>, inverse: Vec<f32>, gpu: Option<Gpu>, exact: bool = false, group: i64 = 0): Sequence

The sequence of positions (rows of a position per axis: H3's t, h, w) whose rows use modulation rows map, with the rotary inverse frequencies inverse of each axis (H3's rope.inv_freq: head / 8 of them), on gpu when there is one. Rows attend within groups of group rows (0: all of them), as tiles of a VAE.

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

sequenceOf

gizlang
function sequenceOf(positions: Vec<f64>, map: Vec<i64>, inverses: Vec<Vec<f32>>, gpu: Option<Gpu>, exact: bool = false, group: i64 = 0): Sequence

sequence with each axis its own inverse frequencies (Z-Image's 16, 24 and 24).

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

stagedBytes

gizlang
function stagedBytes(b: Block): i64

The bytes of b's staged copy (Staged.bytes) without making it.

Effects: fail.

stage

gizlang
function stage(g: Gpu, b: Block): Staged

Block b in page-locked host memory (Staged): its GPU tensors copied, its host ones kept.

Effects: fail, read, write, io.

silu

gizlang
function silu(x: Tensor): Tensor

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

sinusoids

gizlang
function sinusoids(times: Vec<f64>, dim: i64): Tensor

Rows [cos | sin] of each time times the dim / 2 frequencies 10000^(-i / (dim / 2)), in f32 as diffusers' Timesteps (flip_sin_to_cos) computes them: the timestep embedding of H3 and FLUX.3.

Effects: fail.

workOf

gizlang
function workOf(gpu: Gpu, b: Block, rows: i64, a: Arch): Work

Effects: fail, read, write, io.

linearInto

gizlang
function linearInto(work: Work, x: Tensor, b: Block, i: i64, w: Tensor, out: Tensor, ready: bool = false): void

The product x Wᵀ of linear i (w its weights as weightsOf gives them, [out, in]) on the matrix cores, plus its bias and its LoRA's product (withLora), as BF16 into out (x BF16). A W4 or INT8 linear (codes) takes x through ConvRot to INT8 (N.int8Rows) against its INT8 weights, the product times x's scale and W's: WanGP's asym_w4a8_int8 product.

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

withLora

gizlang
function withLora(b: Block, i: i64, down: Tensor, y: T.Lazy): T.Lazy

Linear i's output y plus its LoRA's B product of down (loraOf's rows), each rounded to BF16 as production stores them; in y's product's epilogue (Product.low), so neither is stored. y alone without a LoRA.

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

quantizedOf

gizlang
function quantizedOf(work: Work, x: Tensor, b: Block, ready: bool): Vec<Tensor>

A W4 or INT8 block's rows of x as INT8 and their scales (work.q, work.s; N.int8RowsInto unless ready), which its linears and a LoRA's INT8 A take; x and x for a BF16 block.

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

productOf

gizlang
function productOf(b: Block, i: i64, w: Tensor, x: Tensor, q: Tensor, s: Tensor): T.Lazy

Linear i's product of x's rows (q and s: quantizedOf's) with its bias, for a chain to go on in its epilogue.

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

loraOf

gizlang
function loraOf(work: Work, x: Tensor, b: Block, i: i64, qs: Vec<Tensor>): Tensor

Linear i's LoRA A product of x (its INT8 rows when A is INT8) into work.down; x itself without a LoRA.

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

gatedInto

gizlang
function gatedInto(work: Work, x: Tensor, y: Tensor, b: Block, i: i64, w: Tensor, gate: Tensor, runs: Vec<i64>, ready: bool): void

x += gate times linear i of y, in a product's epilogue: a product for each run of rows of one modulation row (Sequence.runs), whose gate row the chain takes, so the linear's output is never stored; its LoRA's product too (withLora).

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

int8Cores

gizlang
function int8Cores(gpu: Option<Gpu>): bool

Whether gpu is a GPU with INT8 matrix cores (K.hasI8Mma): there W4 and INT8 blocks run as stored.

Effects: fail.

normedInto

gizlang
function normedInto(work: Work, b: Block, a: Arch, xs: Tensor, w: Tensor, shift: Tensor, scale: Tensor, map: Tensor, y: Tensor): void

The modulated norm of rows xs into y (BF16), as a block's linears take it: an INT8 or INT4 block's to its rows and scales (work.q, work.s) in the same pass (N.modulatedInt8RowsInto), y then written for a LoRA of BF16 A alone.

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

runsIn

gizlang
function runsIn(runs: Vec<i64>, r0: i64, r1: i64): Vec<i64>

The runs (Sequence.runs) of rows [r0, r1), from r0.

Effects: fail.

prepOf

gizlang
function prepOf(b: Block, s: Sequence, a: Arch): N.HeadPrep

The head norm and H3's split rotary of a block's packed qkv rows (N.HeadPrep): each head of q and k over its RMS times its norm weight, then its first 2 half values turned by the sequence's cos and sin rows, as attention reads them.

Effects: fail.

comfyInt8Rows

gizlang
function comfyInt8Rows(sys: System, named: Map<string, Stored>, names: Vec<string>, gpu: Gpu): Vec<Tensor> throws string

Linears names of a ComfyUI INT8 ConvRot file (each name's .weight and .weight_scale: INT8 rows rotated by the regular Hadamard of 256, a scale a row) stacked by rows on gpu, as N.int8Rows' products read them (canonicalInto): [the INT8 weights [rows, in], their scales [1, rows] F32].

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

canonicalInto

gizlang
function canonicalInto(w: Tensor, from: Vec<i64>, out: Tensor, bits: i64 = 8): void

INT8 rows w ([out, in]) rotated in the regular Hadamard's own order, as ConvRot files store them, into out: its row r is w's row from[r], its inputs in the order N.int8Rows rotates inputs to (as W4.decodeInto's codes). With 4 bits w holds INT4 pairs ([out, in / 2] bytes, the even input in the low nibble: convrot_w4a4) and out is I4 [out, in].

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

blockOf

gizlang
function blockOf(w: Vec<Tensor>): Block

A block of weights w (Block.w): no biases, codes or LoRA.

Methods

Arch.width

gizlang
function Arch.width(self: Arch): i64

Values of the attention's queries (and of its keys, and of its values) per row.

Effects: fail.

Sequence.active

gizlang
function Sequence.active(self: Sequence, queries: i64): Sequence

Sequence s where only its first queries rows are updated, the others (cached keys and values: RefSlot) being read only: the same positions and modulation rows, the runs cut to the first rows.

Effects: fail.

Block.forward

gizlang
function Block.forward(self: Block, a: Arch, x: Tensor, m: Modulation, s: Sequence): Tensor

The block over x ([rows, hidden], f32): x + gate (attention of the modulated norm), then the same with the MLP. On a GPU x is updated in place and returned; on the host a new tensor.

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

Staged.on

gizlang
function Staged.on(self: Staged, g: Gpu, slot: Buffer): Block

The staged block on the GPU memory slot (its bytes there once copied).

Effects: fail.

Block.quantized

gizlang
function Block.quantized(self: Block, bits: i64 = 8): Block

The block (BF16) with each linear quantized once as N.int8Rows quantizes x: its rows through ConvRot to INT8 over a scale a row (INT4 with 4 bits, where K.hasI4Mma: about 1.8 times the products' speed, at a loss of quality). Products then run as a W4 block's (linear). On the host, or on a GPU without INT8 matrix cores (K.hasI8Mma: Apple GPUs), the block stays BF16 and its products run on the F16 and BF16 matrix cores.

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

Block.dequantized

gizlang
function Block.dequantized(self: Block): Block

The block (W4 as stored, or INT8 as Block.quantized and ComfyUI's files hold it) as BF16: on a GPU without INT8 matrix cores, and before a requantization. Each linear is its INT8 weights times each output's scale, turned back from ConvRot's rotation: N.int8Rows takes each 256 inputs x to y = R x, so the weights of x are those of y times R. A LoRA stays as it is: its A must be BF16, not INT8.

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

Block.parallel

gizlang
function Block.parallel(self: Block, a: Arch, x: Tensor, m: Modulation, s: Sequence, slot: Option<RefSlot> = undefined): Tensor

The parallel block over x ([rows, hidden], f32): x + gate (attention + SwiGLU MLP), both of one modulated LayerNorm. Its MLP's input linear has the gate and up rows interleaved (fluxBlock): row 2j is gate j, 2j + 1 up j. On a GPU x is updated in place and returned; on the host a new tensor.

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

Constants

gizlang
const HEAD = 128

Values of an attention head of H3, and the rotary frequencies of each of its (t, h, w) axes. A head of any multiple of 32 values (Arch.head) rotates its first 3/4: the t, h and w angles of head / 8 frequencies each, twice (split halves).

AXIS_FREQUENCIES

gizlang
const AXIS_FREQUENCIES = 16

The rotary frequencies of each of a head's (t, h, w) axes: HEAD / 8.

QKV

gizlang
const QKV = 0

The index in Block.w of the fused query, key and value projection.

OUT

gizlang
const OUT = 1

The index in Block.w of the attention's output projection.

UP

gizlang
const UP = 2

The index in Block.w of the MLP's up projection (gate and up rows in pairs: gluRows).

DOWN

gizlang
const DOWN = 3

The index in Block.w of the MLP's down projection.

NORM1

gizlang
const NORM1 = 4

The index in Block.w of the norm weight before the attention.

NORM2

gizlang
const NORM2 = 5

The index in Block.w of the norm weight before the MLP.

Q_NORM

gizlang
const Q_NORM = 6

The index in Block.w of the queries' head norm weight.

K_NORM

gizlang
const K_NORM = 7

The index in Block.w of the keys' head norm weight.

POST_ATTN

gizlang
const POST_ATTN = 8

The indexes in Block.w of a sandwich block's norm weights after the attention and after the MLP (Z-Image): its outputs are normed before their gates. A block without them adds its gated outputs as they are.

POST_MLP

gizlang
const POST_MLP = 9

The index in Block.w of a sandwich block's norm weight after the MLP (see POST_ATTN).

CHUNK

gizlang
const CHUNK = 4096

Rows a chunk of a block's linears and MLP takes: their temporaries (Work) stay within a few hundred MB.