| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
clean code Co-authored-by: yayahello<zhaopenglei@hisilicon.com> # message auto-generated for no-merge-commit merge: !11339 merge new into master clean code Created-by: yayahello Commit-by: yayahello Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> MC2 告警清理 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [x] 🐛 Bug修复 - [ ] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [ ] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: See merge request: cann/ops-transformer!11339 | 14 天前 | |
modify moe_ep_dispatch waitCnt and cached Co-authored-by: z1017i<zengzhe4@huawei.com> # message auto-generated for no-merge-commit merge: !12195 merge training_0915 into master modify moe_ep_dispatch waitCnt and cached Created-by: z1017i Commit-by: z1017i Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> 更新 moe_ep_dispatch 算子中 waitCnt 的位置与 cached模式的实现 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> https://gitcode.com/cann/ops-transformer/issues/5124 ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] 🐛 Bug修复 - [ ] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [ ] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: # 代码检视报告 ## 检视概览 - PR:https://gitcode.com/cann/ops-transformer/pull/12195/(moe_ep_dispatch) - 代码文件:mc2/moe_ep_dispatch/op_kernel/moe_ep_dispatch.h、mc2/moe_ep_dispatch/op_kernel/moe_ep_dispatch_tiling.h、mc2/moe_ep_dispatch/op_host/op_tiling/moe_ep_dispatch_tiling.cpp、mc2/common/torch_extension/csrc/elastic_buffer.cpp、mc2/common/torch_extension/elastic_buffer.py、mc2/common/docs/torchapi_ElasticBuffer.md(6 文件,+281/-116) - 代码侧别:混合(Kernel + Tiling + Host 框架 C++ + Python + 文档) - 检视文档:ascendc-red-line(10/10)、ascendc-topk(14/14)、cpp-secure(24/24)、ascendc-api(7/12)、ascendc-perf(10/13)、mc2-specific(8/19)、cpp-general(10/41)、python-secure(3/5)、cpp-style(19 条专项)、doc-style(D1-D4/D8 并入 design-check) - 总条例数:86(不含 style 19 条) - 设计文档来源:./operators/.pr_repo/12195/mc2/common/docs/(重点 torchapi_ElasticBuffer.md) - 检视时间:2026-09-17 ## 检视统计 | 状态 | 条例数 | 占比 | |------|------|------| | PASS | 79 | 91.9% | | FAIL(发现问题)| 6 | 7.0% | | SUSPICIOUS(需关注)| 1 | 1.2% | ## 发现问题(HIGH 置信度) ### [GEN-1.1] 外部数据合法性检查 内容合法,暂不修改 - **状态**:FAIL | **置信度**:HIGH - **问题描述**:cache 模式(IsCached=true)直接信任外部输入 cached_dst_slot_idx 的表内容。SendPhaseCached 从本端行首读 sendCount(moe_ep_dispatch.h:1030)后未做任何值域校验(如 0 <= sendCount <= numTokens),WriteToRemoteWindow cache 分支同样将各行首值作为 sendTokenNum(moe_ep_dispatch.h:1197)直接派生 tokenStart 与远端窗口写地址。当传入 shape 合法但内容非法的 cached 表(sendCount 超过 numTokens/numMaxTokensPerRank)时,SendTokenByChannel 中 srcTokenIdxGMTensor[tokenStart+processed](moe_ep_dispatch.h:1241)读表越界,remoteWinBaseAddr + tokenStart*perSlotBytes_(moe_ep_dispatch.h:1232-1233)越界写远端窗口,造成跨卡内存踩踏。tiling 层仅校验 shape=[ep_world_size, num_tokens+1](moe_ep_dispatch_tiling.cpp:216-232),对内容值域无校验;框架层 torch._check 仅校验 token 数一致性(elastic_buffer.py:1325-1331),均不覆盖该风险变量。 - **代码文件**:mc2/moe_ep_dispatch/op_kernel/moe_ep_dispatch.h - **起始行号**:1024 - **中止行号**:1044 - **代码片段**: cpp LocalTensor<int32_t> srcTokenTensor = topkIdsBuf_.Get<int32_t>(); LocalTensor<int32_t> sendCntTensor = maskBuf_.GetWithOffset<int32_t>(UB_STRIDE, 0); DataCopyParams sendCntHeaderCopyParams = {1U, static_cast<uint16_t>(sizeof(int32_t)), 0U, 0U}; DataCopyPad(sendCntTensor, cachedSlotIdxGMTensor_[static_cast<uint64_t>(epRankId_) * dstSlotStride_], sendCntHeaderCopyParams, padParams_); SyncFunc<AscendC::HardEvent::MTE2_S>(); uint32_t sendCount = static_cast<uint32_t>(sendCntTensor.GetValue(0)); GetLocalSlotStart(sendCount, maxBatchCnt, alignStride, localSlotStart, srcTokenIdxCopyParams); for (uint32_t group = 0; group < groupCnt; group++) { uint32_t startId = startTokenId_ + group * maxBatchCnt; uint32_t topkOffset = startId * axisK_; uint32_t tokenCnt = (group == groupCnt - 1) ? (endTokenId_ - startId) : maxBatchCnt; uint32_t validCnt = (sendCount > localSlotStart) ? (sendCount - localSlotStart) : 0U; uint32_t segCnt = tokenCnt < validCnt ? tokenCnt : validCnt; if (segCnt > 0) { uint64_t srcTokenOffset = static_cast<uint64_t>(epRankId_) * dstSlotStride_ + 1 + localSlotStart; srcTokenIdxCopyParams.blockLen = static_cast<uint32_t>(segCnt * sizeof(int32_t)); DataCopyPad(srcTokenTensor, cachedSlotIdxGMTensor_[srcTokenOffset], srcTokenIdxCopyParams, srcTokenIdxCopyPadParams_); } - **假设检验证据**: 正向证据: | 证据类型 | 分值 | 证据描述 | |---------|------|---------| | 规范违反 | 40 | cached_dst_slot_idx 为外部用户输入 tensor,Kernel 读其行首作为 sendCount(moe_ep_dispatch.h:1030,static_cast<uint32_t>(sendCntTensor.GetValue(0)))无值域校验;WriteToRemoteWindow cache 分支(moe_ep_dispatch.h:1197)同样直接消费外部内容值作为 sendTokenNum | | PR 归属 | 20 | cache 消费路径全部为本 PR 新增——SendPhaseCached(moe_ep_dispatch.h:1008-1049)、GetLocalSlotStart(moe_ep_dispatch.h:973-1005)、WriteToRemoteWindow cache 分支(moe_ep_dispatch.h:1171-1175、1193-1198)均在 diff 变更范围内 | | 数据流风险 | 15 | sendCount 直接决定 validCnt/segCnt(moe_ep_dispatch.h:1037-1038)与 DataCopyPad 读取长度;sendTokenNum 派生 cntPerChannel/tokenStart(moe_ep_dispatch.h:1200-1201)并进入远端窗口写地址(moe_ep_dispatch.h:1232-1233),值不可控 | | 调用链风险 | 15 | sendTokenNum 虚大时 SendTokenByChannel 中 srcTokenIdxGMTensor[tokenStart+processed](moe_ep_dispatch.h:1241)越过 cached 表行容量(dstSlotStride_=axisBS_+1)读,remoteWinAddr 按 tokenStart*perSlotBytes_ 越界写远端窗口(窗口按 numMaxTokensPerRank 预留) | 负向证据: | 证据类型 | 分值 | 证据描述 | |---------|------|---------| | 上游校验 | -1 | moe_ep_dispatch_tiling.cpp:218-231 校验 cached_slot_idx dim0==ep_world_size、dim1==topkDim0+1——仅 shape 校验,校验变量与风险变量(表内容 sendCount 值)不同一,按校验有效性验证规则不计分(记 -1 表示存在但无效) | | 上游校验 | -1 | elastic_buffer.py:1325-1331 torch._check(x.shape[0]==handle.topk_idx.shape[0])——仅保证 cache 复用链 numTokens 一致,不校验表内容值域,不计分(记 -1 表示存在但无效) | | 防御存在 | -1 | moe_ep_dispatch.h:1202 if (sendTokenNum == 0 \|\| tokenStart >= sendTokenNum)——仅跳过本核无任务场景,不防御 sendTokenNum 值域虚大,不计分(记 -1 表示存在但无效) | 自信值 = Σ正向 + Σ负向 = 87% ≥ 70% → 判定违规 - **修复建议**:在 SendPhaseCached 读取 sendCount 后增加防御性校验,sendCount > axisBS_(numTokens)时截断至 axisBS_ 或经 diagWriter_ 上报异常;WriteToRemoteWindow cache 分支对 sendTokenNum 同样 clamp 到 numTokens 上界。更完整的方案是在 host/tiling 侧对 cached_dst_slot_idx 首列值域做校验,或由框架层在 handle 复用时校验行首值不超过当前 num_tokens,防止外部传入非法 cached 表时跨卡窗口越界写。 ### [API-1] 禁止使用 GlobalTensor::SetValue/GetValue 已修改 - **状态**:FAIL | **置信度**:HIGH - **问题描述**:新增函数 CommunicationCached 的本端分支直接调用 GlobalTensor<uint64_t>::SetValue(0, 1)(:1081)逐元素写 GM 通知状态字,命中 API-1 生产代码黑名单。该行位于 IsCached=true 模板实例的生产执行路径(Process:1292 必经),非调试代码。同文件非 cache 路径 Communication 对同一语义操作(本端 notify 状态写 GM 窗口)已采用合规模式:LocalTensor::SetValue + DataCopy(:704/:709),新增代码未沿用该模式,且额外引入 ENTIRE_DATA_CACHE 级 DataCacheCleanAndInvalid 全量 cache 清理(:1082),代价高于既有 MTE 搬运模式。 - **代码文件**:mc2/moe_ep_dispatch/op_kernel/moe_ep_dispatch.h - **起始行号**:1064 - **中止行号**:1085 - **代码片段**: cpp for (uint32_t dstRankId = copyRankStart_; dstRankId < copyRankStart_ + copyRankNum_; ++dstRankId) { if (channelIndex_ != 0) { continue; } // 计算目标窗口地址: GM_ADDR remoteStateAddr = GetWinAddrByRankId(mc2Context_, dstRankId, cntWinStateOffset_); GM_ADDR notifyAddr = remoteStateAddr + epRankId_ * WIN_ADDR_ALIGN; if (dstRankId != epRankId_) { // 远端 使用URMA发送 count + state uint64_t commHandle = GetCommHandle(mc2Context_, dstRankId, channelIndex_); GM_ADDR remoteCountAddr = remoteStateAddr + cntFlagWinSize_ + epRankId_ * moeNumPerRankAlign512_; hcomm_.WriteWithNotifyNbi<true, PIPE_S, PIPE_MTE3, DATA_CFG>( commHandle, remoteCountAddr, sendCntWorkspaceAddr_, WIN_ADDR_ALIGN, notifyAddr, 1); } else { // 本端 GlobalTensor<uint64_t> notifyGMTensor; notifyGMTensor.SetGlobalBuffer((__gm__ uint64_t *)notifyAddr); notifyGMTensor.SetValue(0, 1); DataCacheCleanAndInvalid<uint64_t, CacheLine::ENTIRE_DATA_CACHE, DcciDst::CACHELINE_OUT>(notifyGMTensor); } } } - **假设检验证据**: 正向证据: | 证据类型 | 分值 | 证据描述 | |---------|------|---------| | 规范违反 | 40 | mc2/moe_ep_dispatch/op_kernel/moe_ep_dispatch.h:1081 notifyGMTensor.SetValue(0, 1); —— GlobalTensor<uint64_t> 逐元素 GM 写,生产路径(IsCached=true 实例化,Process:1292 调用 CommunicationCached 必经本端分支),grep 直接命中黑名单 API,且不属于条例允许的调试 GetValue 打印例外 | | 上下文防御缺失 | 30 | CommunicationCached 作用域内无合规替代实现、无例外说明注释;同文件 Communication 本端分支对同一 notify 写操作使用 LocalTensor::SetValue(0, notifyVal) + DataCopy(notifyGMTensor, notifyLocalTensor, INT64_UB_STRIDE) 合规模式(moe_ep_dispatch.h:704/:709),新增代码绕过了该既有模式 | | PR 归属 | 20 | 该行位于本次 diff 新增函数 CommunicationCached 内,diff 中为新增行 '+ notifyGMTensor.SetValue(0, 1);' | 自信值 = Σ正向 + Σ负向 = 90% ≥ 70% → 判定违规 - **修复建议**:参照同文件 Communication(:700-709) 的既有合规模式修复:在 CommunicationCached 中通过 tpipe_->InitBuffer 分配一段不小于 32B 的 UB TBuf,将通知值 1 写入 LocalTensor 后经 DataCopy 搬运至 notifyGMTensor(MTE 路径对该同核轮询场景与 GetRecvCount 轮询语义一致),可同时去除 ENTIRE_DATA_CACHE 级全量 DCCI flush;若经评审确需保留 GM 直写单元素状态字,须在代码中补充黑名单例外说明并单独确认。 ### [RL-5] 禁止使用未初始化的变量 已修改 - **状态**:FAIL | **置信度**:HIGH - **问题描述**:cache 模式(IsCached=true)新增函数 CommunicationCached 在远端分支以 workspace 的 sendCntPerRank 区基址 sendCntWorkspaceAddr_ 为 URMA 载荷源,读取 512B(WIN_ADDR_ALIGN)发往对端 count 窗口(moe_ep_dispatch.h:1076-1077)。cache 路径 Process(:1291-1296)不执行 BufferInit/CalSendCnt/ResetCounters,sendCntWorkspaceAddr_ 指向的区域在本 invocation 内从未被初始化(aclnn workspace 为运行时分配、内容不可预料,可能残留其他算子的数据),属于『内存块未经有效初始化就直接读取其值』。对比非 cache 路径 Communication 发送的 srcWorkspaceAddr 为 per-expert 区且已由同 invocation 的 CalSendCntPerExpert 写入(:690,ResetCounters 先清零后累加)。影响:(a) 未初始化设备内存内容被跨卡 DMA 读取并传输(信息暴露);(b) 若对端以非 cache 模式运行(混合模式误用),其 GetRecvCount/SetRecvNumPerExpert 会消费到错误计数导致 num_recv_per_rank/num_recv_per_expert 输出错误。同构 cache 流程中对端仅校验 state 位(WaitStatusCached:1104-1110 仅读 recvCounterGMTensor_ 状态槽)、框架侧输出复用 handle 值(elastic_buffer.py:1029-1033),垃圾数据不被消费,实际功能影响有限,但读取未初始化内存块本身违反红线。其余新增代码经逐项核查无未初始化使用:局部变量均显式初始化(localSlotStart=0 :1019、rsvdCnt=0 :992/:1023、sumOfFlag=-1 :1096 且 commpareFlag=epWorldSize_>=2 保证先写后读、sendTokenNum=0 :1193、localDescs={} :1220);Communication 的 tempTensor 各槽 SetValue 后才 DataCopyPad(:675/:683-685);UB 读取前均有 DataCopy+SyncFunc(:1027-1030、:1241-1243);成员 sendSrcTokenIdxAddr_/dstSlotStride_/maskBytesAlign_ 在 Init 全路径赋值(:303/:335-338);Python 侧 cached_num_recv_per_rank/expert 与 cached_output_capacity 严格成对(elastic_buffer.py:1332-1348 vs :1357-1375);C++ 侧 dstSlot 用 at::full(-1) 显式初始化(elastic_buffer.cpp:1735-1736)。 - **代码文件**:mc2/moe_ep_dispatch/op_kernel/moe_ep_dispatch.h - **起始行号**:1064 - **中止行号**:1085 - **代码片段**: ```cpp for (uint32_t dstRankId = copyRankStart_; dstRankId < copyRankStart_ + copyRankNum_; ++dstRankId) { if (channelIndex_ != 0) { See merge request: cann/ops-transformer!12195 | 4 天前 | |
delete urma assert Co-authored-by: z1017i<zengzhe4@huawei.com> # message auto-generated for no-merge-commit merge: !12524 merge training_0920 into master delete urma assert Created-by: z1017i Commit-by: z1017i Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] 🐛 Bug修复 - [ ] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [ ] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: See merge request: cann/ops-transformer!12524 | 1 天前 | |
Pre-Commit 规范整改 — MC2 大EP Co-authored-by: gitcode_lijd<lijiandong20@huawei.com> # message auto-generated for no-merge-commit merge: !2597 merge clean into master Pre-Commit 规范整改 — MC2 大EP Created-by: gitcode_lijd Commit-by: gitcode_lijd Merged-by: cann-robot Description: pre-commit是一个Git Hooks框架,用于在 git commit时自动运行代码检查和格式化工具。: | Hook | 功能 | 说明 | |------|------|------| | **clang-format** | C/C++ 代码格式化 | 自动格式化代码,保持风格一致 | | **OAT Check** | 开源合规检查 | 检测许可证头、禁止二进制文件提交 | 本PR对于MC2文件进行了pre-commit检查 See merge request: cann/ops-transformer!2597 | 2 个月前 |