Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Machine files

Most compilers hard-code a cost model. Vx reads one.

A machine file describes the memory hierarchy and interconnect of a real part. The compiler admits or rejects your placements against it, and derives transfer costs from it, before a binary exists.

An example

#![allow(unused)]
fn main() {
Memory HBM  { capacity: 80 GiB, bandwidth: 3.35 TB/s, managed: explicit, scope: device }
Memory L2   { within: Memory::HBM, capacity: 50 MiB, bandwidth: 12 TB/s, managed: cached }
Memory SMEM { within: Memory::L2, capacity: 228 KiB, bandwidth: 128 B/cyc,
              clock: 1.98 GHz, replicas: 132, granule: 1 KiB, scope: sm }

Topology Device {
    arch: nvptx64,
    memory: Memory::HBM,
    transfer Memory::CPU_DRAM -> Memory::HBM : 63 GB/s,
}
}

That is an H100, in eleven lines.

The fields

capacity — how much the space holds. Checked against the working set of anything you place there.

bandwidth — either a rate (3.35 TB/s) or a per-cycle figure with a clock (128 B/cyc at 1.98 GHz). The second form is how scratchpads are usually specified in vendor documentation.

within — containment. L2 sits inside HBM. The containment relation must be acyclic, a child may not exceed its parent’s capacity, and scope narrows as you descend.

managedexplicit if software moves the data, cached if hardware does.

scope — who can see it. device is visible to the whole accelerator; sm is private to one streaming multiprocessor.

replicas — how many copies of the space exist. 132 SMs means 132 scratchpads, and a placement is admitted against one of them, not their sum.

granule — the allocation quantum. A 1 KiB granule means a 100-byte tensor occupies 1 KiB, and admission rounds accordingly.

Units are exact

SI prefixes are decimal and IEC prefixes are binary:

GB10⁹ bytes
GiB2³⁰ bytes
TB/s10¹² bytes per second

Conversions are exact integer arithmetic, never floating point. A figure copied off a vendor datasheet means precisely what the datasheet meant, and does not drift by a fraction of a percent on the way through the compiler.

What the compiler derives

From that declaration alone, before any code is generated:

Admission — whether a tensor’s working set fits the space it is placed in, with granule rounding applied. A rejection carries the space, the amount required, the amount available and the margin.

Routing — the cheapest legal path between two spaces, over the declared transfer graph. If you transfer from a space that has no declared route to the destination, that is an error rather than a silently inserted staging copy.

Transfer cost — a roofline over the containment tree. A containment hop is charged at both endpoints, because data has to leave the parent as well as enter the child.

Coherence of the model itselfwithin is acyclic, no child exceeds its parent, scope narrows downward, and every edge has exactly one cost source. A machine file that contradicts itself is rejected as a machine file, before your program is even considered.

The bundled fleet

The repository ships machine files for real parts under fleet/: H100, H200, B200, A100, MI300X, Apple M4 unified memory, multi-GPU nodes and hosts. Each one cites its sources, and marks figures that have not been validated against hardware as unverified.

That last part matters. A declared bandwidth is often the vendor’s hardware peak rather than an achievable rate — Apple’s 120 GB/s for the base M4 is the memory system’s ceiling, not what a copy loop will reach. The fleet files state the vendor’s claim rather than a number already fitted to a measurement, so the gap between prediction and reality stays visible instead of being quietly tuned away.

Using one

vxc --machine fleet/h100-sxm.vx program.vx -o program

--machine prepends the declarations to your compilation unit. They are visible to capacity and placement checks exactly as if you had written them inline. A name declared by both the machine file and the program is an error, never a silent shadow.

--machine describes an accelerator and says nothing about the host it hangs off. If your program stages through host memory, declare the host too:

vxc --machine fleet/h100-sxm.vx --host default program.vx -o program

--host default means “the machine doing the compiling”. A host file declares no capacity, on purpose: host memory is virtual, and a tensor larger than physical RAM pages rather than failing. A hard limit there would reject programs that actually run.

Writing your own

Start from the closest file in fleet/ and change the numbers. The compiler will tell you if the result is incoherent, which makes the edit-check loop fast. Two habits worth keeping:

  1. Cite every figure. The fleet files carry the source of each number in a comment. When a prediction is wrong, the first question is always whether the model or the measurement is at fault, and a citation answers it in seconds.
  2. Mark what you have not verified. A number from a datasheet and a number from a benchmark are different kinds of thing, and the difference should survive in the file.