6.5.7 · D2Advanced & Emerging Architectures

Visual walkthrough — Google TPU architecture and systolic arrays

2,095 words10 min readBack to topic

We only need one running example, so let us fix it now and never change it:

and are just grids of numbers. has 2 rows and 2 columns; so does . We want their product , which is also a grid. Our whole mission: build a little machine of cells that spits out without ever re-reading a number from memory.


Step 1 — What "multiply two matrices" even asks for

WHAT. The rule for matrix multiplication says: the number in row , column of — written (read "C-eye-jay", the entry at row and column ) — is built by walking across row of and down column of , multiplying the pairs you meet, and adding them up.

Here means "the entry of in row , column ." The little numbers are just addresses on the grid.

WHY. Before we build hardware, we must know exactly what sum each output is. Everything the machine does is a physical realisation of this one formula. If we get the target wrong, no clever wiring saves us.

PICTURE. The figure shows being formed: the top row of (orange) slides across the left column of (teal); the crossings are the products we add.

Figure — Google TPU architecture and systolic arrays

Concretely, . Hold that number; the machine must reproduce it.


Step 2 — The one cell that does a single "multiply-and-pile-up"

WHAT. We build the whole array out of one repeated part: a processing element (PE) — a tiny box that can do exactly one multiply and one add per tick of the clock. "One tick of the clock" (one cycle) is the heartbeat: every cell acts once, all together, then again. Inside the cell lives a stored weight and a running total called the accumulator, written .

Each cycle the cell does:

  • = the number that just walked in from the left (an entry of ).
  • = the number parked inside this cell (an entry of ).
  • = the growing sum that will become one entry of .

WHY. Look back at Step 1: an output is a sum of products. A "multiply-then-add-to-a-total" box is the smallest machine that grows such a sum. We pile up in place so the partial answer never has to leave the cell — that is how we dodge the memory wall.

PICTURE. One cell, labelled: weight frozen inside, entering left, and the accumulator ticking up.

Figure — Google TPU architecture and systolic arrays

Step 3 — Passing the activation along (read once, use many times)

WHAT. A cell doesn't just consume ; it also hands it to the neighbour on its right, unchanged:

That equation looks trivial, but it is the magic. It says: the same activation, after being used here, keeps travelling and gets reused by the next cell one cycle later.

WHY. In the matmul rule, the number shows up in every entry of row of (). So should be read from memory once and then physically walked across all the cells that need it. is that walk. Reading once and reusing times is exactly what raises the arithmetic intensity.

PICTURE. A single activation (orange dot) marching left→right through a row of cells, being multiplied by a different parked weight in each, while partial sums fall downward.

Figure — Google TPU architecture and systolic arrays

Step 4 — Park the weights: laying into the grid

WHAT. Build a grid of cells. Before any activation flows, we load into the cells, one weight per cell, matched to position: cell in row , column stores .

Read the layout carefully: column of the array holds column of . That is deliberate — column of the array will produce column of .

WHY. Each output needs the pair . By stacking column of vertically in array-column , an activation streaming down/through that column meets exactly the weights it must multiply. The geometry does the bookkeeping for us.

PICTURE. The grid with frozen in the four cells, colour-coded by which column of they serve.

Figure — Google TPU architecture and systolic arrays

Step 5 — Stream the activations and watch grow

WHAT. Now push a row of into the grid. Take row 1 of , which is , and feed it into the cells of array-column 1 (the ones holding and ). The accumulator in that column collects:

Feed the same row 1 into array-column 2 (holding and ):

Each partial sum () enters a cell from the top, gets one product added, and leaves at the bottom as :

WHY. Compare with Step 1's target . The array reproduced it without a single instruction fetch — the wiring is the program. The sum that used to unfold in time (loop iterations on a CPU) now unfolds in space (down a column of cells).

PICTURE. Row entering column 1; the partial sum accumulating , then as it drops through the two cells.

Figure — Google TPU architecture and systolic arrays

Step 6 — The skew: why inputs enter diagonally (the timing edge case)

WHAT. There is a subtlety we glossed over: cells act all at once each cycle, but data needs time to travel. If we shoved every activation in on the same cycle, the partial sums arriving from above would meet the wrong activation. The fix is to stagger (skew) the inputs: row 2 of the data enters one cycle later than row 1, row 3 one later still, forming a slanted diagonal wavefront.

WHY. For a product to be correct, the activation and the partial sum must rendezvous in the same cell on the same cycle. Because a partial sum takes one hop per cycle to descend, and an activation takes one hop per cycle to cross, we must offset their launch times so their paths cross at the right instant. Skewing by one cycle per row synchronises the whole grid.

PICTURE. A slanted "wavefront" of inputs: the top row of data already deep inside the array while the next row is only just entering — the tell-tale diagonal staircase.

Figure — Google TPU architecture and systolic arrays

Step 7 — Counting the cost: fill, drain, and why arrays crave big batches

WHAT. For an array (here ; TPUv1 has ), the very first result cannot appear until data has propagated diagonally across the whole grid. That warm-up is the fill; emptying the pipeline afterward is the drain. Together they cost about cycles. After the pipeline is full, one fresh row of results emerges every cycle. So pushing rows of input through takes:

Efficiency — the fraction of cycles doing useful streaming — is:

WHY. Look at the shape of that fraction. If is tiny, the fixed dominates and most cycles are wasted warming up. If is huge, the fixed cost vanishes into the average. That is precisely why the TPU is a throughput machine for large batches, not a low-latency machine — an idea the Roofline model and arithmetic-intensity view make quantitative.

Numbers. For : fill/drain . To hit efficiency:

so about 4600 rows (the parent's "" using the rounder ).

PICTURE. The efficiency curve rising from near-zero toward as batch size grows, with the line marked.

Figure — Google TPU architecture and systolic arrays

The one-picture summary

Everything above collapses into a single frame: weights parked in the grid, a skewed diagonal of activations flowing in from the left, partial sums cascading down, and finished entries of dropping out the bottom.

Figure — Google TPU architecture and systolic arrays
Recall Feynman retelling — say it back in plain words

We wanted to multiply two grids of numbers. Every answer-box is just a row-times-column "dot product" — multiply the matching pairs and pile them up. So we built one tiny box that does one multiply-and-add per heartbeat, and we glued a whole grid of them together. We parked the second matrix's numbers inside the boxes (each stays put — weight-stationary). Then we fed the first matrix in from the left, and here's the trick: each box, after using an incoming number, hands it to its neighbour unchanged — so every number is read from memory once but reused all across a row. Partial sums slide downward through each column, growing until they equal an answer-box, then fall out the bottom. To make the incoming number and the falling sum meet in the right box at the right beat, we release the input rows in a slanted staircase (one beat later per row). Warming the pipeline up and draining it costs a fixed number of beats, so tiny jobs waste time warming up — that's why the TPU loves big batches, where one answer-row pops out every single beat.

Recall Quick self-test

Why is the activation passed unchanged to the right neighbour? ::: So it is read from memory once yet reused by every cell in the row — the reuse trick that beats the memory wall (). Why must inputs enter diagonally staggered? ::: So each activation and its descending partial sum arrive in the same cell on the same cycle; skewing by one cycle per row synchronises the rendezvous. For a array, roughly what batch gives efficiency? ::: About rows (fill/drain , solve ). Why does throughput scale as , not ? ::: There are cells, each doing a MAC every cycle — the parallelism is spatial, so peak FLOP/s.


Related: ASIC vs FPGA vs general-purpose processors · Quantization and 8-bit inference · GPU architecture and SIMT execution