You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Optimization] Zen 4 / EPYC Macro-Blocking (P, Q, R) tuning utilizing COOPERLAKE kernels #5837
I have been profiling SGEMM performance on an AMD Zen 4 (EPYC 9334) server and noticed that the build system accurately falls back to the COOPERLAKE target to leverage the AVX-512/BF16 instructions. While the micro-kernels run flawlessly, the default COOPERLAKE macro-blocking parameters (P, Q, R) seem to bottleneck on AMD's 32MB L3 CCX boundaries.
I recently ran Bayesian Optimisation parameter tuning specifically targeting the macro-blocking dimensions for this hardware. Without altering any assembly, adjusting the blocking limits yielded a performance jump from ~2.8 TFLOPs to ~3.0 TFLOPs for square matrices around N=8192. I also observed similar improvements on smaller square matrices, though performance on heavily skewed shapes (skinny/wide matrices) remained largely unchanged.
It appears the default COOPERLAKE blocking parameters—which assume a monolithic L3—might be causing some cache contention on this 32 MB L3 Zen 4 CCX boundary. The tuned parameters seem to eliminate that L3 thrashing.
Before I open a PR or formalise these values into param.h, I want to confirm this is the right direction or am I missing something.
Thanks for your time and guidance!
Kilaru Vasu Deva.
Sounds right, but would probably require cloning the COOPERLAKE target to create a dedicated ZEN4. I guess you could try if
adding a conditional inside the COOPERLAKE section of param.h would be sufficient, something like
if L3_SIZE == 33554432
#define SGEMM_DEFAULT_P = <your p for zen4>
...
else
#define SGEMM_DEFAULT_P = 640
...
endif
```
and similarly set `TABLE_NAME.sgemm_p` etc. depending on the value of `l3` in the COOPERLAKE section of `kernel/setparam-ref.c` for the DYNAMIC_ARCH case. (I do wonder how many different L3 cache configurations we'd have to cater for across the "ZEN4" processor family ?)
I shall try the conditional workaround to see if it's sufficient. Based on my search and Zen4 Wikipedia table, the majority seem to use the standard 32 MB per CCD, with two other variants: 96MB (per CCD with 3D V-Cache) and 16/8 MB (APUs).
Also, I think I could scale the new values of P, Q, R accordingly for DGEMM, BFGEMM, etc.
@martin-frbg I tried a few things. I see that the L3_SIZE macro in param.h and the get_l3_size function in setparam-ref.c track L3 cache size as a total over all the chiplets. The following conditioning works for cases with more or fewer than 4 chiplets (9334 has 4). I believe this covers a majority of the Zen4 family.
Activity
martin-frbg commentedon Jun 15, 2026
Sounds right, but would probably require cloning the COOPERLAKE target to create a dedicated ZEN4. I guess you could try if
adding a conditional inside the COOPERLAKE section of
param.hwould be sufficient, something likeVasudeva-bit commentedon Jun 15, 2026
I shall try the
conditionalworkaround to see if it's sufficient. Based on my search and Zen4 Wikipedia table, the majority seem to use the standard 32 MB per CCD, with two other variants: 96MB (per CCD with 3D V-Cache) and 16/8 MB (APUs).Also, I think I could scale the new values of P, Q, R accordingly for
DGEMM,BFGEMM, etc.Vasudeva-bit commentedon Jun 19, 2026
@martin-frbg I tried a few things. I see that the
L3_SIZEmacro inparam.hand theget_l3_sizefunction insetparam-ref.ctrack L3 cache size as a total over all the chiplets. The following conditioning works for cases with more or fewer than 4 chiplets (9334 has 4). I believe this covers a majority of the Zen4 family.&
I shall make a PR based on this. Kindly let me know your comments, if any.