softmax 算子建模实现计划
基于:G5-softmax算子建模设计规格(Accepted v1.0.0)。前置:G5-计算算子建模方法分层设计规格(方法分层)+ G5-计算建模设计规格(matmul,tier3 评估模式参照)。 日期:2026-06-22 状态:Done
目标
把 G5 attention 发射里被丢弃的 softmax 升级为算子级向量吞吐 cycle 模型 + LMEM 访存边带域标签,与 fa2 两个矩阵乘串行相加计入 attention 计算时长,使 G5 与解析侧口径一致(现状系统性少算 23–29%)。
Dependencies
- G5 既有 tier3 评估模式:matmul 走
tier3/tiu.rscalc_tiu_latency、HAU 走tier3/hau.rscalc_hau_latency,各有独立 op type(TIUOpType/HAUOpType)+ command 结构 + core_subsys 事件处理(on_tiu_finish/on_hau_finish)。softmax 照 HAU 模式新增向量评估器,非新建引擎。 - Rust chip config
ChipSpec(dataclasses.rs:192)有cube: CubeConfig,无 vector 段——需新增VectorConfig。lane_per_core已在 ChipSpec(tiu 用chip.lane_per_core)。 - 解析侧公式形态(验收锚点):
perfmodel/evaluation/math/evaluators/softmax_eval.py(10 步 SOFTMAX_STEPS_ARRAY +align_up对齐 +eu_block=eu_num//lane_num//dtype_bytes、max(1,eu_block))+perfmodel/evaluation/math/evaluators/precise/attention_evaluator.py:152-193(vec_theo/vec_t_us 口径,gemm+vec 串行;vec_t_us 除数含*SOFTMAX_DTYPE因子)。 - 跨语言指令传递链(仿 HAU):Python
program.py:228CoreInstructions 各引擎 cmd 列表 → Rustinput/parse_commands.rs:36parse_core_instructions 逐类parse_cmd_list+parse_*_command→ Rust CoreInstructions。新增 VectorCommand 必须贯穿这条链。 - Rust 改后
maturin build --release+ pip install + 覆盖根目录g5_rspyd(记忆 project_g5_pyd_shadowing)。
文件变更概览
| 文件 | 改动 |
|---|---|
perfmodel/evaluation/g5/src/types.rs | 新增 VectorOpType(Softmax)+ VectorCommand(B/Q/K/precision 字段);Rust CoreInstructions 加 vec_cmds 字段 |
perfmodel/evaluation/g5/src/input/dataclasses.rs | 新增 VectorConfig(eu_per_lane 每精度 / op_count 步表 / lmem 带宽),ChipSpec 加 vector 字段 |
perfmodel/evaluation/g5/src/input/parse_chip.rs | 解析 chip YAML 的 vector 段;缺字段 raise(不取默认) |
perfmodel/evaluation/g5/src/input/parse_commands.rs | 新增 parse_vector_command;parse_core_instructions 加 vec_cmds 的 parse_cmd_list(跨语言传递链,仿 hau_cmds) |
perfmodel/evaluation/g5/src/input_parse.rs | 新增 parse_vector_op_type(Python op_type 字符串 → VectorOpType) |
perfmodel/evaluation/g5/src/tier3/vector.rs(新增) | calc_vector_latency:吞吐 cycle 公式(复刻解析侧 softmax_eval 的 align_up 形态,非 spec 正文 ⌈Q/L⌉)+ LMEM 访存边(eq:gsm-mem-edge)+ bandwidth_domain="lmem_bus" + combine(串行) |
perfmodel/evaluation/g5/src/tier3/core_subsys.rs | 向量指令 issue + on_vec_finish 事件(仿 on_hau_finish),softmax 串行占时间线 |
perfmodel/mapping/g5/program.py | CoreInstructions 加 vec_cmds 字段 + CoreProgram.total_vec_cmds(仿 hau_cmds) |
configs/chips/SG2262.yaml | 新增 vector.op_count 步表(softmax 10 步);确认 eu_per_lane;同步 _template.yaml |
perfmodel/mapping/g5/instruction_emitter.py | _emit_fa2 在 QK^T 与 PV 之间发射 softmax VectorCommand |
docs/validation/G5softmax建模-test-plan.md(新增) | test case 清单(先于 test 代码) |
tests/evaluation/g5/test_softmax_modeling.py(新增) | 据 test plan 的 test case |
Rules Compliance
- config 禁默认值:VectorConfig 解析缺字段(eu_per_lane / op_count / lmem 带宽)raise 带字段名,禁止仿解析侧
if lane_num>0 and eu_per_core>0静默置 0。 - no-backward-compat:直接给 fa2 发射加 softmax,不写
if 不建模 softmax分支。 - naming(_gb_per_s):vector 带宽字段用
_gb_per_s,不用_gbps。 - sync-templates:SG2262.yaml 加 vector 段须同步
configs/chips/_template.yaml。 - windows-encoding:Rust/Python 输出无特殊 Unicode(用 [OK]/[FAIL])。
- 不碰
DepEngine::Cdma=>0:A1/A2 边界,本篇只加 compute 算子。 - strict 无容差:形态一致性断言严格相等。
- Rust 改后 maturin 重建 + 覆盖根目录 pyd。
无 Complexity Tracking 偏离。
实现步骤
Task 1 [Sequential,基础] — Rust 向量吞吐成本公式 + 配置 + 跨语言传递链
新增 tier3/vector.rs 的 calc_vector_latency,从 VectorCommand 字段 + VectorConfig 算 softmax 时长。仿 tiu.rs 结构(公式在 Rust、参数从 config、combine 合成)。本 Task 含 VectorCommand 从 Python emitter 跨 PyO3 到 Rust 的完整传递链(仿 hau_cmds),否则 Task 4 发射后指令过不了边界。
- VectorConfig(dataclasses.rs):eu_per_lane(每精度 map)、op_count 步表(每步 shape_type + op_count,对应解析侧 SOFTMAX_STEPS_ARRAY 10 行)、lmem 带宽(访存边用)。ChipSpec 加
vector字段。 - VectorOpType + VectorCommand(types.rs):op_type=Softmax;字段 B / Q(QS_tile)/ K(KS_tile)/ precision。Rust
CoreInstructions加vec_cmds。 - 跨语言传递链:
program.pyCoreInstructions 加vec_cmds字段 + total_vec_cmds;parse_commands.rs加parse_vector_command+parse_core_instructions接vec_cmds;input_parse.rs加parse_vector_op_type。 - 公式(G2:以解析侧形态为准,非 spec 正文 ⌈Q/L⌉):严格复刻
softmax_eval.py的_softmax_core——aligned_qs=align_up(QS,lane)、aligned_ks=align_up(KS,eu_block)、eu_block=eu_num//lane_num//dtype_bytes带max(1,·);vec_theo=Σ_step(shape0: aligned_qs·aligned_ks·op_count / shape1: aligned_qs·op_count);t_vec=vec_theo·B/(eu_per_core·dtype_bytes·f_v)(除数含 dtype_bytes 因子,对齐 attention_evaluator.py:186)。spec eq:gsm-vec-cycle/time 是概念式,实现与验收以解析侧 softmax_theoretical_and_real 为锚点。访存边 t_mem=(score 读+概率写 bytes)/lmem 带宽,bandwidth_domain="lmem_bus";combine 串行(ρ=0 相加,复用 tiu.rs combine_overlap 同义)。 - 解析(parse_chip.rs):vector 段缺字段 raise 带字段名(禁止解析侧
lane_num>0 and eu_per_core>0静默置 0 那种兜底)。 - 门控:softmax 复用既有 unvalidated 门控(HAU/TIU 同),无新增门控逻辑。
Acceptance:cargo test——给定 (B,Q,K,BF16) + vector 参数实例,calc_vector_latency 的向量 theo/时长严格等于解析侧 softmax_theoretical_and_real + vec_t_us 口径同输入(无容差);访存边带 bandwidth_domain="lmem_bus";删 eu_per_lane 字段 → 解析 raise 带字段名。VectorCommand 能从构造的 Python CoreInstructions 经 parse_core_instructions 解析到 Rust(传递链通)。
Task 2 [Sequential,依赖 1] — 向量指令接入事件驱动执行
core_subsys.rs:向量指令 issue + 完成事件,softmax 串行占计算时间线。
- 仿
on_hau_finish/HAU issue 路径,加向量指令的 load/issue +on_vec_finish(cmd_id)。 - A1 边界:softmax 串行占时间线(与矩阵乘串行相加,不并行重叠——真 overlap 是 A2,不碰 DepEngine::Cdma=>0)。
Acceptance:cargo test——含 1 个 softmax VectorCommand + 2 个 matmul 的 CoreProgram 跑通,attention 时长 = 三项串行相加(matmul1 + softmax + matmul2),无悬挂事件。
Task 3 [P] — SG2262 vector 参数实例 + 模板同步
(与 Task 1/2 无真数据依赖:cargo test 用 Rust 内联 make_chip 不读 YAML,YAML 解析在本 Task 自验,可并行起草。)
- SG2262.yaml 加 vector 段:芯片专属参数——eu_per_lane(已有 BF16=32 等)、lane、lmem 带宽。op_count 步表不进 YAML(跨厂商算法常量,已在 Task 1 代码固化为 VectorConfig::softmax_steps(),逐行=SOFTMAX_STEPS_ARRAY)。
- 同步
configs/chips/_template.yamlvector 段(含字段注释 + 必填标注)。 - 决策记录(已与用户确认):op_count 步表是 softmax 算法分解、跨芯片完全相同,固化为 Rust 常量而非 YAML(放 YAML 各芯片重复同一份、易漂移);spec 附录 C/B 已订正为"代码固化常量"。eu_per_core 源 = 解析侧
chip.eu_num // core_count(= vector 每 lane eu × vector lane 数),非 plan 初稿误写的eu_per_lane*lane;Task 1 已按正确源实现 bit-exact。
Acceptance:load_chip("SG2262") 解析出 vector 段无报错;删任一 vector 必填字段(eu/lane/带宽)→ raise 带字段名 + 文件路径。(op_count 逐行一致性在 Task 1 Rust 单测已覆盖。)
Task 4 [Sequential,依赖 1,2,3] — emitter 发射 softmax + 重建
instruction_emitter.py _emit_fa2:在 QK^T(line ~353)与 PV(line ~363)之间发射 softmax VectorCommand(B=b, Q=qs_tile, K=ks_tile, precision)。
- 字节口径:score 读+概率写,与 QK^T/PV 矩阵乘访存边不重复计(softmax 只覆盖 score↔prob,不碰 Q/K/V/输出)。
- maturin build --release + pip install + 覆盖根目录 pyd。
Acceptance:跑一个 fused attention(MLA prefill),EngineResult 的 attention 计算时长含非零 softmax 分量,且 = QK^T + softmax + PV 串行相加;softmax 访存边不与矩阵乘访存边重复计(比对覆盖张量)。
Task 5 [P,依赖 spec] — 测试用例清单(先于 test 代码,写入本 plan 下方「测试用例清单」小节)
(依赖 spec 验收标准而非实现产物,可与 Task 1-4 并行起草;符合 test-plan-before-cases:清单设计先行。test case 清单是规划材料,写进本 plan 小节,不另起 docs/validation 文档——validation 放验证报告/数据,非规划。)填下方「测试用例清单」小节:每 case 写输入 / 预期 / 对应 spec 验收点 / 断言性质(严格无容差 vs 行为)/ 落点(Rust 单测 or Python test)。
Acceptance:清单覆盖 spec 全部验收标准行;每 case 标清断言性质与落点。
Task 6 [Sequential,依赖 5] — test case 代码
tests/evaluation/g5/test_softmax_modeling.py:据 test plan 写 test case(不边实现边内联补,test plan 先行)。
Acceptance:所有 test case 通过;形态一致性 case 严格相等;删实现核心(softmax 发射 / op_count)对应 case 变红(变异有效性)。
Task 7 [Sequential,依赖 6] — 回归
- 现有 G5 测试(72 passed)不破。
- matmul(tiu)/ 通信侧 / 多芯片桥(A1)不受影响。
Acceptance:cargo test 全绿 + pytest tests/evaluation/g5/ 全绿。
验证计划
- 单元:Rust 向量公式(Task 1 cargo test,严格等解析侧)、配置解析缺字段 raise(Task 1/3)。
- 集成:event 执行串行相加(Task 2)、emitter 端到端 attention 含 softmax(Task 4)。
- 形态一致性差分:G5 softmax cycle 严格等于解析侧 softmax_theoretical_and_real 同输入(无容差)。
- 回归:现有 G5 全量 + matmul/通信/A1 桥不破(Task 7)。
- Rust 改后 maturin 重建 + 覆盖根目录 pyd(每次改 Rust 都要)。
测试用例清单(Task 5 产出,Task 6 据此写代码)
| # | case | 输入 | 预期 | spec 验收点 | 断言性质 | 落点 |
|---|---|---|---|---|---|---|
| C1 | 形态一致性 | (B,Q,K,BF16) 多组 + vector 参数实例 | vec_theo/时长严格等解析侧 softmax_theoretical_and_real + vec_t_us 同输入 | 形态一致严格相等 | 严格无容差 | Rust 单测(Task 1 已建:test_softmax_theo_handcalc / test_shape_consistency_python_reference / test_eu_block_floor) |
| C2 | 访存边带域 | 一个 softmax cmd | 访存边 bandwidth_domain == "lmem_bus" | 访存边带域 lmem | 行为 | Rust 单测(Task 1 已建) |
| C3 | 串行合成 | 固定 t_vec/t_mem | combine 结果 = t_vec + t_mem(非 max) | 串行合成非取 max | 严格 | Rust 单测(Task 1 已建) |
| C4 | 缺字段 raise | 删 vector eu / core_count=0 | raise 带字段名,不置零 | 参数缺字段 raise | 行为 | Rust 单测(Task 1 已建)+ Python load_chip 缺字段(Task 6) |
| C5 | attention 含 softmax 串行 | MLA prefill 单芯片 | attention 时长 = QK^T + softmax + PV,softmax 分量非零 | attention 含 softmax 串行 | 行为 | Python test(Task 6) |
| C6 | 字节不重复计 | fa2 核 | softmax 访存边覆盖 score↔prob,不与 QK/PV 矩阵乘访存边(Q/K/V/输出)重叠 | 字节不重复计 | 行为 | Python test(Task 6) |
| C7 | 厂商中立 | 改 vector.eu_per_lane 参数实例 | softmax cycle 随参数变、公式结构不变 | 厂商中立 | 行为 | Python test(Task 6,仿 tiu test_vendor_neutral) |
| C8 | 门控继承 | unvalidated 置位 | 绝对查询返回相对(复用既有门控,无新增) | 门控 unvalidated | 行为 | 继承既有 test_slo_gate,无新增 |
| C9 | 变异有效性 | 删 softmax 发射 / 改 op_count | C5/C1 对应 case 变红 | —(测试有效性自检) | 行为 | 手动变异验证(Task 6) |
| C10 | 回归 | 全量 | 现有 72 G5 测试不破 | 回归 | 严格(继承既有) | cargo test + pytest(Task 7) |
C1-C4 在 Task 1 Rust 单测已落地(cargo test 465 passed);C5-C7、C9 是 Task 6 Python test 新增;C8/C10 继承既有。
风险与回退
| 风险 | 缓解 |
|---|---|
| Rust 重实现 softmax 公式与解析侧漂移 | Task 1 acceptance 严格等解析侧、无容差,漂移即红 |
| 向量指令接入 event 漏处理 → 悬挂事件 | Task 2 acceptance 验无悬挂事件,仿 HAU 成熟路径 |
| softmax 字节与矩阵乘访存边重复计 | Task 4 字节口径只覆盖 score↔prob,acceptance 比对覆盖张量 |
| op_count 下沉 YAML 各芯片重复 | Task 3 已记决策:spec 契约优先,重复可接受;若后续多芯片维护痛,回 spec 议是否改为共享算法常数 |
| 被误读为"建厂商引擎"(违 discuss 边界) | 明确仿 HAU/TIU 既有算子成本+调度模式,非 cycle 级 SystemC 引擎;A1 串行不建真 overlap |
| 参数缺字段静默置 0(复现被丢弃缺陷) | Task 1/3 缺字段 raise 带字段名,acceptance 删字段验抛错 |