Graphs¶
A graph is a subclass of iron.Graph whose body() is recorded on handles,
once per input shape, and compiled to one image per shape. These are the
names import iron gives.
IRON: operators for the NPU, and graphs over them.
Its names are imported on first use, so import iron stays light.
Carried
module-attribute
¶
Carried = Annotated[T, Kind.CARRIED.value]
A scratchpad value a graph computes for its next call and returns last with
iron.carry(name=...): an expression of its values (position + 1) or a
one-element handle (a sampled token); the host seeds only the first call.
Scratchpad
module-attribute
¶
Scratchpad = Annotated[T, Kind.SCRATCHPAD.value]
A per-call value patched into a DMA descriptor or read by a core: free per call, works under full ELF, cannot change a DMA size or stride; 30 bits at most.
Precision
¶
Bases: StrEnum
The roundings a matmul may make beyond its reference's.
Named as torch.set_float32_matmul_precision names them; each level
allows the one above's and more, and a matmul takes the fastest kernel
its level allows.
HIGHEST: f32 partial sums, rounded once to the output's type.HIGH: partial sums rounded to the output's type per K tile.MEDIUM: A and B rounded to bfp16 for the multiplies, where the device has bfp16 macs.
Profile
¶
Tunable values by operator shape, as (cls, dims, tunables) entries.
An open tunable comes from the most specific match (a dimension left out matches any, a subclass its base's); equally specific ones that disagree raise.
Source code in iron/common/declare/profile.py
make
¶
Build cls(**kwargs) with its open tunables filled from this profile.
Standalone use of what a graph's recorder applies implicitly to every step it constructs.
Source code in iron/common/declare/profile.py
add
¶
Add an entry for cls.
param() values to match (one left out matches any value) and
tunable() values to give.
Source code in iron/common/declare/profile.py
tunables_for
¶
Resolve the tunables for the cls a call with given keywords makes.
Each comes from the most specific entry naming it.
Source code in iron/common/declare/profile.py
dims
staticmethod
¶
Collect every dimension (param()) a kind call with given makes.
This is what an entry is matched against: one it leaves out is its
default, None where a function computes it.
Source code in iron/common/declare/profile.py
matches
staticmethod
¶
Whether an entry's matched dimensions cover dims.
load
classmethod
¶
Load the profile save wrote to path.
Source code in iron/common/declare/profile.py
save
¶
Write the profile as JSON, one entry to a line.
Raises:
| Type | Description |
|---|---|
ValueError
|
An entry's operator is not in |
Source code in iron/common/declare/profile.py
CarriedLoop
¶
CarriedLoop(first: CompiledGraph, body: CompiledGraph, depth: int = 2)
A graph's carried values looped on the device.
first runs once from the host, then body (no tensor) with
depth runs in flight, each run's Emit writing the next's
scratchpad, so the host only waits and restarts.
Source code in iron/common/graph/carried.py
run
¶
start now, then steps, each index yielded once complete.
start
¶
Run first on tensors and values, and wait for it.
Source code in iron/common/graph/carried.py
steps
¶
Run steps steps of body, yielding each index once complete.
Closing early waits out the steps in flight.
Source code in iron/common/graph/carried.py
CompiledGraph
¶
CompiledGraph(recording: Recording, plan: Plan, check: bool = False, arena: ScratchArena | None = None, emit: EmitSite | None = None)
A recorded graph built into an image, ready to call.
Called with the per-call values this version reads (Recording.reads);
the graph's others go unused.
Source code in iron/common/graph/compiled.py
callable
property
¶
The loaded image, made on first use so a host without an NPU can compile.
release
¶
Free this version's runs, image and the buffers it holds outside the arena.
Source code in iron/common/graph/compiled.py
read
¶
x's buffer as the device left it: a view of its host memory.
push
¶
Send to the device what the host wrote into read(x)'s view.
upload
¶
Copy every closed-over weight into its buffer, once per storage.
Source code in iron/common/graph/compiled.py
load
¶
load(release: Callable[[ndarray], None] | None = None, piece_bytes: int = UPLOAD_PIECE) -> CompiledGraph
Load the image and upload its weights now rather than on first call.
Source code in iron/common/graph/compiled.py
start
¶
Start a call of this full ELF on run without waiting for it.
Raises:
| Type | Description |
|---|---|
ValueError
|
A host step runs between its commands. |
Source code in iron/common/graph/compiled.py
emit_to
¶
emit_to(target: CompiledGraph) -> None
Program this version's Emit to start a call of target.
Source code in iron/common/graph/compiled.py
Graph
¶
A graph: a subclass whose body is recorded on handles.
body's positional parameters are the inputs (one defaulting to None
may be left out), its keyword-only ones the per-call values, its return
the outputs; signature() may name them instead. Weights and states
are what it holds, by attribute path (self.layers[3].q is
layers.3.q); profile is a Profile or a directory of
<device>.json ones. Called in another graph's body, it records there.
signature
¶
signature() -> Signature
Return the inputs and per-call values body takes, self left out.
body's own parameters, unless a subclass names them here.
Source code in iron/common/graph/compiled.py
held
¶
Each param, weight and state held, by id, with its path.
Raises:
| Type | Description |
|---|---|
TypeError
|
A |
Source code in iron/common/graph/compiled.py
release
¶
Free the device memory this graph's versions and arena hold.
A call after it loads them again.
Source code in iron/common/graph/compiled.py
load_state_dict
¶
load_state_dict(tree, *, path: str = '') -> None
Bind each param held, at any depth, to its tensor in tree.
The tensor is found at path (this graph's prefix, "model.")
plus its dotted path in tree, cast as torch's copy_; a param
held at several paths binds once.
Raises:
| Type | Description |
|---|---|
ValueError
|
|
TypeError
|
A param is in a tuple or a frozen dataclass. |
Source code in iron/common/graph/compiled.py
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 | |
record
¶
Run body on handles of the given shapes.
An optional input given none is None.
Source code in iron/common/graph/compiled.py
compile
¶
compile(*, dev: Device | None = None, full_elf: bool | None = None, check: bool = False, feeds: CompiledGraph | None = None, **shapes: Sequence[int] | tuple[Sequence[int], DTypeLike]) -> CompiledGraph
Compile and return the version for these input shapes.
Compile all before the first call, as a later one grows (copies) the arena.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dev
|
Device | None
|
The device, for this compile alone; else the current one. |
None
|
full_elf
|
bool | None
|
One full ELF, else an xclbin per step; |
None
|
check
|
bool
|
Run each step on its own dispatch, raising at the first
outside its |
False
|
feeds
|
CompiledGraph | None
|
The version a full ELF's Emit starts; by default itself when it takes no tensor. |
None
|
**shapes
|
Sequence[int] | tuple[Sequence[int], DTypeLike]
|
Each input's shape, or |
{}
|
Source code in iron/common/graph/compiled.py
inline
¶
Record method, one of this graph's, into the graph being recorded.
Recorded under this graph's profile; that graph names its values.
Raises:
| Type | Description |
|---|---|
TypeError
|
No graph's body is being recorded. |
Source code in iron/common/graph/compiled.py
reference
¶
reference(*tensors, dev=None, **values) -> Any
Run the body on the host, each step through its operator's reference().
Tiled for dev (else the current device) without needing an NPU;
outputs are numpy arrays of their shape, cut to bounds.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
No device is given or bound. |
TypeError
|
An input or per-call value is missing or unknown. |
IndexError
|
The values index or bound a view outside it. |
Source code in iron/common/graph/compiled.py
carry
¶
Return with a graph's outputs the next value of each carried value.
return logits, iron.carry(token=sampled, position=position + 1).
Source code in iron/common/graph/handle.py
clamp
¶
Return a per-call value's expression x held to [lo, hi], a bound of None none.
The nearer bound itself where x never reaches the range.
Source code in iron/common/graph/handle.py
on_host
¶
on_host(fn: Callable[..., None], *reads, writes=()) -> None
Run fn(*reads, *writes) on the host between the steps around it.
A full ELF ends a command there, so the graph has no device loop. Each is contiguous: reads cut to their bounds, writes parts of states no step writes.
Raises:
| Type | Description |
|---|---|
TypeError
|
No graph's body is being recorded. |
Source code in iron/common/graph/handle.py
param
¶
param(*shape, dtype=bfloat16) -> ndarray
Declare a weight a graph holds, as torch's nn.Parameter.
Declared by shape for Graph.load_state_dict to bind, or
param(array) holding array. A graph refuses to hold a bare array.
Source code in iron/common/graph/compiled.py
state
¶
Handles¶
What a graph's body() reads and writes: each operator step returns one.
Handle
dataclass
¶
Handle(buffer: Buffer, shape: tuple[int, ...], dtype: Any, valid: Mapping[int, Affine] = dict(), layout: Dense | Strided | Gather = Dense())
A recorded tensor: its place in a graph buffer, shape, dtype, and per-axis bound.
layout is where it is in the buffer; valid holds, per axis, the
leading entries valid this call (x[:n]).
h[key] takes numpy's basic indexing, a per-call value on one axis
(keys[:, pos]), and leading-axis rows, fixed (table[ids]) or a 1-D
integer handle's per call; any view but a contiguous static slice is a copy's.
whole
classmethod
¶
Make a new buffer name of shape, whole.
ref
¶
Return where a step finds this handle.
A part of its buffer for a contiguous run, else all of it.
Source code in iron/common/graph/handle.py
reshape
¶
reshape(*shape) -> Handle
Return the same buffer seen with another shape (no data moves).
Source code in iron/common/graph/handle.py
transpose
¶
transpose(*axes) -> Handle
Return the same buffer walked with its axes permuted (no data moves).
Source code in iron/common/graph/handle.py
at
¶
at(tap: TensorAccessPattern | tuple[TensorAccessPattern, ...], shape, *, bounds=None, repeat=None, length=None)
Return what tap walks, as shape: a slice if contiguous, else a view.
Per call, repeat runs each pattern's first dimension (a tuple, one
per pattern of a tuple tap) and length takes entries of its
second; bounds then gives the rows the view moves a call.
Raises:
| Type | Description |
|---|---|
ValueError
|
With |