Appendix E. Glossary and Command Reference¶
The first half is a glossary of the terms the book uses, each with the chapter that explains it; the second half lists, in one place, the commands, options and passes you can run. The chapter index at the end is generated from the chapter pages. The pass list and the usage texts were produced by running the tools themselves (appendixE/code/list_passes.sh).
E.1 Glossary¶
| term | meaning | where |
|---|---|---|
| adjoint | the derivative of the loss with respect to a value: how much the loss changes if that value changes | Ch 45 |
| affine (dialect) | MLIR's dialect of loops whose bounds and indexing are affine expressions, which makes them analysable | Ch 4, 7; App B |
| attention | a layer that mixes each position's value from the others, weighted by how well queries match keys (a softmax of scores) | Ch 29, 30, 33 |
| backward pass | computing the gradient of a loss by walking the program's operations in reverse | Ch 33 to 35, 45 |
| basic block | a straight-line run of instructions ending in a branch or return | App C |
| broadcasting | stretching a size-1 dimension to meet another operand (RxC with 1xC) |
Ch 22; App A |
| bufferization | replacing value-semantics tensors with memref buffers in memory |
Ch 6 |
| canonicalization | the standard clean-up pass: folds constants, removes dead operations | Ch 3; App B |
| dialect | a named group of MLIR operations, types and attributes (arith, affine, mg, ...) |
Ch 2; App B |
| dynamic shape | a dimension whose size is unknown at compile time (written ?) |
Ch 13, 14 |
| FileCheck / lit | LLVM's test tools: lit runs test files, FileCheck matches their output against CHECK: lines |
Ch 15 |
| fast-math flags | per-instruction permissions (reassoc, contract, nnan, ...) that let LLVM reorder or fuse floating-point arithmetic |
Ch 44 |
| fusion | merging two loops into one so intermediate values stay in registers | Ch 7, 18 |
| GA-1 | the book's model of a matrix accelerator, used to study tiling and loop order | Ch 40, 41 |
| gradient | the vector of derivatives of a loss with respect to its parameters | Ch 26, 33, 45 |
| Hessian | the matrix of second derivatives of a loss; the book computes its product with a vector | Ch 46 |
| lowering | rewriting operations of a higher-level dialect into lower-level ones | Ch 4, 5; App B |
| memref | an MLIR type for a reference to a buffer in memory, with sizes and strides | Ch 1; App B |
| mutation test | a test of the tests: break the code on purpose and check that the checker fails | Ch 15 and every chapter's "wrong versions" section |
| NVVM / PTX | NVIDIA's flavour of LLVM IR, and the assembly language of NVIDIA GPUs | Ch 10, 11 |
| outlining | moving a repeated piece of code into a shared function | Ch 38, 43 |
| pass | a program transformation on a module; a pipeline is a list of passes | Ch 3; App B |
| phi | the LLVM IR instruction that picks a value according to which block control came from | App C |
| progressive lowering | lowering in many small steps, one level of abstraction at a time | Ch 4, 5 |
| region | the list of blocks an MLIR operation can contain (a loop body, a function body) | App B |
| reverse-mode differentiation | computing all the derivatives of a scalar loss in one backward walk over the program | Ch 45 |
| SSA | static single assignment: every value is defined exactly once | App B, C |
| softmax | exponentiate and normalise a row so it sums to 1 | Ch 29 |
| tile / tiling | splitting a loop nest into blocks that fit a small fast memory | Ch 7, 40 |
| vectorization | doing one instruction on several elements at once (SIMD) | Ch 37, 44 |
E.2 mgc, the driver¶
usage: mgc run|build|lib|mlir|ptx prog.mg [-o exe] [-O0..-O3] [--passes "..."] [--matmul-order ikj|ijk] [--no-outline] [--no-reverse-loops] [--fast-math[=flags]]
| subcommand | does |
|---|---|
mgc run prog.mg |
compile to a native executable and run it |
mgc build prog.mg [-o exe] |
compile to a native executable |
mgc lib prog.mg [-o dir] |
compile the defs to prog.o plus a C++ header prog.h (no main) |
mgc mlir prog.mg |
print the mg-dialect MLIR the front end produces |
mgc ptx prog.mg |
compile to PTX (nothing is launched) and print it |
| option | meaning | chapter |
|---|---|---|
-O0 to -O3 |
optimisation level of the final clang step (default -O0) |
23 |
--passes "..." |
extra mg-opt passes on the affine IR, before lowering (quote as one argument) |
23 |
--matmul-order ikj\|ijk |
loop order mg.matmul is lowered to (default ijk) |
24 |
--no-reverse-loops |
use MLIR's own --convert-scf-to-cf instead of lowering last to first (the default since Chapter 43) |
42, 43 |
--no-outline |
do not outline loop nests into shared functions (outlining is the default since Chapter 43) | 38, 43 |
--fast-math[=flags] |
set fast-math flags on floating-point operations (off by default; in the Chapter 44 version of mgc, part44/code/mgc) |
44 |
Environment variables: MG_OPT (which mg-opt to use), MGC_KEEP=dir (keep every intermediate file), MGC_CFLAGS (extra flags for clang, for example -march=native), MGC_CLANG (which clang to call).
E.3 The passes this book adds to mg-opt¶
mg-opt is built from MLIR's own pass library plus the following five passes and the mg dialect (as printed by mg-opt --help for the Chapter 44 build; comparing its option list with mlir-opt-18 --help shows these and their parameters (flags, matmul-order, min-loops) as the only differences, and mg-opt registers only a subset of mlir-opt's passes):
--convert-mg-to-affine - Lower Mountain Goat's own mg dialect to affine/memref/arith, hand-bufferizing each op's own result as it is lowered.
--mg-lower-assert-to-stderr - Rewrite cf.assert into a branch that write()s its message to fd 2 and aborts (MLIR's own lowering uses buffered stdout)
--mg-outline-loops - Outline top-level affine loop nests into deduplicated functions (cuts compile time of huge functions)
--mg-scf-to-cf-reverse - Lower scf to cf one top-level statement at a time, from the last to the first
--mg-set-fastmath - Set fast-math flags (default reassoc,contract) on floating-point arith operations
E.4 The Python tools of Chapters 45 and 46¶
autograd.py (Chapter 45) writes a Mountain Goat program that computes a loss and its gradients, or takes gradient-descent steps; hvp.py (Chapter 46) wraps it to compute Hessian-vector products:
usage: autograd.py [-h] [--loss LOSS] --wrt WRT [--descend STEPS] [--lr LR]
program
Reverse-mode automatic differentiation for Mountain Goat, as a source-to-
source transformation.
positional arguments:
program
options:
-h, --help show this help message and exit
--loss LOSS which print is the loss (0 = the first)
--wrt WRT comma-separated names of `let` matrices to differentiate
with respect to
--descend STEPS instead of printing the gradients, write a program that
takes STEPS gradient-descent steps on the --wrt matrices
and prints the loss after each
--lr LR learning rate for --descend
usage: hvp.py [-h] --wrt WRT --vec VEC program
positional arguments:
program
E.5 Running the book's tests¶
cd docs/part44/code && ./build.sh # build mg-opt (needs mlir-18-tools, libmlir-18-dev, cmake)
cd ../../part15/code && ./run_lit.sh # the whole test suite (about 2 minutes)
E.6 Chapter index¶
- 1. Why a Multi-Level IR at All
- 2. A Minimal Dialect From Scratch: Mountain Goat's Own
mgDialect - 3. The Real Pass Infrastructure: Canonicalizing Mountain Goat
- 4. Progressive Lowering: Mountain Goat to
affine, Two Real Ways - 5. Finishing Progressive Lowering:
affinetoscftollvm, and Mountain Goat Finally Runs - 6. Real Bufferization: Closing Chapter 4's Own Honest Gap
- 7. Real Loop Transforms: Fusion, Tiling, and Unrolling at the
affineLevel - 8. A Standalone Native Executable: Mountain Goat Without MLIR At Runtime
- 9. MLIR's Own Real C++
ExecutionEngineAPI, Called In-Process - 10. GPU Lowering: Mountain Goat to the
gpuDialect, NVVM, and Real PTX - 11. The GPU Host Side: Device Memory, Real Runtime Calls, and a Stub "Device"
- 12. Reading MLIR's Own Production Pipelines: What This Book's Compiler Is Missing
- 13. Dynamic Shapes: Closing Chapter 12's Biggest Unknown
- 14. A Runtime Shape Check: Closing Chapter 13's Memory-Safety Hole
- 15. A Real Test Suite:
lit,FileCheck, and Proof That the Tests Can Fail - 16. Testing the GPU Path and the Loop Transforms
- 17. Loop Transforms on Dynamic Bounds
- 18. Why Fusion Declines: Reading the Pass, and a Second Bug Found Along the Way
- 19. A Better Abort: Reporting Assertion Failures on stderr
- 20. The Mountain Goat Demo: A Surface Syntax, a Driver, and C++ Calling Compiled Code
- 21. More Operations: Subtract, Hadamard, Divide, Matrix Product, and Scalars
- 22. Broadcasting, Reductions and relu: Enough Operations for a Neural-Network Layer
- 23. Measuring Performance: Does Any of It Make the Code Fast?
- 24. Closing the Gap: A Matrix Product That Walks Memory in a Better Order
- 25. Keeping It Working: Continuous Integration and the Tests the Early Chapters Never Had
- 26. Learning From Data: Gradient Descent in Mountain Goat
- 27. Tensor Contractions as Matrix Products
- 28. Tensor Contractions in Mountain Goat Itself
- 29. Softmax and Attention
- 30. A Small Transformer
- 31. Training a Language Model: Gradient Descent on a Bigram
- 32. Does It Generalize? Held-Out Data, Overfitting, Weight Decay and Greedy Generation
- 33. Backpropagation Through Attention: Training a One-Head Classifier
- 34. Why a Block Has a Feed-Forward Network: Backpropagation Through Layer Normalization, ReLU and Residuals
- 35. Training a Transformer Language Model: Backpropagation Through Causal Attention, Layer Norms, a Feed-Forward Network and Embeddings
- 36. Training Chapter 30's Transformer: Two Heads, Two Blocks, and a Result That Is Not Better
- 37. Inside the LLVM Stage: Reading the IR, and Why a Loop Does or Does Not Vectorize
- 38. Why Compile Time Was Quadratic, and a Pass That Outlines Loop Nests
- 39. Finding the Quadratic: a Differential Profile of the Lowering Pass
- 40. A Model of a Matrix Accelerator: Tiles, a Scratchpad, and What Loop Order Does There
- 41. Compiling Mountain Goat to GA-1: Fusion, Tiling and Why Decoding Is Memory-Bound
- 42. Lowering the Loops Last to First: Testing the Idea Chapter 39 Left Open
- 43. Outlining by Default: What the Calls Cost, and Which Defaults Changed
- 44. Fast-Math Flags from the Compiler: What Reordering Is Allowed to Buy, and What It Did
- 45. Automatic Differentiation: Letting the Compiler Write the Backward Pass
- 46. Second Derivatives: Differentiating the Backward Pass Again