All tutorials · Updated September 21, 2026 · tinygrad 8ad8f73
VIZ records the transformations that connect a Tensor expression to executable work. It is especially useful when the final source looks surprising: walk backward to the first pass that introduced the unexpected operation.
from tinygrad import Tensor
x = Tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]).realize()
result = (x.permute(1, 0) + 1).sum(axis=1)
assert result.tolist() == [7.0, 9.0, 11.0]
print(result.tolist())
Save it as example.py, then run:
VIZ=1 DEV=CPU python3 example.py
The current VIZ README says this saves profiling/rewrite data and launches the server in interactive shells. The viewer is local. In noninteractive environments, inspect the generated recording using the CLI instead of assuming a browser will open.
At Tensor level, look for movement and reduction operations. During rangeification, inspect how coordinates are mapped and how the reduction obtains explicit ranges. At kernel splitting, identify storage boundaries and calls. During codegen, look for optimization, range expansion, reduction lowering, target preparation, and the final program.
A node disappearing does not necessarily mean its semantics disappeared. A transpose can become address arithmetic; padding can become validity and selection. Verify the equivalent indexing, not the presence of the original opcode.
The CLI consumes recorded profiling data; run the workload first.
python3 -m tinygrad.viz.cli
DEBUG=3 python3 -m tinygrad.viz.cli --json
The CLI’s documented debug levels add ASTs at 3, source at 4, rewrite steps/kernel graph at 5, all UOp graphs at 6, and all rewrites at 7. These are viewer output controls; do not assume their meaning is identical to every runtime’s logging behavior.
Use --help and the current README for selectors. Select a schedule or kernel from your own recording, then use --ls to list its passes. Names shown in another machine’s screenshot are not stable identifiers.
For the example, ask: where does output coordinate i get mapped to column i of the original matrix? Next ask: which range iterates over its two rows?
If the numeric result is wrong, this separates a movement/indexing error from a reduction or backend error. If the result is right but slow, inspect realization boundaries, index complexity, launch dimensions, and repeated compilation before changing the expression.
The old viewer screenshots are retained in repository history; the current walkthrough follows the recording and pass structure of the pinned revision.
Original chapter by Di Zhu: historical version.