<< All versions
Skill v1.0.0
currentAutomated scan100/100blaizzy/mlx-vlm/benchmarking
──Details
PublishedOctober 24, 2026 at 08:26 PM
Content Hashsha256:c8751953842bcc5e...
Git SHA41bef911b414
──Files
Files (1 file, 4.1 KB)
SKILL.md4.1 KBactive
SKILL.md · 81 lines · 4.1 KB
version: "1.0.0" name: benchmarking description: Use this skill when the user wants to benchmark an MLX-VLM change and present the numbers in a PR — fork-vs-main A/B comparisons, isolated-module micro-benchmarks, median-of-N timing with warmup, peak-memory reporting, correctness checks, parameter sweeps, and self-contained reproducible bench scripts to paste into a PR description.
Benchmarking & PR A/B Testing
Use this workflow to produce credible, reproducible performance numbers for a PR.
Rules for a trustworthy benchmark
- Median of N (not mean), with a few warmup iterations discarded.
- Call
mx.eval(...)/mx.synchronize()before stopping the timer (MLX is lazy — untimed work hides otherwise). - Report peak memory via
mx.get_peak_memory()/1e9(GB); reset withmx.reset_peak_memory()if available. - Include an inline correctness check — a benchmark that computes the wrong thing is meaningless. Assert the new path matches the baseline (exactly in the degenerate limit, or within tolerance).
- Sweep one parameter (sequence length, batch, tokens, layers) and print a markdown table with
flush=True. - Prefer a random-init synthetic model (tiny config) so the script needs no checkpoint download and runs on a fresh checkout.
- State the hardware (Apple-Silicon chip + RAM). A model must fit in RAM; isolate the module under test with random weights if the full model won't fit — don't run large models on an 8 GB machine.
Fork-vs-main A/B (paste into the PR body)
Clones upstream main and your fork, runs the identical bench on both, and joins into a speedup table:
bash
#!/usr/bin/env bash# <feature> perf: upstream main vs fork, random-init tiny <model>, swept over <param>.set -euo pipefailW=$(mktemp -d)git clone -q --depth 1 https://github.com/Blaizzy/mlx-vlm "$W/main"git clone -q --depth 1 https://github.com/<you>/mlx-vlm "$W/fork"cat > "$W/b.py" <<'PY'import time, numpy as np, mlx.core as mxfrom mlx_vlm.models.<model> import Model, ModelConfigcfg = ModelConfig(...tiny config...) # small enough to fit in RAMm = Model(cfg); m.eval(); mx.eval(m.parameters())def ms(T):c = m.make_cache(); p = 0while p < T: # chunked prefill avoids OOMn = min(256, T - p)mx.eval(m(mx.array(np.random.randint(0, cfg.vocab_size, (1, n))), cache=c).logits); p += nfor _ in range(4): mx.eval(m(mx.array([[0]]), cache=c).logits) # warmupt = time.perf_counter()for _ in range(20): mx.eval(m(mx.array([[0]]), cache=c).logits)return (time.perf_counter() - t) / 20 * 1e3for T in (16384, 32768, 65536):print(T, round(ms(T), 2), flush=True)PYrun() { uv venv -q "$1/.venv"; uv pip install -q -e "$1" --python "$1/.venv/bin/python"; "$1/.venv/bin/python" "$W/b.py"; }run "$W/main" > "$W/m.txt"run "$W/fork" > "$W/f.txt"echo; printf "| param | main | fork | speedup |\n|--:|--:|--:|--:|\n"join "$W/m.txt" "$W/f.txt" | awk '{printf "| %d | %.2f ms | %.2f ms | %.2fx |\n", $1, $2, $3, $2/$3}'
Isolated-module micro-benchmark
For one function/kernel (time + peak mem + correctness), swept over a param:
python
import time, statistics, mlx.core as mxdef bench(fn, it=30, warm=5):for _ in range(warm): mx.eval(fn())mx.synchronize()if hasattr(mx, "reset_peak_memory"): mx.reset_peak_memory()s = []for _ in range(it):t0 = time.perf_counter(); mx.eval(fn()); s.append((time.perf_counter() - t0) * 1e3)return statistics.median(s), mx.get_peak_memory() / 1e9# build inputs; assert new == baseline in the degenerate limit; then print a swept markdown table.
Presenting in the PR
- Paste the exact script (self-contained) plus the resulting markdown table, and state the chip/RAM and mlx-vlm commit.
- Report both latency and peak memory — a speedup that blows the memory budget isn't a win.
- If comparing against another PR (e.g. an earlier version), link it and use the same script for both.
- Keep the repro script in scratch (not committed); only the script text + table go in the PR body.