Codegen parameter sweep
Blocking is a real compiler knob; LMUL is implied by the vector types emitted, so sweeping it sweeps nothing. Record the plateau.
What you can actually sweep
In the compiler path there is no LMUL argument on the command line: the vector types the vectorizer emits imply LMUL, and vsetvli insertion derives vtype from them. What you can turn: the tile triple handed to the tiling pass, the vectorization and unroll choices, and whatever LMUL knob your release exposes through -mllvm. Find it rather than copy it: llc -march=riscv64 --help-hidden | Select-String -Pattern 'lmul|vector-bits'. The spelling has moved between releases, and a flag from a blog post is a silent no-op.
One row per configuration
printf 'bm\tbn\tlmul\tmedian\tspread\n' > sweep.tsv
for bm in 4 8 16; do
for bn in 8 16 32; do
for lm in 1 2 4; do
TILE=$bm,$bn,32 LMUL=$lm ./scripts/run_bench.sh | tail -n +2 \
| sed "s/^/$bm\t$bn\t$lm\t/" >> sweep.tsv
done
done
done
The script passes TILE into the tiling pass and LMUL into the codegen flag, and it must fail loudly when either is unused. hyperfine is fine for a whole-process comparison, but per-configuration rows come from the harness so the shape and reference check travel with the number.
Two ways to read the file
Across tiles: for each tile, which LMUL wins, and by how much relative to the spread. Across LMUL: whether the curve is a plateau or a knife edge. A configuration is robust when several neighbouring values reach the same level; a lone maximum on a surface of noise is a measurement to repeat, not a finding.
Things that break
The knob is read when the pipeline is built and the benchmark reuses a cached .mlir, so every row is the same code and the surface is flat. A flat line for a parameter that should matter is the tell; diff mlir-opt output at both extremes with grep 'vector<' before trusting it. The other failure is a rebuild between rows: make’s timestamps leave the binary from the previous configuration while the label says the new one, so the sweep compares two builds and calls it a parameter.
Sources
- MLIR pass documentationdocs · LLVM 23
- hyperfine: a command-line benchmarking tooldocs
- Active benchmarkingblog
A version records the documentation the claim was checked against, not a house pin. Confirm flags with --help on the release you installed.
Check yourself
Two sweep rows differ by more than their spreads, but both neighbours are flat. What do you do?
The sweep is flat for every LMUL value. What is the first thing to check?
Why does a compiler-path sweep need the pass pipeline printed next to each row?