[mhc_post] optimize: 优化 MHC 后处理的泛化分派、访存效率与编译安全 #57
Loading…
Reference in New Issue
No description provided.
Delete Branch "eryi/TileOPs-Metax:feat/mhc-post"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
PR B:[mhc_post] optimize: 优化 MHC 后处理的泛化分派、访存效率与编译安全
小组课题信息
课题名称:面向 MetaX C500 的 MHC 后处理算子泛化与性能分析优化研究
课题完整简介:本课题面向 MHC(Manifold-Constrained Hyper-Connections)后处理链路中的
mhc_post算子,在保持语义不变的前提下,补全原实现对非整块通道、任意扩展分支数、空维度、输入契约和
torch.compile(fullgraph=True)的支持,并针对 MetaX C500 设计通用逐分支 Kernel 与N=4合并分支 Kernel 的 shape-aware 分派。性能评估同时采用独立 PyTorch reference 和未优化 Kernel 两个 baseline:优化后的实现在 15 组 mHC/DeepSeek V4 workload 上相对 PyTorch reference 取得5.811×–14.171×加速,几何平均加速约9.998×;相对未优化 Kernel 有 13 组取得加速,整体几何平均加速约1.385×。除 Kernel 优化外,本课题还修复了原 Benchmark 中会将 TFLOPS 夸大
N*C+1倍的 FLOPs 公式错误,将性能矩阵从 3 个微型 shape 扩展到 15 个真实/泛化 workload,将定向验证从 3 个常规 case 扩展到 38 项测试,并交付“一键正确性检查 → Benchmark → Markdown/CSV 报告”和“15-case 最终 Review 矩阵”工具。成果不只是一个更快的 Kernel,也是一套可复现、可审阅、可继续扩展的 C500 算子性能验证闭环。PR 简要描述
算子名称:
mhc_post/MHCPostOp算子认领 Issue:
[提交前回填:GitLink 算子认领 Issue 编号与 URL]关联 Manifest PR(PR A):
[提交前回填:PR A 编号与 URL]小组:第 4 组
成员:邓悦如、吴习哲、熊明康、左嘉帅
认领类型:主算子
候选清单状态:待优化
候选清单难度:中
改动类型:
feat:新增算子或功能optimize:优化已有实现来源与版本:
TileOPs-Metax/tileops/kernels/mhc/mhc_post.py181801d4be993b757008c857ccbc2befc7061105feat/final-test@84b385cbe3418e41507e914443ec0efa990cb156feat/mhc-post@d1fa7ffb54ccf8b9e99c6f4eeaac45e5c83cf852[提交前回填;bench_analysis.md 本身未嵌入被测 SHA]本 PR 只包含
mhc_post相关改动;共享文件中的mhc_pre不属于本 PR 的实现、测试或性能结论范围。算子接口与语义
x_layer_out[B, C]bfloat16h_post[B, N]float32x_res[B, N * C]bfloat16x_out[B, N * C]bfloat16每个输出元素执行一次 FP32 乘法和一次 FP32 加法,最终转换为 BF16。
核心成果与开源价值
N、非整块 C tail 和完整接口契约的同时,15 组 workload 全部快���独立 PyTorch reference,相对未优化 Kernel 则有 13 组取得加速;相对 PyTorch 的最大加速为14.171×,相对未优化 Kernel 的最大加速为3.113×,大 workload 的估算有效带宽达到1.45–1.50 TB/s。MHCPostBenchmark.calculate_flops()错用近似矩阵乘法复杂度,导致 TFLOPS 被夸大数千至数万倍;本 PR 将 Benchmark、Manifest 和 Roofline 统一到真实逐元素 FMA 口径。N=2/8泛化 workload;定向测试从 3 个常规 case 扩展为 38 项,覆盖数值、边界、异常、分派、缓存和编译路径。scripts/mhc_bench_report.py可零参数依次执行正确性测试和 Benchmark,并从原始日志自动生成 Markdown/CSV;审阅归档中的mhc_post_final_matrix.py可生成 15-case dispatch、配置、源码哈希、barrier、输出契约与逐元素 oracle 结果。AGENTS.md固化mhc_post审阅范围、正确性基准、性能口径、验证命令和问题报告格式,防止共享文件中的mhc_pre结果被误纳入本 PR。1. 本次 PR 优化方案
优化前的主要问题
c_x // block_C构造 C 维 grid,C不是block_C整数倍时尾部元素无法覆盖。N,并为x_res、x_out分配 shared memory;资源开销随N增长,且单次使用的数据存在冗余暂存。N、最小 shape、空维度、跨 shape 缓存复用等完整契约。x_layer_out的[B,C]shape,与真实[B,N*C]输出不一致;coldtorch.compile(fullgraph=True)路径不安全。2*B*(N²*C²+N*C),而真实计算只有2*B*N*C,会把 TFLOPS 夸大N*C+1倍。原 memory 统计也漏掉 batch、dtype 字节数与h_postFP32 流量。采用的优化方案
T.ceildiv与边界 mask 覆盖任意B/N/C;整块 shape 使用T.copy,不规则 shape 使用带 mask 的加载。N == 4 && B >= 8:选择 all-N4 2D Kernel,一个 program 合并四个分支并复用x_layer_out。N的通用 3D Kernel。h_post与可复用的x_layer_out保留在 shared memory;只使用一次的x_res直接从 global memory 读取,x_out直接写回。block_x_b={1,8,64}、block_C={64,128}、threads={128,256};num_stages=1仅为配置与 ABI 兼容保留。2*B*N*C,按实际 dtype 字节数统计x_layer_out/h_post/x_res/x_out,并将 Benchmark/Manifest 扩展到 15 个 mHC/DeepSeek V4 decode、prefill 与N=2/8泛化 workload。profile_run.log,同一份结构化数据同时驱动延迟换算、两个 baseline 对比、block/shared/HBM/FLOPs/带宽利用率分析和可选 CSV,避免硬编码 15 行数据;Review 矩阵工具记录每个 case 的 dispatch、配置、生成源码 SHA256、barrier 数、输出 metadata、最大误差和逐元素 PyTorch oracle 结论。关键代码或配置变更
tileops/kernels/mhc/mhc_post.pytileops/ops/mhc.pytests/ops/test_mhc.pybenchmarks/ops/bench_mhc.pytileops/manifest/sequence_modeling.yamlscripts/mhc_bench_report.pyMHCPostOp,自动生成 Markdown/CSV、双 baseline 对比、资源、访存与带宽分析mhc_post_final_matrix.py(审阅归档根目录)AGENTS.md优化实验结论
N分支、复用 C tile,并减少 program/wave 与重复访存指令。N与非整块 tail 的正确性;最终bench_analysis.md中N=2、N=8workload 相对 PyTorch reference 分别达到10.596×与8.329×。O(B*N²*C²)恢复为与 Kernel 语义一致的O(B*N*C);这使性能数字、Profiler 解释和 Roofline 判断第一次处于同一可信口径。exit 137。MHCPostOp/tileops数据,并同时与独立 PyTorch reference、未优化 Kernel 两个 baseline 比较。2. 精度验证
精度对比基准实现:独立 PyTorch reference。未优化 Kernel 仅作为第 3 节的性能 baseline,不作为正确性 oracle。
参考结果最终转换为
bfloat16,不复用 TileLang Kernel 的实现逻辑。测试命令:
归档 C500 运行使用的等价独立测试文件命令:
测试矩阵:
(B,N,C)=(1,4,1280)、(2,4,1920)、(4,4,2560)。(1,1,1)、(2,4,1024)、(1,3,128)。C=65/127/129。B=7 -> 8 -> 7、N=4,并验证N!=4回退。B=0、N=0、C=0。C64/C128 × T128/T256。torch.compile(fullgraph=True)。x_layer_out/x_res=bfloat16、h_post=float32、x_out=bfloat16。误差范围:
rtol=1.6e-2,atol=1.6e-2。归档验证结果:
38 passed in 30.24s03 passed, 12 deselected07 passed, 8 deselected013 passed, 2 deselected015 passed0benchmarks/tests18 passed0tests/test_ops_manifest.py7 passed0scripts/validate_manifest.py --check-op MHCPostOp0git diff --check0pre-commit run --all-files127提交前完整校验命令:
证据边界:
8ba899b标识该轮测试源码;日志没有记录其完整 SHA,不能自行补全。84b385cbe3418e41507e914443ec0efa990cb156;Benchmark 脚本来自d1fa7ffb54ccf8b9e99c6f4eeaac45e5c83cf852。3. 性能数据【必填】
测试环境
2.8.0+metax3.7.1.3torch.version.cuda兼容字段11.60.1.10+cuda.gitf549117c,路径/opt/tilelang-metax-v0.1.10macatorch.cuda.get_device_capability()的兼容值为(8,0),这里只用于仓库门禁,不代表 NVIDIA Ampere。性能协议与复现命令
BenchmarkBase协议:最终性能数据来源:
/data/logs/mhc_post_202608051533.log,报告生成时间2026-08-05 07:36:10。报告行没有出现 event fallback 标记。本节设置两个性能对比 baseline:
一键报告与 Review 证据生成
提交的报告脚本不需要手工拼接表格。零参数运行时,它会先执行
mhc_post正确性门禁,只有测试通过才执行完整 Benchmark,随后解析profile_run.log并生成统一口径的 Markdown 报告:也可以对已有日志离线生成 Markdown 与 CSV 宽表:
审阅归档还提供最终矩阵工具,在真实 C500 上逐一检查 15 个 workload,并生成机器可读 Review 证据:
该矩阵不仅记录 pass/fail,还记录 public selector 实际选择的 mapping、配置、生成源码 SHA256/大小/barrier 数、输出 shape/dtype、最大绝对误差,以及全元素独立 PyTorch oracle 结论。这样维护者可以复核“运行的是哪份设备代码”,而不只看到一张手工整理的性能表。
Benchmark TFLOPS 口径修复
原 Benchmark 的 FLOPs 公式为:
但
mhc_post的每个输出元素只执行一次乘法和一次加法,真实公式应为:因此:
在本次 15 组 workload 中,旧公式会将 TFLOPS 夸大约
4,097–28,673倍。该问题会直接扭曲算力利用率和 Roofline 判断,并非单纯的显示误差。本 PR 同时完成:2*B*N*C,与 Kernel 逐元素 FMA 语义及 Manifest 完全一致;x_layer_out/x_res/x_out与 FP32h_post的真实字节口径;两个 baseline 与优化后
mhc_post的 15 组结果下表同时给出两个比较对象。“优化后”是
tileops行;“独立 PyTorch baseline”是torch-ref行,其加速比定义为torch-ref_us / tileops_us;“未优化 Kernel baseline”是优化前实现,其加速比定义为base_us / tileops_us。因此,加速比大于1×表示优化后实现更快,小于1×表示优化后实现存在回退。(B,N,C)(1,4,1280)(2,4,1920)(4,4,2560)(32,4,4096)(32,4,7168)(128,4,4096)(128,4,7168)(512,4,4096)(512,4,7168)(1024,4,4096)(1024,4,7168)(8192,4,4096)(4096,4,7168)(128,2,2048)(128,8,1024)汇总结论:
5.811×–14.171×,中位数10.596×,几何平均约9.998×。0.917×–3.113×,中位数1.231×,几何平均约1.385×。medium和v4-flash-decode-s两组分别为0.972×和0.917×,即存在约2.8%和8.3%的轻微回退。1.45–1.50 TB/s,约为完整 C5001843 GB/s理论参考带宽的78.5%–81.4%。N=2/8泛化 workload 已分别达到5.70 µs和7.00 µs,不能继续使用上一版 PRB 的20.0 µs、35.5 µs数据。带宽口径说明:
bench_analysis.md“资源与性能分析/表 3”的估算 HBM 流量除以优化后延迟,包含 Kernel mapping 导致的x_layer_out读放大,未扣除 L2 命中。bench_analysis.md前部原始bandwidth_tbs列与后部按字节重算结果明显不一致(all-N4 路径约 2 倍,通用路径还叠加了x_layer_out读放大);本 PR 不使用该原始列作为 Roofline 证据。base_us / tileops_us计算,并与 PyTorch reference 对比分列展示,避免混淆两种 baseline。Roofline 公式与实测
Manifest 公式:
公式分别计入
x_layer_out读取、h_postFP32 读取、x_res读取和x_out写回。典型N=4shape 的算术强度约为0.444 FLOP/Byte,属于低算术强度算子。本次使用完整 C500 的
1843 GB/s理论 DRAM-L2 参考带宽,不进行 sGPU 折算。打包证据没有建立同一软件栈下的实测BW_peak微基准或 FP32 vectorP_peak,因此下表报告的是AI × 1843 GB/s的内存参考 Roofline,不将其包装成已经校准的完整 Roofline。(B,N,C)(128,4,4096)(8192,4,4096)(4096,4,7168)(128,2,2048)(128,8,1024)mcProfiler 瓶颈分析
Profiler 证据来自最终打包目录
mcProfiler-v4 flash and pro,覆盖 DeepSeek V4 Flash/Pro 的 10 个 decode/prefill workload。每个目录均包含 raw JSON、report.txt/json/csv、Roofline 图、访存图和 PDF。report.txt本身没有记录工具版本;同一最终打包归档中的 profiler metadata 记录为 mcProfiler3.8.1.4、build20260715214228。代表性计数器:
瓶颈判断与优化对应关系:
21.5%–35.8%;继续减少 launch、workgroup 和指令开销比增加计算吞吐更重要。99%降到大 decode/prefill 的0.06%–2.02%,Profiler 带宽升到1.31–1.46 TB/s,Benchmark 估算带宽达到1.45–1.50 TB/s。35.89%–53.22%,STE 只有1.07%–4.09%;这与逐元素 FMA、低算术强度和 load/store 主导的静态判断一致。100%,当前 shared/block 仅约0.5–4.1 KiB,远低于 C500 的64 KiB/block上限。x_layer_out,减少重复 program/wave 和指令;x_res直接读取、x_out直接写回则避免无复用价值的 shared staging。4. 提交自检清单
torch.compile(fullgraph=True)git diff --check、Manifest 校验、Benchmark tests 与 Manifest tests 已有归档通过证据tests/ops/test_mhc.py -k "mhc_post"与 15 组 Benchmarkpre-commit后执行pre-commit run --all-filesMHCPostOpManifest 状态由当前审阅快照的spec-only更新为implementedStep 1:
From your project repository, check out a new branch and test the changes.Step 2:
Merge the changes and update on Gitea.