bench: roofline datapoint for Apple M2 Pro (Mac mini, cliffs + perf) - #145
Merged
Merged
Conversation
Numeric-cliffs run on a Mac14,12 Mac mini, macOS 26.5.2 (25F84), on AC at automatic energy mode, from a clean checkout of 263e02f. The slice crop-DMA clamp is present here: |value| > 4094 goes to inf, where the M5 Pro is exact. That is the first confirmation of the pre-A16 clamp from an M-series chip in this table, and it brackets when the clamp disappears. matmul inf-cliff and reduce exactness both match the M5 Pro (~32759 across K in {4,8,32,64,128}, and integer row-sums exact through 2048, first wrong at 2049 -> 2050), so those two look architecture-wide rather than per-generation. Perf rooflines not included: --perf needs an interactive sudo for powermetrics.
axiom-of-choice
commented
Aug 1, 2026
| Add yours: `PYTHONPATH=. python3 bench/roofline_suite.py --contributor <your-gh-handle>`, commit the JSON it writes under `bench/results/rooflines/`, regenerate this file with `python3 bench/aggregate_rooflines.py`, and open a PR. See [`rooflines/README.md`](rooflines/README.md). | ||
|
|
||
| Thanks to [@sbryngelson](https://github.com/sbryngelson) for contributing datapoints. | ||
| Thanks to [@axiom-of-choice](https://github.com/axiom-of-choice), [@sbryngelson](https://github.com/sbryngelson) for contributing datapoints. |
Contributor
Author
There was a problem hiding this comment.
@sbryngelson Feel free to edit this contribution sections
Replaces the cliffs-only submission with a --perf run (sudo granted) from a clean checkout of 263e02f. Measured ANE peaks: 3.26 TF/s fp16 GEMM, 1379 GFLOP/s/W, 1.0 GB/s streaming bandwidth. Two columns stay empty, for reasons worth recording rather than hiding: Ridge and the table's GEMM/bandwidth cells come only from roofline_analysis.py, which fails on any --perf run (filed as sbryngelson#146): PERF_FAST passes --quick, --quick omits GPU from the sweeps, and load_ceilings iterates a hardcoded CPU/GPU/ANE. The underlying numbers are in this report's perf_rooflines regardless. Decode is empty for a different and more interesting reason: on M2 the decode model's [1,32000] vocab projection exceeds ANE family 3's 16384 dimension cap, so both batch rows return NotImplementedError. That is a real per-generation limit, not a harness failure; the same model fits on M5.
The previous commit message blamed --quick for omitting GPU from the sweeps. That was wrong: GPU is present throughout this run. roofline_analysis fails because layer_norm did not compile on the ANE, so that one archetype's peak block has no 'ane' key while load_ceilings iterates a hardcoded CPU/GPU/ANE per archetype. Filed and corrected in sbryngelson#146; the measured numbers are unaffected.
Open
33 tasks
This was referenced Aug 1, 2026
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Datapoint for #137. Adds Apple M2 Pro to the map.
Run from a clean checkout of
263e02f(dirty: falsein the report), Mac14,12 Mac mini, macOS 26.5.2 (25F84), AC, automatic energy mode.The interesting one: the slice clamp is present on M2 Pro
The issue says the pre-A16 crop-DMA clamp is gone by A16/M5, and this is the first M-series confirmation in the table that it is there on an earlier chip. So the boundary is now bracketed from both sides rather than only asserted on one.
The other two look architecture-wide, not per-generation
Both match the M5 Pro:
K in {4, 8, 32, 64, 128}, consistent withfp16_max/2independent of reduction depth, which is what I measured by hand in matmul saturates at fp16_max/2 (~32752); two transpose-fed cases return inf even below that #115 before this tooling existed.<= 2048, first wrong at 2049 returning 2050.Worth noting the second one against history: when I probed the integer reduce by hand on this same machine (#115, 2026-07-31) it looked exact past 2048 and I reported it as not reproducing. The suite disagrees, and the suite is right. My hand probe kept the addends small enough that the sum stayed on the exact fp16 grid, so it never actually crossed the boundary the metric measures. The harness picks the boundary case properly. Retracting that half of my earlier report; the per-generation split there was my measurement artifact, not silicon.
Perf half (added)
Ran
--perfwith sudo from a clean tree. Measured ANE peaks:Two table cells stay empty, both for reasons worth stating rather than hiding.
Ridge, and the table's GEMM/bandwidth cells, are blank because of a harness bug I hit and filed as #146.
aggregate_rooflinesreads those three fromroofline_analysis.py, and that step raisedKeyError: 'ane'. Cause:layer_normfailed to compile on the ANE at these shapes, so the bandwidth script correctly recordedane_gbps: Noneand that archetype'speakblock has noanekey, butload_ceilingsiterates a hardcoded("CPU","GPU","ANE")per archetype and raises. Not specific to this machine: any run where one archetype loses one engine loses the whole synthesis. The measured numbers above are in this report'sperf_rooflinesregardless, so nothing is lost, only unsynthesized. Once #146 lands, re-runningaggregate_rooflines.pyfills those cells with no new measurement.Decode is blank for a genuinely different reason, and it is a datapoint. On M2 the decode model's
[1, 32000]vocab projection exceeds ANE family 3's 16384 max dimension, so both batch rows return:That is a real per-generation capability limit, not a harness failure. The same model measures fine on your M5 (117 tok/s in the table), so
bench/decode_measurement.pycurrently cannot produce a decode number on family-3 silicon at all without tiling the projection. Worth deciding whether the harness should tile it, or whether the table should distinguish "not measured" from "cannot run on this family".Not included
Not included
Nothing further. Both halves are in.
Files
bench/results/rooflines/roofline-apple-m2-pro-Mac14_12-723396ad9091-1c1aa174.json(new)bench/results/ROOFLINES.md(regenerated withbench/aggregate_rooflines.py, now 2 machines)