linalg/mmm: naive tile walk when L2 is undetectable#2469
Conversation
The single-thread block budget fell back to a 256 KiB guess when the cache probe found nothing, which over-blocks the very cores that fallback is for: small embedded arm parts whose cache the OS does not expose and whose tiny L1 an L2-sized block blows, making the blocked walk slower than the naive stream the hardware prefetcher handled well. The budget helpers now return None on an unknown cache and the walk takes the naive loop (edge 1) there, so only cores with a detected L2 get the blocking they were tuned for.
|
ping @czoli1976 |
|
🔴 Bench vs main — 12 speed regression(s) Reference: main nightly, latest 2026-07-13 (0d old) · PR Speed — evaltime · prefill · decode
🟢 4 improvement(s)
lower is better except prefill/decode (tok/s) · adaptive thresholds (max(floor, k×noise) vs the series' own history) · single-shot vs nightly reference · full report → run |
|
Mmmm tricky one. I was chasing the inception regression, and I broke everything else. |
|
At which point did you detect the regression? which PR? is the eval time the concern or wha? |
|
The tricky part is that "undetectable L2" isn't one workload — the little cores split on what they want:
So fn l2_block_budget_bytes() -> Option<usize> {
let ci = crate::cache::cache_info();
// detected L2 → tuned budget; hidden → block to L1, not an L2-sized guess
// that blows L1, and not naive which strips the reuse the GEMM-bound models need.
Some(tier_budget_bytes(ci.l2, 1, 3).unwrap_or_else(|| ci.l1_data_or_default()))
}That keeps a real but small tile — shouldn't blow L1, should hand mobilenet/tdnn back their reuse without re-inflating inception. The L1 fraction is a knob to tune. Pure hypothesis on my end though: I've got no a7/a53/a55 to bench on, so it'd need a run through the bot to confirm it lands in the middle instead of just tilting the see-saw the other way. |
|
My imaginary friend seems confident here |
|
I'm trying to recover performance that slipped on long term time series that i was not monitoring very closely (e.g. inceptionv3 on intel). I think these regressions started before you started working on tract, and I'm trying to address a wider bag of performance waste with #2478 . It looks like a simple linear model can equal the choices of the DNN on the cortex devices, so I'm looking into generalizing the approach. I'll come back to the cache once I'm convinced we're not picking stupid kernels to start with. |
The single-thread block budget fell back to a 256 KiB guess when the cache probe found nothing, which over-blocks the very cores that fallback is for: small embedded arm parts whose cache the OS does not expose and whose tiny L1 an L2-sized block blows, making the blocked walk slower than the naive stream the hardware prefetcher handled well. The budget helpers now return None on an unknown cache and the walk takes the naive loop (edge 1) there, so only cores with a detected L2 get the blocking they were tuned for.