MTT S4000 FP16 GEMM 优化实战:逼近 mcc 编译器的物理上限
我参加摩尔线程 GEMM 矩阵挑战赛——这篇文章是完整的 三段式工程复盘。
第一段:开发阶段(§2-§7)。 从官方两份示例(
example_naive.mu标量版 ~0.5 T、example_tensorcore_basic.muWMMA 起点)出发,我自己主导方向 + AI 辅助快速生成代码,70+ 个版本(historical_versions/team3_gemm_v1→v78)反复迭代:64×64×32 → 128×128×32 双缓冲 → 256×256×32 mega tile → 32×32×16 WMMA。整条路径覆盖 tile 拉大、协作加载、双缓冲流水线、MP22 原生 32×32×16 fragment 等所有 GEMM 优化套路。4 个 legacy 正确性用例每一版都过、8k 性能爬到 ~90 TFLOPS,在原评分脚本上拿到满分 100/100,1 月 22 日提交。本仓库historical_versions/下 ship 了其中 6 个关键版本(v1 / v20 / v59 / v68 / v70 / v76),读者可以用grader/test_cases_legacy.json复现它们当年的状态——其中 v68 在 fresh build 上实测 93.12 TFLOPS,4 legacy 用例 max_err = 0,总分 100/100。第二段:塌陷(§8)。 评审期脚本里新增了一条
8192×8192×16384的正确性测试correctness_8k,我那个 90T 提交版首次跑就 fail——75% 输出元素错,max_err ≈ 36。深挖发现:原 dispatch 把M, N ≤ 1024的 4 legacy 用例全部路由到一条独立的 16×16×16 单 warp 安全内核,而追性能的 256×256 mega tile 路径从未被正确性测试覆盖过。换句话说,90 TFLOPS 是建立在一个从未被校验的代码路径上的虚高数字——同一个 v68 用 4-用例配置看起来 100/100 满分,用 5-用例配置直接挂correctness_8k。这一对矛盾结果你可以在仓库里 fresh clone 后用两条命令亲眼复现(README 末尾给出)。第三段:重建(§9-§25)。 4 月 3 日下午到 4 月 8 日,6 天时间从头建。物理 warp = 128 修复(0 → 22 T)、stride-33 bank conflict 消除(22 → 48 T)、M-first 蛇形 CTA 排序(48 → 54 T)、256×256×32 + 1024 线程(54 → 57 T)、postRA + ILP 调度 flag(57 → 67 T)、FenceSetting=mixed(67 → 73 T)、4 个 load-store flag(73 → 73.8 T)。最终
participants/team03_gemm_work.mu通过全部 5 个正确性用例(包括correctness_8kmax_err = 0)、绝对性能 73.8 TFLOPS / muBLAS 94% / 官方 100/100。结论:73.8 TFLOPS 不是"代码还能更聪明",是触到了当前 mcc 3.1.0 + S4000 +
load_matrix_sync组合的编译器物理上限——VLIW 165/165 满打包(0 空 slot)、C++ 双缓冲 5 种方案全部低于单缓冲基线、手动 fragment 加载被 MMA 专用寄存器 bank 约束封死。过程中定位到两个可以直接立项的摩尔线程编译器/头文件 bug:machine-schedulerpass +internal-regs-ra的 WMMA 操作数 bypass 冲突(73 → 79 T 的差距)、crt/mma.h:761的 fragment 元素数定义可能多分配 3 倍寄存器。所有数字、代码、bug、复现命令都可以在本仓库里逐项交叉验证。