systile
A TPU-native tiled tensor data structure, written from scratch in Rust.
Most tensor libraries store a flat row-major buffer and bolt on a layout pass when
it is time to talk to an accelerator. systile inverts that: its core data
structure, the Padded Tile Lattice, is laid out the way a Tensor Processing
Unit's memory is addressed from the very first allocation. The flat buffer it owns
is already in device order, so handing data to hardware is a memcpy rather than
a transpose.
This is a host-side data structure and a CPU reference simulator. You do not
need a TPU to use it — the point is to model the constraints a TPU imposes
(mandatory tiling, padding, (sublane, lane) addressing, bf16/int8 dtypes, square
matrix-unit blocking) so you can prepare, validate, and reason about layouts before
anything touches real silicon.
Why a data structure "for TPUs"?
A TPU is not a flat array machine. Three hardware facts drive its data layout, and
systile encodes all three:
| Hardware fact | What it forces | Where systile handles it |
|---|---|---|
Vector memory is addressed as 8 × 128 (sublane, lane) tiles |
Data must be tiled and padded to tile boundaries | Geometry, Layout, Shape |
The matrix unit is a 128 × 128 systolic array |
Matmul runs in square mxu blocks, padding included |
systolic |
Native dtypes are bf16 and int8, not f32 |
You quantise/narrow before compute, accumulate in f32 |
bf16, quantize |
Because padding is mandatory, the structure tracks both the logical shape you
asked for and the padded shape it actually stores, plus a validity Mask so
reductions and dense round-trips never fold in garbage.
Quick start
use *;
let a = from_dense.unwrap;
let b = from_dense.unwrap;
// Matmul runs in the same blocked dataflow a systolic array uses.
let = a.matmul_with_stats.unwrap;
assert_eq!;
println!;
The headline: a data structure whose operations are matmuls
On top of the tiling substrate, systile ships an invented container — the
Holographic Tensor Store (HoloMemory) — a key→value map that holds every
entry summed on top of every other inside a single fixed-width vector, and
recovers a value by algebra plus one matrix multiply.
use *;
let mut book = new; // 8192-dim, 1000 value symbols
for name in 0..200
// Look up all 200 names at once — a single (200 × 8192)·(8192 × 1000) matmul.
let hits = book.batch_get;
let correct = .filter.count;
assert_eq!; // 100% recall, well under the d/(2 ln M) capacity bound
200 entries live in 32 KB of f32; lookup of the whole batch is one MXU-shaped
GEMM. On a CPU this is a worse map than a hash table — it only pays off where
dense matmul is the cheap primitive and you batch thousands of probes: a TPU. It's
approximate and bounded (K_max ≈ d / (2 ln M)), degrading gracefully past
capacity. The full mechanism, capacity math, honest novelty assessment, and
citations are in HOLOGRAPHIC.md. Try it:
cargo run --release --example holo_kv # 200 pairs in one vector, 1 matmul
cargo run --release --example holo_capacity # recall vs the d/(2 ln M) bound
cargo run --release --example resonator_factor # factor a product with no known factors
cargo run --release --example holo_precision # f32 vs bf16 cleanup recall
cargo run --example holo_analogy # "Dollar of Mexico?" -> peso, zero training
Features
- A family of matmul-native containers on a hyperdimensional (VSA) substrate
(
Hyperalgebra +Codebookmatmul cleanup):HoloMemory— key→value store in superposition; batched lookup is one matmul.HoloSet— set membership as a matmul; union by bundling; norm-based cardinality.HoloSequence— order via permutation binding; whole-sequence decode in one matmul.Resonator— factor a bound product back into its unknown symbols by iterated matmul cleanup (anMᶠsearch run as a short sequence of GEMMs), with exact verification and restarts.
PaddedTileLattice<T>— the core 2-D tiled tensor, generic over element type.bf16— a from-scratch bfloat16 with round-to-nearest-even and a full set of arithmetic / comparison / conversion impls.- Systolic matmul simulator — weight-stationary,
f32-accumulated, verified bit-for-bit against a naive triple loop, and it reports MAC utilisation. - Tile-level sparsity — find and skip the all-zero tiles a kernel would waste cycles on.
- Affine int8 quantisation — symmetric and asymmetric calibration that preserves the hardware tiling end to end.
- Transpose & relayout — re-tile the same logical data under a new geometry.
- Element-wise maps and reductions — padding-correct by construction.
#![forbid(unsafe_code)], no required dependencies.
Examples
cargo run --example quickstart
cargo run --example bf16_roundtrip
cargo run --example quantize_matmul
cargo run --example sparsity_report
cargo run --example padding_inspect
cargo bench
Layout, in one picture
A 3 × 5 logical matrix on Geometry::TPU_V (8 sublanes × 128 lanes) pads up to a
single 8 × 128 tile. Element (row, col) lives at:
offset = tile_index * (sublanes * lanes) + sublane * lanes + lane
tile_index walks tiles in row-major order; within a tile the order is row-major
over (sublane, lane). That is exactly the order a TPU's vector memory expects, so
as_storage_slice() is copy-ready.
Status
systile is young and the API may shift before 1.0. The simulator is a reference
model, not a cycle-accurate one: it reproduces the blocking and accumulation
order of a systolic array (and so its numerics), not its timing.
License
Licensed under either of MIT or Apache-2.0 at your option.