diff --git a/BMM/BMM_Theory/docs/03_测评报告/BMM_Theory软件测评报告_v2.0.md b/BMM/BMM_Theory/docs/03_测评报告/BMM_Theory软件测评报告_v2.0.md new file mode 100644 index 0000000..d51b957 --- /dev/null +++ b/BMM/BMM_Theory/docs/03_测评报告/BMM_Theory软件测评报告_v2.0.md @@ -0,0 +1,213 @@ +# BMM/BMM_Theory 理论最优实现分析软件 测评报告(第二轮 · 整改后复评) + +- 测评对象:`git.magicnetworld.com/admin/matmul-analysis` 仓库 `BMM/BMM_Theory`(软件包 `bmm_theory`) +- 本轮基准:HEAD `99a25a6b42efa63689f21ae53a7cc467c2fca79f`(main,2026-09-03),相对上轮基准 `d36e224` 共 **33 个整改提交** +- 测评方式:整改 diff 逐文件审查 + issue 逐条复测 + 全量运行/单测 + 同分布压力回归(与上轮同种子同分布对比)+ 口径深查 +- 说明:上轮报告为 `docs/03_测评报告/BMM_Theory软件测评报告_v1.0.md`(2026-09-03 入库,commit d36e224);本轮为整改后的复评。 + +--- + +## 0. 结论摘要(TL;DR) + +**整改诚意与质量都很好:上轮提出的 7 个 issue(#4–#10)中 6 个实质闭环,1 个(#9 StreamK 计账口径)修复方向正确但引入新疑点,需二次复核。** 软件从"可跑但自相矛盾"升级为"可自检、自洽率大幅提升"的可信工具雏形。 + +关键数字对比: + +| 指标 | v1(上轮) | v2(本轮) | +|---|---|---| +| 单元测试 | 17/17 | **23/23**(新增 6 条 issue 回归) | +| P0 崩溃(K=1 且 B<128) | 必崩 AttributeError | **不崩溃**,占位标注"[无方案]" | +| 典型 LLM 形状自检不可行率(6000 例) | **18.0%**(1079 例) | **0.0%** | +| 宽范围随机自检不可行率(8000 例) | **6.0%**(480 例) | **0.2%**(16 例,全部为极端瘦长 MergeBatch 且自检已显式标注) | +| 生成结果可复现性(vs 仓库固化示例) | 0 差异 | 0 差异 | +| 推荐→评估回灌 feasible | 94% | **99.8%**(16/8000 标注违规但仍推荐) | +| NaN/负时延/崩溃 | 无(P0 区除外) | 无 | + +**遗留问题(详见 §5)**: +1. 【P2,建议跟进】issue#9 的修复引入新口径问题:StreamK 部分和写出被**双重计账且按单核串行假设高估 32 倍**——demo case 总时延从 9.96us 变为 55.03us、瓶颈变成 FIXPIPE(51.6us),而同一批字节在 `t_reduce` 内仅计 1.61us。该数字已被作者固化进 examples,建议复核。 +2. 【P3】K=1 且 B<128 区域仍**无任何理论方案**(占 K=1 域的约一半),现以"无方案占位"标注兜底(崩溃已解决、可接受),建议后续补 AIV 单缓冲/Cube 兜底方案。 +3. 【P3】MergeBatch 极端瘦长 case(M 或 N 很小 × 大 B)仍有 0.2% 生成不可行方案——`b0` 选择未把 L0A/L0B 容量纳入上限;现已被生成自检显式标注(不再静默矛盾)。 +4. 【P3】负/零矩阵维度无输入校验,静默产出无意义方案;FIXPIPE 建议文案对 StreamK(部分和 4B)给出 fp16/fp8 减半的误导提示。 +5. 【P3】过程噪音:整改过程中 11 个 commit 误提交临时文件(bug1.csv/t.csv 等)后删除,建议加 .gitignore。 + +**总体评价:6.2 → 约 7.6/10。** 架构与理论映射维持高水准;内部一致性与鲁棒性是本轮最大提升(单一约束源 + 生成自检是正确架构决策);剩余扣分集中在 StreamK 时延口径复核、输入校验与若干边界覆盖。 + +--- + +## 1. 本轮整改概览(33 commits) + +| 主题 | 主要提交 | 对应 issue | +|---|---|---| +| 新增 `bmm_theory/constraints.py`(170 行,单一约束源 + 生成侧收敛辅助) | 16a84ac | #5 #6 共性根因 | +| `router.py`:生成后自检 `_wrap_checked` + 无方案兜底 `_no_plan` | dad4585 | #4 #5 | +| `evaluator.py`:约束校验委托单一约束源 | 0c19d99 | #5 | +| `__main__.py`:plan=None / timing=None / 自检违规打印防护 | b57ba57 | #4 | +| `io_csv.py`:out_nd 解析 + A/B dtype 不一致告警 + 建模边界说明 | 9ef240f | #7 #8 | +| `timing.py`:REDUCE 移出稳态 max()(`reduce_serial` 约定) | 933b428 | #9 | +| `branches/stream_k.py`:fixpipe 改按部分和 4B、显式 reduce_serial | f756729 | #9 | +| `branches/asw_basic.py`:降核 base_k 按 dtype 容量反推(clamp 同源);k_l1 小 K 不切 | e6aa792 | #5 | +| `branches/iter_batch.py`:L0 tile 长宽比跟随 + L0C/L0A/L0B 同源收敛 | c0b358f | #5 | +| `branches/merge_batch.py`:新增条件 2b(合并后最小 K 粒度下 L0A/L0B 可驻留) | 1385d01 | #5 | +| README / docs/01_软件架构.md 同步 6 分支现状 + 约束模块/归约口径文档 | 7bcacef / 593ffcf | #10 | +| examples 两个结果 csv 按新模型重生成 | bbef360 / cff5665 | — | +| tests 新增 `TestIssueRegression` 6 条 | 87b7be5 | #4–#9 | +| 误提交临时 csv 后清理 | 0e644ac…99a25a6(11 commits) | — | + +净改动:15 个文件,+408/−92 行。无第三方依赖新增。 + +--- + +## 2. issue 逐条闭环验证 + +### #4 【P0】K=1 且 batch<128 崩溃 → ✅ 已闭环(标注式兜底) + +复测:`B=64 M=8192 N=32 K=1 int8` 走 `recommend`(-v / 不带 -v / 输出 plans.csv 三条路径)均**不再崩溃**: + +``` +=== bug_k1_smallB: ... K=1 int8 -> [特殊分支] + 仲裁: [无方案] K=1逐元素乘...; 但进入条件不满足 (2_K=1的AIV触发: B >= 2*AIV核数), 该区域暂无理论方案... + 方案: 核数=0 ... +``` + +实现:`router.py:52-58` capable=False 或 plan=None 时走 `_no_plan`(占位 ImplPlan,used_core_num=0,timing=None);`__main__.py:85-90` 增加空值防护。 + +**残留(P3)**:该区域仍未给出任何实现方案。扫描 B=1..255 × K=1 × 若干 M/N:**49.4%(378/765)落"无方案占位"**;K=0 全部有方案。原 issue 允许"标注无方案"作为最低要求(已达成),但建议后续补 AIV 单缓冲或 Cube 兜底方案消除空洞,或至少在文档(00_总纲 / 04_特殊分支)中明确该限制。 + +### #5 【P1】推荐模式不做约束自检 → ✅ 基本闭环(6.0%/18.0% → 0.2%/0.0%) + +架构修复正确:新增 `constraints.py` 为**唯一事实来源**,`router._wrap_checked` 在每次生成后调用同一校验函数,违规时在 arbitration/advice 中显式标注"[自检违规: …]";`evaluator._check_constraints` 改为委托同一函数。同时生成侧收敛辅助(`clamp_base_k` / `clamp_base_mn_l0c`)消除降核 base_k 硬编码等缺陷。 + +复测(与 v1 同种子同分布): +- 上轮全部最小违规样例(IterBatch K=8/K=2、MergeBatch fp8 K=32、ASW_降核 fp16/fp32、fp32 大 MN 等 12 个)→ **全部 violations=OK**; +- 宽范围 8000 例:480 → **16**(0.2%);典型 6000 例:1079 → **0**。 + +**残留(P3)**:16/8000 全部为极端瘦长 MergeBatch(如 `B=811 M=33 N=1 K=2459 fp32`、`B=1024 M=1 N=1024 K=1024 int8`):`make_plan` 的 b0 上限只取 L0C/算存比/b_core 三者的 min,**未纳入 L0A/L0B 容量**,导致 `b0*M`(或 `b0*N`)过大时 `base_k≥16`(fractal 下限)也放不进 L0A/L0B。新条件 2b(merge_batch.py:55-62)只按 MIN_B0=2 检查,未覆盖实际选中 b0 的情形。因生成自检已显式标注,属于"可感知的残余",建议把 L0A/L0B 容量加入 b0_max 求解(如 b0 ≤ L0A/(2·m·16·dt) 与 L0B 侧取 min 后取不超过 b_core 的因子)。 + +### #6 【P1】dValue 口径矛盾 → ✅ 闭环 + +理论裁定已落地并文档化(constraints.py:7-15、docs/01_软件架构.md §3.5):**dValue 128B 下限只对"K 被切分、K 段成为搬移连续维"(k_l1 < K)的方案生效;K 整驻留(k_l1 ≥ K,形态 a/b、小 K 整搬)时连续维是 M/N,豁免 K 向检查**。实现于 `_k_segment_is_contiguous`(constraints.py:118-134)。复测:IterBatch K=8/K=2 整驻留样例 → 无违规;形态 c/d 与 MergeBatch/ASW/StreamK 的 K 切分路径仍受约束。新增回归测试 test_issue6。 + +### #7 【P2】out_nd 无法经 CLI 传入 → ✅ 闭环 + +`io_csv.load_cases` 现解析 `out_nd`(缺省 True,大小写不敏感)。CLI 复测:同一 StreamK case `out_nd=0` → ASW_Basic_降核(StreamK 条件 4 生效);`out_nd=1` → StreamK。csv 头注释补充说明。新增回归测试 test_out_nd_disables_streamk。 + +### #8 【P2】A/B dtype 不一致无告警 → ✅ 闭环 + +`io_csv.load_cases` 加载后对 `dtype_a ≠ dtype_b` 打印 `[warn]`(stderr,含 case_id 与建模口径说明)。CLI 复测:`fp8 vs bf16` 输入正确输出告警。 + +### #9 【P2】StreamK 归约计账口径 → ⚠️ 部分闭环,引入新疑点(重点跟进) + +修复部分正确:REDUCE 不再进稳态 max()(`assemble_timing` 增加 `reduce_serial=True` 约定,timing.py:96-132),归约只作为 drain 串行追加一次;最终写回只留在 `eval_streamk_reduce` 内;回归测试 test_issue9 验证 `t_total = t_steady + t_drain` 且 `drain = t_reduce`(代数恒等)。 + +**但 fixpipe 的新口径有实质问题**(复算证据,demo case:B=4 M=N=128 K=10240 bf16,grid_K=32): + +| 账目 | 字节量 | 带宽分母 | 结果 | +|---|---|---|---| +| `t_reduce` 内 t_write_partial(部分和写 L2) | grid_K×tile×4B = 8.39MB | 整片 5.2TB/s(并发写) | **1.61us** | +| 新 `t_fixpipe`(stream_k.py:152-153) | 同一批 8.39MB | **单核份额 162.5GB/s** | **51.62us** | + +1. **同一批部分和字节被计两次账**(一次在 reduce 内按整片带宽、一次在 fixpipe 按单核带宽)——issue#9 原指控的"重复计账"并未消除,只是换了个位置与分母; +2. **单核串行化假设与软件自身的带宽模型矛盾**:timing.py 文档与 00_总纲均声明"每核独立 DMA 引擎、带宽按核数配平",即 grid_K 个核的部分和是**并发写出**的,墙钟时间应为 字节量/整片带宽 ≈1.61us;51.62us 相当于把整组部分和压到单核写口串行写,**高估 grid_K=32 倍**; +3. 后果已固化进 examples:streamk_demo 总时延 9.96us → **55.03us**,瓶颈从 MTE2_GM → FIXPIPE,且 advice 还给出"fp16/fp8 可减半写出量"的提示——该提示对按 4B 防精度丢失的部分和不成立(advice 生成器未感知 StreamK 例外,evaluator.py 的 _advice FIXPIPE 分支); +4. 修复后的回归测试只验证汇总代数式,**验证不了字节量与带宽口径的物理正确性**。 + +建议:fixpipe 部分和按"每核自己的部分和(tile×4B)÷ 单核份额"计(=1.61us,与 reduce 内并发口径一致),或与 `t_reduce` 的 t_write_partial **二选一**计账并在文档写明;再校验 8.39MB 是否应为每核 256KB 的并发总和语义。此条建议**重新开启 issue#9 或另开 issue**。 + +### #10 【P3】文档-代码漂移 → ✅ 闭环 + +README 目录树与分支注释更新为 6 分支全实现;docs/01_软件架构.md 分层图、§3.5(单一约束源)、§4 扩展指南(转Matmul 精切为后续方向、新分支须走 constraints.py)均已同步;Python 版本声明改为"实测 3.12/3.14,建议 3.10+"(3.14 本机复验通过)。轻微残留:`router._wrap`(旧包装函数)成为死代码未删除;README 目录树仍缺 `docs/03_测评报告` 条目(小事)。 + +--- + +## 3. 回归测试与可复现性 + +- 单测:`python -m unittest discover -s tests -v` → **Ran 23 tests, OK**(0.028s)。 +- recommend 输出 vs 仓库 `examples/result_recommend.csv`:10 行全列 **0 差异**;evaluate 输出 vs `examples/result_evaluate.csv`:**0 差异**(含新的 streamk 55.03us 数值——即作者已用新模型重生成示例)。 +- 压力回归(与 v1 完全同种子同分布)见 §0 表;两组均 0 崩溃、0 NaN、0 负时延。 + +--- + +## 4. 代码质量复查(针对改动) + +- `constraints.py` 抽象正确:校验与生成收敛共用;注释完整记录 dValue 裁定缘由。 +- 三处发现的小问题: + 1. `constraints._l1_need_bytes` 对 IterBatch 形态 c 的预算推断(resident = min 侧 + 对侧 k_l1 双缓冲)与生成侧 iter_batch.l1_form 逻辑手写两遍,仍属"双源"(本次未合并),好在口径一致、且有校验兜底;建议未来直接让 make_plan 调用同一 helper。 + 2. `merge_batch.py` 条件 2b 用 MIN_B0 预检但实际 b0 更大时仍可能溢出(§2 #5 残留)——校验兜底已标注,但生成侧仍可产生违规方案(0.2%)。 + 3. 输入范围校验仍缺失:`M=-5` / `M=0` 静默产出 IterBatch 伪方案与无意义时延;非法 dtype 抛裸 ValueError。建议 load_cases 后加维度正数校验。 + +--- + +## 5. 遗留问题清单(按优先级) + +| # | 级别 | 问题 | 证据 | 建议 | +|---|---|---|---|---| +| N1 | P2 | StreamK fixpipe 部分和写双重计账 + 单核串行化高估 ~32 倍;examples 已固化 55.03us 结果 | stream_k.py:152-153 vs timing.py:77-93;demo 复算 51.62us vs 1.61us | reopen #9 或新开 issue;fixpipe 与 reduce 内部分和写二选一,按并发口径计 | +| N2 | P3 | K=1 且 B<128 无方案空洞(占 K=1 域 49.4%) | B=1..255 × K=1 扫描 378/765 占位 | 后续补 AIV 单缓冲/Cube 兜底方案或文档明示 | +| N3 | P3 | MergeBatch 瘦长 case b0 未含 L0A/L0B 上限 → 0.2% 自检违规(已标注不静默) | 8000 例中 16 例,样例见 §2 #5 | b0_max 纳入 L0A/L0B 容量约束 | +| N4 | P3 | FIXPIPE 建议文案对 StreamK 误导(fp16/fp8 减半对 4B 部分和不成立) | evaluator.py _advice | advice 生成感知分支例外 | +| N5 | P3 | M≤0 等非法输入无校验,静默输出伪方案 | M=-5/M=0 探针 | load_cases/route 前参数校验 | +| N6 | P3 | 无 .gitignore、整改期误提交 11 个临时文件 commit;死代码 router._wrap;README 目录树缺 03_测评报告 | git log 0e644ac..99a25a6 | 补 .gitignore、删死代码 | + +--- + +## 6. 总体评分(第二轮) + +| 维度 | v1 | v2 | 说明 | +|---|---|---|---| +| 设计架构 | 9.0 | 9.0 | 单一约束源使架构更完整 | +| 理论-代码映射 | 8.0 | 8.5 | dValue 裁定、归约约定均有文档 | +| 功能完成度 | 8.0 | 8.5 | 双模式 + 自检 + 告警 | +| 内部一致性 | 5.0 | 7.0 | 0.2%/0% 自洽率;StreamK 口径遗留 | +| 鲁棒性/错误处理 | 4.0 | 7.5 | 崩溃消除、占位兜底、告警落地;输入校验仍缺 | +| 测试 | 5.0 | 7.0 | 23 条含 6 条 issue 回归;仍无 io_csv/CLI 单测 | +| 工程化/交付 | 5.0 | 6.5 | 文档同步、模块化;无 CI/打包/.gitignore、误提交噪音 | +| **综合** | **6.2** | **7.6** | POC → 可用工具雏形 | + +**定位更新**:已从"理论文档的代码化 POC"升级为"分支归属与方案生成可自检、结果自洽率 99.8% 的辅助分析工具"。仍不建议把绝对时延数值直接当硬件实测使用(T_cmd=50ns 等参数未标定、StreamK 口径待复核),但**方案归属、tile 取值与相对瓶颈分析已经具备可信度**。 + +**优先建议**:① 复核 StreamK fixpipe 口径(N1);② 补输入校验(N5);③ 清理工程噪音并考虑 CI(N6);④ 中远期做硬件标定与 ops-nn 源码对照验证。 + +--- + +## 附录 A:本轮复测命令 + +```bash +git fetch origin && git log --oneline d36e224..origin/main # 整改提交 +python -m unittest discover -s tests -v # 23/23 +python -m bmm_theory recommend examples/cases_demo.csv -o r.csv --plans p.csv +python -m bmm_theory evaluate examples/cases_demo.csv p.csv -o e.csv +# 与 examples/result_*.csv 比对: 0 差异 +``` + +## 附录 B:残余 MergeBatch 违规样例(16/8000,0.2%) + +``` +B=811/811 M=33 N=1 K=2459 fp32 -> L0A tile 超容量 (b0=25: base tile 825×…×16×4B×2) +B=1024/1024 M=1 N=1024 K=1024 int8 -> L0B 超容量 + dValue=48B +B=2048/2048 M=512 N=1 K=16 bf16 -> L0A 超容量 (b0=8) +... +``` +特征:M 或 N 极小 × B 巨大 × b0 因子选择偏大 → 合并后 base tile 一维过长,L0A/L0B 在 base_k≥16 下无法驻留。已在 advice 中标注"[自检违规]",不静默。 + +## 附录 C:K=1 无方案空洞扫描 + +B=1..255 × K=1 × M/N∈{64×64, 256×256, 4096×64}:765 例中 378 例(49.4%)返回 used_core_num=0 占位"[无方案]";K=0 同域 0 例占位。 + +## 附录 D:遗留问题闭环确认(2026-09-06,commit 4bedf0a / HEAD 3a6c952) + +本报告 §5 的遗留问题(N1–N6)已全部转为 issue #11–#16 并修复闭环: + +| Issue | 修复内容 | 验证 | +|---|---|---| +| #11 N1(P2)StreamK fixpipe 双重计账/32×高估 | 部分和写/读回/求和/最终写回全部单次计入串行 drain(稳态 Fixpipe 账目清零) | streamk_demo 55.03→**9.96us**,瓶颈回到 MTE2_GM | +| #12 N2(P3)K=1 且 B<128 无方案空洞 | 新增 **AIV 单缓冲**模式(B≥128 仍乒乓),04_特殊分支.md 同步 | B=1..255×K=1 全扫 **765/765 全有方案** | +| #13 N3(P3)MergeBatch 瘦长不可行(0.2%) | b0_max 纳入 L0A/L0B 容量上限;路由对胜出方案自检,违规时回退(另一切B候选→StreamK→ASW) | 8000 例宽范围违规 **16→0** | +| #14 N4(P3)FIXPIPE advice 对 StreamK 误导 | StreamK 跳过 dtype 减半提示,新增 REDUCE 瓶颈建议 | 文案验证 | +| #15 N5(P3)输入校验缺失 | BmmCase.__post_init__ 维度/dtype 校验,非法输入明确抛错 | M≤0/K<1/dtype 非法均正确报错 | +| #16 N6(P3)工程噪音 | 根目录 .gitignore、删除 router._wrap 死代码、README 目录树补 03_测评报告 | — | + +**修复后全量验证**:单测 **28/28**(新增 8 条回归);宽范围 8000 例 + 典型形状 6000 例压力测试 **违规 0 / 异常 0 / 无方案 0 / NaN 0**;examples 已按新模型重新生成并与代码 0 差异提交。Gitea issue #4–#16 已全部关闭(附修复注释)。 + +--- + +*第二轮复评完成:本地动态测试 + 与仓库 HEAD 99a25a6 比对;全部问题均有可复现证据。修复确认见附录 D(HEAD 3a6c952)。*