| 新增带宽检测工具 Co-authored-by: jiangxiuhan1<jiangxiuhan@huawei.com> # message auto-generated for no-merge-commit merge: !4648 merge master into master 新增带宽检测工具 Created-by: jiangxiuhan1 Commit-by: jiangxiuhan1 Merged-by: cann-robot Description: ## 描述 1、实现MOE场景下的AlltoAll Dispatch通信带宽测试。该算子用于测试NPU设备间的通信带宽性能。 2、 torch-extension匹配aclnn接口时只匹配libopapi.so和libcustopapi.so,增加libopapi_transformer.so匹配。 ## 关联的Issue https://gitcode.com/cann/ops-transformer/issues/2829 ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] 🐛 Bug 修复 - [ ] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [ ] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: # 算子代码检视报告 **检视对象**:bandwidth_test算子(MC²领域工具算子) **检视时间**:2026-06-03 **检视模式**:全量代码检视模式(条款级精确检视) **代码侧别**:Device侧(MC²领域算子)+ Host侧(Tiling层) **检视Agent**:Ascend C 算子代码检视 Agent --- ## 一、检视概览 **检视统计** - 检视条款总数:10条核心条款 - 检视完成条款:10条 - 条款覆盖率:100% - 发现问题条款:3条 - 问题总数:3个 **问题严重程度分布** | 严重程度 | 问题数量 | 占比 | |---------|---------|------| | 严重 | 1 | 25% | | 重要 | 2 | 50% | | 一般 | 1 | 25% | **检视维度覆盖** | 维度 | 条款数 | 发现问题数 | |------|--------|-----------| | 数值安全 | 2 | 1 | | 内存安全 | 2 | 1 | | 通信安全 | 1 | 1 | | 输入验证 | 3 | 2 | | MC²领域 | 2 | 0 | --- ## 二、发现问题清单 ### 🔴 严重问题(必须立即修复) #### **问题1:WaitDispatch状态轮询可能无限循环** **违反条款**:MC2-NEW-2(通信状态同步必须有超时机制) **置信度**:HIGH (90%) **文件位置**:mc2/tools/bandwidth_test/op_kernel/bandwidth_test.h **问题行号**:455-467 **问题代码片段**: cpp // Line 455-467 - WaitDispatch函数 while (sumOfFlag != compareTarget) { // ⚠️ 无超时机制,可能永久hang // 读取状态区的flag值 SyncFunc<AscendC::HardEvent::S_MTE2>(); DataCopy(statusFp32Tensor_, windowInStatusFp32Tensor_[startStatusIndex_ * stateOffset_ / sizeof(float)], intriParams); SyncFunc<AscendC::HardEvent::MTE2_V>(); // 计算所有flag的和 ReduceSum(statusSumOutTensor, statusFp32Tensor_, gatherMaskOutBuf_.Get<float>(), 1, recStatusNumPerCore_, 1); SyncFunc<AscendC::HardEvent::V_S>(); sumOfFlag = statusSumOutTensor.GetValue(0); } **问题根因分析**: 1. **循环条件**:while (sumOfFlag != compareTarget) 2. **无退出机制**: - 没有超时计数器 - 没有最大循环次数限制 - 没有错误状态检测 3. **潜在死锁场景**: - 某个rank崩溃,无法写入状态flag - 通信链路故障,状态数据无法传输 - compareTarget计算错误(Line 448: sumTarget_ * recStatusNumPerCore_) - 状态区内存损坏 4. **对比其他通信算子**: - moe_distribute_v2_base.h的AIVRDMAPostSend有while循环但有限制(Line 117-122) - 该算子有QP_DEPTH限制,避免无限循环 **风险影响**: - Device侧kernel永久hang住 → 整卡无法响应 - 用户调用超时 → 进程hang住,影响整个训练/推理流程 - 多卡训练时 → 所有rank都会hang住等待该rank - 无法恢复 → 需要重启进程甚至重启卡 ### 🟡 重要问题(建议修复) **问题1:Tiling层属性覆盖导致的校验遗漏** 违反条款:TOPK-7(外部输入校验完整性) 置信度:MED (80%) 文件位置:mc2/tools/bandwidth_test/op_host/op_tiling/bandwidth_test_tiling.cpp 问题行号:192-193, 159-161 问题代码片段: cpp // Line 192-193 CheckInputTensorShape函数 tilingData.max_bs = static_cast<int32_t>(xDim0); // ⚠️ 直接覆盖 tilingData.data_size = static_cast<int32_t>(xDim1); // ⚠️ 直接覆盖 // Line 159-161 GetAttrAndSetTilingData函数 tilingData.world_size = static_cast<int32_t>(*worldSizePtr); tilingData.max_bs = static_cast<int32_t>(*maxBsPtr); tilingData.mode = static_cast<int32_t>(*modePtr); 假设检验过程: 阶段1:表达式建模 - CheckInputTensorShape从tensor shape获取max_bs和data_size - GetAttrAndSetTilingData从属性获取max_bs - 存在两次设置同一个字段的情况 阶段2:业务约束判断 - Line 159从属性设置max_bs(先执行) - Line 192从tensor shape覆盖max_bs(后执行) - 这可能导致属性值校验失效 阶段3:证据收集 - 证据1:Line 159设置tilingData.max_bs → +25% - 证据2:Line 192再次设置tilingData.max_bs(覆盖)→ +40% - 证据3:属性校验在Line 128检查maxBsPtr,但tensor shape校验在Line 186仅检查>0 → +30% - 证据4:data_size仅在Line 193设置一次,无属性来源 → +15% 阶段4:决策判断 - 自信值:80% > 60% → 判定存在风险 风险影响: - 属性传入的max_bs被tensor shape覆盖,可能导致不一致 - 如果用户传入属性max_bs=1000但tensor shape bs=100,实际使用100,校验不完整 - data_size仅从tensor获取,缺少属性层的预期值校验 改进建议: cpp // 建议方案1:增加一致性校验 const int64_t expectedMaxBs = tilingData.max_bs; // 属性值 OP_TILING_CHECK(xDim0 != expectedMaxBs, OP_LOGE(nodeName, "x dim0 should equal to max_bs attr, but got xDim0=%ld, maxBs=%ld.", xDim0, expectedMaxBs), return ge::GRAPH_FAILED); // 建议方案2:明确参数来源 // 移除Line 159的max_bs设置,仅在Line 192设置,并在属性校验时记录预期值 --- ## 三、条款检视详情 ### ✅ 通过条款(7条) | 条款编号 | 条款名称 | 检视结果 | 置信度 | 说明 | |---------|---------|---------|--------|------| | TOPK-5 | 属性获取类型一致 | PASS | HIGH 90% | GetAttrPointer类型匹配正确(Line 93-96, 153-156) | | MC2-13 | CCU通信数据量限制 | PASS | HIGH 85% | CheckWinSize函数Line 289-315完整校验HCCL_BUFFSIZE | | MC2-15 | 通信域字符串深拷贝 | PASS | HIGH 90% | group参数Line 158使用std::string深拷贝 | | MC2-17 | HCCL API参数验证 | PASS | MED 80% | context_->epHcclBuffer_访问有数组索引约束 | | MC2-18 | HCCL通信生命周期 | PASS | HIGH 85% | InitWinState正确管理状态区生命周期(Line 180-181) | | SEC-4.1 | 外部输入合法性校验 | PASS | HIGH 88% | Tiling层有完整校验逻辑(Line 98-135, 177-207) | | TOPK-1 | 必须校验函数返回值 | PASS | MED 75% | CheckAttrPointersNotNull返回值检查完整(Line 147-148) | ### ⚠️ 发现问题条款(3条) | 条款编号 | 条款名称 | 检视结果 | 置信度 | 问题数 | |---------|---------|---------|--------|--------| | MC2-NEW-2 | 通信状态同步超时机制 | FAIL | HIGH 90% | 1个严重问题(WaitDispatch无限循环) | | TOPK-7 | 外部输入校验 | WARN | MED 80% | 1个重要问题(属性覆盖校验遗漏) | | SEC-2.3 | 除法运算除零保护 | WARN | MED 75% | 1个重要问题(除零风险缺少防御) | --- ## 四、条款检视覆盖率统计 检视条款清单执行情况 ══════════════════════════════════════ 检视任务清单(共10条核心条款) ══════════════════════════════════════ [✅] SEC-2.3: 除法/余数运算除零保护 - WARN (发现1个重要问题) [✅] SEC-4.1: 外部输入合法性校验 - PASS [✅] TOPK-1: 必须校验函数返回值 - PASS [✅] TOPK-5: 属性获取类型需与ir原型一致 - PASS [⚠️] TOPK-7: 融合规则/InferShape/Tiling外部输入校验 - WARN (发现1个重要问题) [✅] MC2-13: CCU通信数据量限制 - PASS [✅] MC2-15: PTA通信域字符串深拷贝 - PASS [✅] MC2-17: HCCL API参数动态查阅验证 - PASS [✅] MC2-18: HCCL通信生命周期与参数 - PASS [⚠️] MC2-NEW-2:通信状态同步超时机制 - WARN (发现1个严重问题) ══════════════════════════════════════ 条款覆盖率:100% (10/10) 问题发现率:30% (3/10) ══════════════════════════════════════ --- ## 五、算子核心功能分析 **主要功能内容** 1. **MOE AlltoAll通信带宽测试** - 实现分布式token分发通信性能测试 - 根据dst_rank_id将token发送到目标rank - 支持完整流程(mode=0)和仅发送模式(mode=1) 2. **执行流程(mode=0完整流程)** - SendToMoeExpert:发送token到目标rank窗口(bandwidth_test.h:338-374) - SetStatus:统计发送数量并通知对端(bandwidth_test.h:377-409) - WaitDispatch:等待所有rank完成(bandwidth_test.h:430-481) - LocalWindowCopy:从窗口拷贝到输出(bandwidth_test.h:484-570) 3. **HCCL通信窗口机制** - 使用Mc2MoeContext管理通信上下文 - 基于epHcclBuffer_数组实现rank间数据传输 - 状态同步通过状态区flag值轮询实现 4. **Tiling层完整校验** - 属性参数校验:group/worldSize/maxBs/mode(Line 98-135) - Tensor shape校验:x/dst_rank_id/y/receiveCnt(Line 173-250) - 窗口大小校验:HCCL_BUFFSIZE限制(Line 289-315) - Workspace计算:系统预留+通信空间(Line 273-285) --- ## 六、总结与建议 **总体评价** bandwidth_test算子作为MC²领域带宽测试工具,实现了完整的AlltoAll通信流程。Host侧Tiling层校验逻辑清晰完整,但Device侧kernel代码存在防御性编程缺失, 缺少超时机制,可能导致永久死锁 **优先修复建议** | 优先级 | 问题编号 | 问题类型 | 修复建议 | |--------|---------|---------|---------| | P0(严重) | 问题1 | 缺少超时机制,永久hang风险 | 增加超时限制 | | P1(重要) | 问题2 | 除零风险缺少防御 | Line 200和529增加除零防御检查 | | P2(一般) | 问题3 | Ceil参数合法性 | 增加防御性注释或断言 | **代码质量改进建议** 1. **防御性编程加强** - Device侧kernel函数参数判空(SEC-3.5红线要求) - 所有除法运算增加除零保护 - 所有循环必须有退出机制 2. **校验逻辑完善** - Tiling层属性与tensor shape一致性校验 - 避免参数覆盖导致的校验失效 3. **代码规范优化** - kernel侧增加参数合法性断言 - 关键计算增加边界检查 --- ## 七、检视方法说明 **检视方法论** 本次检视采用假设检验驱动的条款级精确检视方法: 1. **条款识别**:基于算子类型(MC²通信算子),从规范文档识别10条核心条款 2. **假设建立**:对每个代码段建立安全假设(H0:安全) 3. **证据收集**:使用Grep/Read工具系统性收集证据 4. **自信值计算**:证据分值累加(违反+40%,无防御+30%,调用链+25%) 5. **决策判断**:自信值>60%判定风险, See merge request: cann/ops-transformer!4648 | 3 个月前 |