Pull Request has been successfully merged by CANN-robot.
(Thank you for zhong-zixin's contribution.)Thanks for your pull-request.
The full list of commands accepted by me can be found at here.
You can get sig-info at here.
You can self-configure the PR merge rules for this repository. For more details, please refer to Here.
For more, you also can visit HICANN.
PR Approval Progress
✅ Congratulations! All modules have met the lgtm and approve requirements.
Module Approval Details
| module | lgtm status | approve status |
|---|---|---|
| mc2 | ✅ 刘丹, chenjunjian11 (2/2) | ✅ 刘丹 (1/1) |
💡 Tip:
- Committer can comment
/approveor/lgtm- Commenting
/approveimplies both code review (lgtm) and intent to merge (approve)
CLA Signature Pass
zhong-zixin, thanks for your pull request. All authors of the commits have signed the CLA. 👍


【review】
问题分类:正确性
位置:mc2/moe_distribute_dispatch_v2/op_kernel/arch35/moe_distribute_dispatch_v2_a5_full_mesh.h:2140,代码:uint64_t flags = flagReadyTensor_.GetValue(beginFlag / flagsPerWord) >> (offset * BITS_PER_BYTE);
问题:CompareScalar 按每个浮点元素写入一个字节结果,而 beginFlag 表示 32B 标志块序号;当前索引没有乘以 UB_ALIGN_DATA_COUNT,导致第二个及后续标志块读取的是前一块结果中的填充字节,而不是对应 32B 块的首个比较结果。
可能导致的结果:当一个 token 或一批 token 包含多个 32B 标志块时,即使后续块已经就绪,检查也会读到填充的 0 值并判定未就绪,持续跳过已到达数据,造成输出长期等待或无法完成。
建议的修改方法:按 CompareScalar 结果的实际布局,将 beginFlag/offset 换算为每个 32B 块对应的 UB_ALIGN_DATA_COUNT 个字节(或在生成比较结果时直接压缩为每块一个字节),再按块序号构造 readyMask。


【review】
问题分类:安全
位置:mc2/moe_distribute_dispatch_v2/op_kernel/arch35/moe_distribute_dispatch_v2_a5_full_mesh.h:2301,代码:uint32_t flagReadySize = Ceil(blockCntPerToken_ * maxCopyTokenCnt, UB_ALIGN) * UB_ALIGN;
问题:maxCopyTokenCnt 的预算在上一行只按每个 token 增加 sizeof(uint8_t),但 flagReadySize 实际会把所有 token 的位图一次性向 UB_ALIGN 向上取整;同时旧实现用于回算 totalBufferSize 并递减 maxCopyTokenCnt 的容量校验已删除。
可能导致的结果:当 blockCntPerToken_ * maxCopyTokenCnt 不是 UB_ALIGN 的整数倍且 TBuf 剩余空间小于补齐量时,flagReadyTensor_ 会与 flagRecvTensor_ 或后续 UB 区域重叠,CompareScalar 写入越过 TBuf 分配范围,触发非法内存访问并破坏同一 kernel 的其他临时数据。
建议的修改方法:按 flagReadySize 的实际向上取整结果计算总占用,并在确定 maxCopyTokenCnt 后验证 2 * dataBufferSize + flagReadySize + flagRecvSize <= tBufRealSize_;若不满足则递减批大小后再初始化各 LocalTensor。


compile


| 🚀 CI 流水线已启动 |
|---|
| 📋 执行详情: 点击查看流水线 |


/lgtm


描述
串行专家计数同时改为连续块搬运,保留 Scalar 消费所需的 MTE2_S,删除无 Vector 消费者的 MTE2_V。
关联的Issue
关联 Issue #7275
测试
本地验证、二级冒烟
文档更新
不涉及
类型标签
以下为 2026-11-07 独立源码检视报告。源码链接已绑定固定提交,报告引用的辅助检查记录仅保留文件名,未作为附件发布。
fullmeshv2_ready_batch 独立源码检视报告
检视日期:2026-11-07。
结论:完整差异中未发现已证实的新增功能缺陷,也未发现新增风格违反。 在文档支持的 Ascend 950 / DAV_3510 普通与串行路径中,批量就绪判断、数据搬入/搬出、双缓冲复用及最终清理的依赖链能够闭合;新的 UB 布局可由容量和对齐公式证明。此结论来自源码、API 实现和数学检查,不是编译或设备验收结论。
实际部署 SDK 的 CompareScalar 实现、保留 UB 编译选项及硬件行为尚未验证,详见后文。
1. 版本、范围与证据
/tmp/ops-fullmesh-ready-batch-rebase-20261106fullmeshv2_ready_batch2e66dd201b80abaaee0b08398620a450d8f619e5e66f7133131527427832bffd6be296087ed8c8cdmc2/moe_distribute_dispatch_v2/op_kernel/arch35/moe_distribute_dispatch_v2_a5_full_mesh.h/home/zerozill/.openclaw/projects/asc-devkit,版本672a659aa82d72c4b843a21d714e73fa28e143ed检视覆盖完整 Git diff,并追踪 Host 约束、公共量化与通信实现、公开 API V2/V3/V4 到内部 Kernel 的调用关系。同步脚本对 HEAD 和基线各扫描 13 个相关文件。工作树检查为干净,
git diff --check通过。以下简称用于精确定位,行号均为上述 HEAD:
主要改动是:批量收集 flag 并生成位图,按位图搬入多个已就绪片段,再统一搬出;将原逐片段接收函数拆成
LoadDataFlags、CheckDataArriveWithFlag、LoadReadyData、CopyOut;减少接收工作区;串行计数搬运改为等价连续块,并删除无 Vector 消费者的同步。2. 发现分类
71 条适用功能/通用条款与 19 条风格条款的结果见 条款汇总(
clause_report.md)。其中 PASS 仅表示本次差异未违反相应条款,包含内容筛查后的不适用分支;不能解读为整个仓库通过完整产品验收。2.1 既有风格项
P3,已证实,非新增。 K:2294 的
uint32_t srcExpertId, dstPosition, copyCnt;来自基线的五变量声明,本次仅删去两个变量;K:2191 的两个GlobalTensor<float>同行声明从原接收函数保留。均不符合“一行声明一个变量”的风格规则,可在后续整理时拆开。未发现由本次拆分产生的死函数、只写不读字段或重复完整计算链。3. 流水同步与 buffer 生命周期
令
b=blockCntPerToken_,P=480b为一个 token 的紧凑 payload 字节数。每批最多处理 64 个源片段;未就绪片段保留其 UB 槽位。flagRecvTensor_MTE2_V→ 2118CompareScalarflagReadyTensor_V_S→ 2140GetValueV_S等待 V 的读写完成;其后 Scalar 读取/控制流再发起下一批 DMA/比较MTE3_V,再V_MTE2Set/WaitMTE2_MTE3;之后 K:2337CopyOutMTE3_MTE2、MTE2_MTE3MTE3_V,K:2353–2356 drain;K:2263 才DuplicateDuplicate→ MTE3 清 GM flagV_MTE3→ 2280DataCopyMTE2_S;K:2536S_MTE3MTE2_V无对应 V 消费者GetValue与LocalTensor::operator()的此处访问属于 Scalar。V_S不能代替 MTE3 完成,因此 payload 复用和结束清理分别保留了明确的 MTE3 完成依赖。固定事件 ID 为 0/1;事件资源按方向区分,接收循环内的SyncFunc<MTE2_V/V_S>不与持有中的MTE3_Vrelease 冲突。发送阶段的事件已在其尾部排空后进入接收阶段。设实际成功接收批次数为
B:MTE3_V发布次数为B。max(B−2,0)。min(B,2),两项之和恰为B。copyBatchId;首次等待只发生在即将搬入第一个已就绪片段时。因此“1 处 Set、2 处 Wait”这一静态调用点计数不是事件不平衡的证据。未见新增跨核同步或通信协议发布顺序的变化。
4. UB 容量、对齐与 Host 配置
4.1 新布局的通用证明
K:2295–2309 取
T=tBufRealSize_、m=floor(T/(993b))、F=bm:480F480F480Falign32(F)960F32F960F+align32(F)总量为
992F+align32(F)=align32(993F)。当T为 32B 对齐且非负时,由993F≤T得总量≤T。所有区域起点均 32B 对齐,GetWithOffset的 size 已按对应元素大小换算。该证明不依赖 token 恰好填满 64/128/256B,也不依赖固定 AIV 核数。布局不越界与
m>0是两个条件,后者分别沿非串行和串行入口证明如下。4.2 普通 Host 域与非串行路径
Host 校验包括
2≤P_ep≤1024(H:608–628)、专家数E≤2048(H:751–780)、S<P_ep、L=E/(P_ep−S)>0且P_ep×L≤4096(H:977–993)、1024≤H≤8192(H:1093–1096)、每源最多 512 token(H:940–960、1003)。还需满足其 dtype、量化、输出 shape、窗口及其他 UB 检查;这些范围并非可以任意笛卡尔积组合。K:2373–2421 在 Reset 后只分配本阶段对象。令
C=aivUsedCumSum_≤8,s=sendNum_≤4096。无需假定典型 56/64 核,即可保守放大:≤align32(4×(s+8))≤16416B。≤3×16384=49152B。≤32+2×8×32=544B。≤align32(4×2048)+align32(8×2048)=24576B。所以
T≥U−64−90688=U−90752。对 950 资料中的每 AIV 可用U=253952B,有T≥163200B,不存在减法下溢。类型可达性不能只按全局注册表判断:
op_host/moe_distribute_dispatch_v2_def.cpp:100/123的 INT32 列属于 A6 配置,默认注册第 166/184 行也包含 INT32;但 A5 的op_host/op_tiling/arch35/moe_distribute_dispatch_v2_tiling_arch35.cpp:1255–1279查询moe_distribute_dispatch_tiling_helper.h:72–95的QUANT_MODE_MAP,其中没有 INT32 输出,查无即拒绝。另一 tiling 入口第 379–390、1036–1038 行检查同一表;两个 arch35 Kernel 入口的 dtype 分支也均未实例化 INT32。因此该注册列不属于本次 A5 full mesh 的有效配置,以下 2H 上界有对应的 Host 可达性限制。详细证据见 dtype 适用域核对(dtype_scope.md)。Q:63–117 与 K:477–486 给出 token 打包尺寸。对支持类型,输出至多
2H字节,输入附带 scale 至多4H;其余 per-token/per-group/MX 对齐及元数据也受6H+64的放大界覆盖。因此b≤ceil((6×8192+64)/480)=103,单 token 原始预算993b≤102279B<T。即使再放大为输出与 scale 各4H,得到b≤137,仍有993b≤136041B<T。故该路径m≥1。平台值来自 Host 的
GetCoreMemSize(UB)(H:2531–2535);上述 248KiB 数值由架构资料支持,未读取本次设备返回值。对其他平台描述,应重新代入U,不能把证明变成代码中的硬编码容量。4.3 串行路径
串行选择条件为
axisMaxBS≤32、原始 EP 小于 16、且非 scaling-down(K:417–418)。BufferInitSerial在 K:2427–2441 保留既有固定区,再形成剩余接收区。H:1973–2018 的
CheckSerialReceiveUbSizeA5按实际平台 UB,累加固定区、保留区及至少一 token 的旧接收需求,超过预算则拒绝。旧需求包含960b+align256(4b)+32b;新需求为960b+align32(b)+32b,前者不小于后者。Host 固定区计算对共享专家路径也使用保守状态数。因此既有 Host 检查仍足以保证新路径至少容纳一 token。4.4 其他边界
在上述合法域内,
F=bm≤floor(253952/993)=255。因此新 flag/payload DMA 的blockCount=b×copyCnt≤255,输出copyCnt≤255,均未接近 uint16 窄化边界或普通 DataCopy 的 4095 上限。串行计数连续块的statusNum≤4096,放在 uint16blockLen中合法。最大累计 token 数受
4096×512=2097152约束,三元组元素偏移不超过 6291456。一个来源段内finish×hCommuSize的保守上界为512×103×512=27000832。大窗口 section 及 expandX 总偏移使用 64 位计算。与此次改动相关的窄化、位移及乘法未发现溢出条件。5. 位图 API、尾部与有效位
K:2116–2122 调用的是带 mask/repeat 参数的 CompareScalar 重载,前置
SetMaskCount、随后SetMaskNorm;不能套用另一个 count 重载要求 count 字节数为 256B 整倍数的限制。可读 DAV_3510 实现 kernel_operator_vec_cmp_impl.h:478 在 CounterMode 中按
ceil(mask/64)迭代,使用UpdateMask<float>和带 mask 的LoadAlign<DATA_BLOCK_COPY>。对应 API 说明全无效的 32B 块不读取。这里 mask 为N×8个 float,恰好覆盖 N 个完整 32B flag 块,尾部不会无条件多读一个 256B 向量。比较将 8 个 float 的判断压成 1 字节。实现按每轮 8B 写位图,尾部实际存储量
8ceil(N/8)≤align32(F);Scalar 的最后一次 uint64 读取也落在该预留区内。K:2130–2145 用0x0101010101010101只检查每个 flag 块首 float 的比较位;尾字通过flagNum和 offset 限制,未把无效高位参与就绪判断。片段 mask 的移位范围为 0..63,字节检查移位范围为 0..56。没有移位 64 位、误读尾部位或把 flag 的其他七个 float 当成协议必要条件的情况。
上述结论绑定可读 D 版本。实际部署头文件及
--cce-disable-asc-reserved-ubuf等编译选项未确认,不能从可读兼容实现推断所有 SDK 组合都可编译。6. 数据搬运、索引与输出语义
6.1 三轮片段遍历的一致性
LoadDataFlags、LoadReadyData、输出循环均以同一片段范围、同一min(left,m−tokenNum)递进。未就绪片段仍累计 tokenNum,后面的已就绪片段使用原槽位;left 为零的片段三处都跳过。最多 64 个片段包括中间零项,位索引使用index−beginIndex,没有把位图序号与非零片段序号混用。源 section 都由
GetLocalWindowSrcDataBlockIdx计算,payload 与 flag 使用相同的expertFinishNumTensor_×hCommuSize_。目的位置仍为对应源片段的接收前缀加已完成数量,和谁先 ready 无关。每片段输出完成指令提交后才更新 finish/left。入口只将有 token 的片段加入有效表,validNum 为零时调用者退出,不会因最初的全零片段使 finishNum 永远不足。6.2 DataCopy/DataCopyPad 的单位
{copyCnt×b,1,15,0}以 32B 为长度/stride 单位,每次取 32B flag、跨过 480B payload。{copyCnt×b,480,32,0}中 blockLen 和 GM stride 为字节,每块读 480B、跳过 32B flag,在 UB 紧排。令输出字段有效长度为
L,token 步距为P=480b。K:2194–2204 使用的 UB 步距为:32×ceil(L/32)+32×floor((P−L)/32)=P。该等式覆盖非 32B 对齐的 h、FP4 打包、MX scales、单 float scale 和 12B 三元组。Q:342–373 按量化模式选择字段起始偏移,与此步距一致。没有因尾部向下取整 stride 而逐 token 累积错位。
6.3 可选 expertScales 的覆盖范围
K:2220–2229 每个 4B 专家权重搬入 UB 后占一个 32B 槽,覆盖当前片段开头
32×copyCnt字节。当前片段长度为480b×copyCnt,所以覆盖范围始终包含在本片段中,不会破坏后续已预取片段。覆盖前等待本片段 token/scales/索引的 MTE3 读取完成,覆盖后等待 MTE2 完成才输出。下一片段有自己的 UB 起点。6.4 串行计数与公开接口
K:2514–2518 从
{statusNum,1,0,0}改成{1,statusNum,0,0},覆盖的连续字节均为statusNum×32。后续消费者均为 Scalar GetValue,保留 MTE2_S 足够;数量或前缀和输出逻辑未变。公开 V2/V3/V4 经共享 base 路由,内部 V3 的 A5 Kernel 也包含本头文件。逐项核对 expandX、dynamicScales、assistInfo、expertTokenNums、epRecvCounts、expandScales 及确定性语义,未发现新输出契约偏差。详细对照及调用位置见 设计与精简性核查(
style_design_results/design_notes.md)。A2 设计说明没有用于推断 A5 的 packet 或 UB 约束。7. 脚本候选与静态检查
同步扫描 HEAD 产生 6 个红线、6 个高等级、25 个性能及 1 个信息候选;基线分别为 6、7、25、1。HEAD 的 12 个红线/高等级候选均有基线同类模式。已逐项区分模板参数、调用点计数、跨迭代配对、分支对称及不同数据区访问,未把脚本候选直接当作缺陷。完整原文与人工判断见 同步候选附录(
sync_candidates.md)。两个版本的图分析器均返回
findings=[];它是正则前端,无法据此证明跨函数、模板和循环回边完整正确。第 3 节的人工数据流追踪是必要补充。纯 Python 数学检查结果:
结果见
static_math_checks.json,脚本见static_math_checks.py。另用边界工具检查主要偏移乘法,见numeric_bounds.txt。这些只验证离散数学模型,不模拟硬件时序,也不是设备测试。workflow.line_verify.py处理 90 个 YAML,无 FAIL/SUSPICIOUS 项需要修正;条款拼接已完成。报告中的重点源码位置另与冻结源码核对。8. 验证局限与后续验收重点
后续设备验收宜覆盖普通/串行、共享/路由专家、有无 expertScales、各支持量化模式、非对齐 H、最大片段数、64 片段边界、部分就绪和多轮复用,尤其检查尾部地址与并发。此处仅列验收重点,没有声称这些设备用例已执行。
9. 证据索引
full.diff)、扫描清单(scan_manifest.json)、代码概要(code_summary.md)。api_prestudy.md)、逐条 API 核查(api_clause_results)。sync_candidates.md)、HEAD 同步输出(head_sync_audit.json)、基线同步输出(base_sync_audit.json)。head_ascendc_flow_analyzer.json)、基线数据流输出(base_ascendc_flow_analyzer.json)。clause_report.md)、逐条结构化结果(file_j6uok2)、风格及设计对照(style_design_results/design_notes.md)。review_plan.md)、流程工具记录(workflow_verification.txt)、数学检查结果(static_math_checks.json)。