ISSUE-042: driver alltoall data_bytes 多乘 (N-1) — 数据量膨胀 (N-1)×,放大 ISSUE-040/041
发现日期:2026-06-07
修复日期:2026-06-07
状态:已修复
类型:建模 bug — driver build_alltoall_program 的 data_bytes 不符合 alltoall 规范约定,多乘 (N-1),致每对实际传输 (N-1)× 目标字节
关联 issue:本 issue 是 ISSUE-040 / ISSUE-041 的共同根因 — 31× 数据膨胀 (N=32) 制造极端负载,才暴露了 retry_timeout 偏紧 (ISSUE-041) 与 credit-emit race (ISSUE-040)
结论速览
根因:driver.rs::build_alltoall_program 设 data_bytes = msg_size × N × (N-1),但 alltoall 规范约定 (见 types.rs CommOp.send_counts doc: "None = uniform data_bytes/N") 是 data_bytes = per-chip sendbuf = N × per-pair chunk (MPI alltoall 语义)。expand_pairwise_alltoall 取 uniform_chunk = data_bytes / N 作每对 chunk。
故 driver 的每对实际 chunk = msg_size × N × (N-1) / N = msg_size × (N-1),而非 doc 声称的"msg_size = 每对单向字节数"。对 N=32,每对传 256KB×31 = 7.9MB 而非 256KB,每 chip 出向 256KB×31×31 = 245MB 而非 7.9MB — 数据量膨胀 31×。
正确值:data_bytes = msg_size × N → 每对 chunk = msg_size ✓。
问题现象
ISSUE-041 修复后 code-review (opus) 用"busbw 异常低"sanity check 发现:重新生成的 golden baseline 里 clos-32-256kb busbw = 12.23 GB/s — 远低于物理合理值 (link 400 GB/s 量级)。每个 alltoall cell 的 busbw 都被 1/(N-1) 误缩放。
修正 data_bytes 后:
| 指标 | 修复前 (data_bytes×(N-1)) | 修复后 (正确) |
|---|---|---|
| clos-32-256kb 每对 chunk | 7.9 MB | 256 KB |
| clos-32-256kb sim_time | 664,447 ns | 22,091 ns |
| clos-32-256kb busbw | 12.23 GB/s | 367.86 GB/s |
| golden_compare 全跑耗时 | ~121 s | ~秒级 |
调查过程
Phase 0 预期行为 (alltoall data_bytes 约定)
types.rsCommOp.send_countsdoc: "None = uniform data_bytes/N" — 规范约定每对 chunk = data_bytes/N,即 data_bytes = N × per-pair (MPI alltoall sendbuf: N 块,每块 sendcount,块 i 发给 rank i)。expand.rs约定注释:"所有原语的 data_bytes ≡ 全量 M (与 Math comm_bytes 同语义)" — 对 alltoall, expander 实现的是 per-chip sendbuf 语义 (data_bytes/N = per-pair)。expand_pairwise_alltoall(alltoall.rs):uniform_chunk = ceil(data_bytes / n),每 chip 对 (n-1) 个对端各发一个 uniform_chunk。expander 是规范实现,正确。
Phase 1 反馈环 + 验证
- 读
alltoall.rs确认:per-pair = data_bytes/N; driver 传 data_bytes = msg_size×N×(N-1) → per-pair = msg_size×(N-1)。bug 在 driver,非 expander。 - grep 生产 Python 路径:未发现其它 alltoall data_bytes 构造点 — bug 限于 driver (Phase 2C Task 1 新代码),不影响生产 Python 仿真。
- 修正后再验 (clos-32-256kb,正确数据量):retry_timeout=10μs 与 1ms 的 sim_time 完全一致 (22091),均 incomplete=0 — 正确数据量下 retry 根本不触发 (证明 ISSUE-041 的 spurious retry 是被本 issue 的 31× 数据膨胀放大出来的)。
与 ISSUE-040 / ISSUE-041 的因果
ISSUE-042 (data_bytes 膨胀 31×)
→ 数据量 31× → 单 chip in-flight 巨量 → ACK RTT 飙到 50-70μs (clos 多跳 + ACK MERGE 排队)
→ ISSUE-041 (retry_timeout=10μs < ACK RTT) → spurious Go-Back-N 重传风暴
→ ISSUE-040 (try_arbitrate↔emit 异步窗口被迟到 cumulative ACK 撕裂) 被暴露
三者均为真 bug,但本 issue 是把另两个从"latent"放大到"可见"的根。ISSUE-040 (credit 原子) 与 ISSUE-041 (retry 兜底) 的修复仍正确且保留 (latent bug 防御)。
根因分析
| 错误模式 | 实例 | 后果 |
|---|---|---|
| alltoall data_bytes 不符规范约定,多乘 (N-1) | driver.rs data_bytes = msg_size×N×(N-1) vs 规范 data_bytes/N = per-pair | 每对传 (N-1)× 目标字节,数据量膨胀 (N-1)×; busbw 被 (N-1)× 误缩放;sim_time 对应膨胀工作量 |
解决方案
采用:driver.rs::build_alltoall_program data_bytes msg_size × N × (N-1) → msg_size × N。
修正后:
- 每对 chunk = data_bytes/N = msg_size ✓ (符合 doc "msg_size = 每对单向字节数" + 规范 types.rs:377)
- 每 chip 出向 = msg_size×(N-1) ✓ (符合 driver.rs:187 busbw 注释 + busbw 分子)
- busbw = msg_size×(N-1)/latency = 每 chip 出向/latency = algbw ✓
涉及文件:
perfmodel/evaluation/g5/src/driver.rs— data_bytes 修正 + 注释perfmodel/evaluation/g5/tests/golden/baseline.json— 重新生成 (全 alltoall cell 数值修正)
附带修复 (同 code-review):driver.rs unwrap_or(0.0) → expect (config-loading,缺 stat 报错不静默兜底);golden_compare.rs 零基线守卫 (baseline=0 时 inf 而非 NaN 静默放过)。
验证
- 修正后 sanity:clos-32-256kb busbw 367.86 GB/s (接近线速,物理合理),sim_time 22091 ns。
- retry 不再触发:正确数据量下 retry_timeout 10μs/1ms sim_time 一致,证明 ISSUE-041 spurious retry 由本 issue 放大。
- golden 重新生成 16/16 + 守恒 5 项 KPI 全 0。
- 全量回归
cargo test --release0 failed。
Lessons Learned
- 数值的物理合理性必须独立 sanity check,不能只看"守恒过 + 测试绿":本 issue 与 ISSUE-041 都由"busbw 异常低 / sim_time 异常大"sanity check 发现 — 守恒断言 (incomplete/residue=0) 全程通过,但数据量错了 (N-1)×。Golden 数值锁定 + busbw 物理上界检查是抓这类"自洽但错误"bug 的关键防线 (印证 Phase 2C 四层防线 Golden 层)。
- root cause 可能藏在更上游:ISSUE-040 (credit race) 和 ISSUE-041 (retry 偏紧) 都是真 bug,但若先发现 ISSUE-042,它们可能根本不会以那么极端的形式出现。调试时若一个 bug 的触发条件异常极端 (本例 7.9MB/对),应回头质疑输入本身是否正确。
- 跨层约定 (data_bytes 语义) 要在构造点核对: driver 是新加的 oracle 层,没有核对
types.rs/ expander 既定的 alltoall data_bytes 约定就自行构造,导致语义错位。新增调用既有接口的代码必须核对接口契约。
遗留问题
- busbw 约定是否完全对齐 NCCL:当前 busbw = 每 chip 出向/latency = algbw。NCCL alltoall 的 busbw 定义 (algbw × 系数) 是否需进一步对齐,是独立精化项 (不影响回归自洽性)。
- Clos/Torus/FatTree 拓扑保真度 (code-review F002):当前 Clos 是单 spine 星型,Torus/FatTree 别名到 ring/clos, 8/16 golden cell 实为重复。真实多 spine / 2D torus 留 Phase 3 (Task 1 已文档化此简化)。
- MR 2 对称性当前 inert (code-review F004): per_chip_completion_times 全相等 (SimRecord 无 per-chip 维度),CV≡0 恒过。留 Phase 3 扩 MultiChipSim 暴露 per-chip 时间。