文件最后提交记录最后更新时间
MatmulAlltoAll和AlltoAllMatmul增加通信引擎约束描述 Co-authored-by: adamlwang<wangjingquan2@huawei.com> # message auto-generated for no-merge-commit merge: !5068 merge doc into master MatmulAlltoAll和AlltoAllMatmul增加通信引擎约束描述 Created-by: adamlwang Commit-by: adamlwang Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> 增加MatmulAlltoAll和AlltoAllMatmul的通信约束描述。 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> https://gitcode.com/cann/ops-transformer/issues/2310 ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] 🐛 Bug 修复 - [ ] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [x] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: See merge request: cann/ops-transformer!506820 天前
MC2算子资料完善 Co-authored-by: lyt_claire<luyitong1@huawei.com> # message auto-generated for no-merge-commit merge: !2997 merge mc2AIDD into master MC2算子资料完善 Created-by: lyt_claire Commit-by: lyt_claire Merged-by: cann-robot Description: ## 描述 修改MC2相关算子资料和示例代码 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] 🐛 Bug 修复 - [ ] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [X] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: See merge request: cann/ops-transformer!29971 个月前
add scenario info in error check Co-authored-by: wangkechen<wangkechen3@huawei.com> # message auto-generated for no-merge-commit merge: !4164 merge adderrorcheckinfo into master add scenario info in error check Created-by: Kiana1216 Commit-by: wangkechen Merged-by: cann-robot Description: ## 描述 alltoallmatmul和matmulalltoall算子部分报错信息缺少当前场景的描述,原因是aclnn侧使用的是公共OP_CHECK_xxxx宏,导致在不同量化场景下,使用该宏的校验打印LOG日志相似,不方便用户定位当前的场景。 ## 关联的Issue https://gitcode.com/cann/ops-transformer/issues/1865 ## 测试 本地出包验证,本地UT验证,线上rdv验证 ## 文档更新 不涉及 ## 类型标签 <!-- [x] 表示选中 --> - [ ] 🐛 Bug 修复 - [x] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [ ] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: # PR 4164 代码检视报告 ## 检视概览 **PR编号**: 4164 **PR标题**: add scenario info in error check **提交哈希**: 891de2353c837399839c07daa47f36e2f950d9b1 **检视日期**: 2026-04-15 **检视范围**: TOPK问题、红线问题、代码质量 ### 修改文件清单 | 文件路径 | 修改类型 | 变更统计 | |---------|---------|---------| | mc2/allto_all_matmul/op_api/aclnn_allto_all_quant_matmul.cpp | 修改 | 19处变更 | | mc2/matmul_allto_all/op_api/aclnn_quant_matmul_allto_all.cpp | 修改 | 20处变更 | | mc2/matmul_allto_all/op_api/matmul_allto_all_util.h | 修改 | 新增26行 | ### 修改内容摘要 该PR主要修改了 alltoallquantmatmulquantmatmulalltoall 使用宏校验的地方,增加了当前场景信息,使得报错信息更加清晰。具体修改包括: 1. 新增三个场景常量:KC_SCENEKCDYN_SCENEMX_SCENE 2. 新增三个带场景标识的校验宏: - OP_CHECK_WRONG_DIMENSION_WITH_SCENARIO - OP_CHECK_DTYPE_NOT_SUPPORT_WITH_SCENARIO - OP_CHECK_DTYPE_NOT_SAME_WITH_SCENARIO 3. 将原有的校验宏替换为带场景标识的宏,共替换30处 --- ## 检视结果汇总 ### 整体评分 | 评分维度 | 得分 | 满分 | 说明 | |---------|------|------|------| | TOPK问题合规性 | 95 | 100 | 发现1个建议性问题 | | 红线问题合规性 | 100 | 100 | 无红线问题 | | 代码质量 | 90 | 100 | 发现1个建议性问题 | | **总分** | **95** | **100** | **代码质量优秀** | ### 问题统计 | 严重级别 | 数量 | 说明 | |---------|------|------| | 🔴 严重(必须修复) | 0 | 无严重问题 | | 🟡 中等(建议修复) | 2 | 建议性优化 | | 🟢 轻微(可选修复) | 0 | 无轻微问题 | --- ## TOPK问题检查结果 ### ✅ 通过的TOPK检查项 | 序号 | 检查项 | 结果 | 说明 | |-----|--------|------|------| | TOPK-1 | 必须校验函数返回值 | ✅ 通过 | 所有函数调用均正确处理返回值 | | TOPK-2 | 使用GetInputDesc获取Dtype | ✅ 通过 | 代码中使用GetViewShape获取Shape | | TOPK-3 | 生命周期内使用局部变量指针 | ✅ 通过 | 无野指针风险 | | TOPK-4 | 属性从context获取 | ✅ 通过 | 不涉及属性获取 | | TOPK-5 | 属性获取类型需与ir原型一致 | ✅ 通过 | 不涉及属性获取 | | TOPK-6 | 必须考虑nan/inf/+0/-0等特殊值 | ✅ 通过 | 不涉及数值计算 | | TOPK-7 | 融合规则/InferShape/Tiling外部输入校验 | ✅ 通过 | 宏定义中包含输入校验 | | TOPK-8 | gm内存偏移或大小必须用int64表示 | ✅ 通过 | 不涉及内存操作 | | TOPK-9 | atomic累加需src(ub)与dst(gm)清零处理 | ✅ 通过 | 不涉及atomic操作 | | TOPK-10 | 可整数计算时不允许转浮点数计算 | ✅ 通过 | 不涉及数值计算 | | TOPK-11 | 通信算子融合需核间同步 | ✅ 通过 | 不涉及通信算子 | | TOPK-12 | 宏定义中临时变量命名不能和外部变量冲突 | ✅ 通过 | 宏定义中未使用临时变量 | | TOPK-13 | dlopen管理的so禁用thread_local | ✅ 通过 | 不涉及动态库 | ### 🟡 发现的TOPK问题 #### 问题1:宏定义中缺少空指针检查(建议性) **问题编号**: TOPK-3(生命周期内使用局部变量指针,避免野指针) **严重级别**: 🟡 中等(建议修复) **影响范围**: 所有新增的校验宏 **问题描述**: 新增的三个校验宏 OP_CHECK_WRONG_DIMENSION_WITH_SCENARIOOP_CHECK_DTYPE_NOT_SUPPORT_WITH_SCENARIOOP_CHECK_DTYPE_NOT_SAME_WITH_SCENARIO 在宏定义中直接调用 tensor->GetViewShape()tensor->GetDataType(),没有对 tensor 参数进行空指针检查。 虽然原有的宏定义 OP_CHECK_WRONG_DIMENSIONOP_CHECK_DTYPE_NOT_SUPPORTOP_CHECK_DTYPE_NOT_SAME 也没有空指针检查,但为了提高代码健壮性,建议在新宏中增加空指针检查。 **代码位置**: ```cpp // 文件:mc2/matmul_allto_all/op_api/matmul_allto_all_util.h // 行号:55-75 #define OP_CHECK_WRONG_DIMENSION_WITH_SCENARIO(tensor, expectedDimNum, scenario, retExpr) \ if (tensor->GetViewShape().GetDimNum() != expectedDimNum) { \ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "In [%s] scenario, dimension check failed: Expected %zu dimension input, but got %s with sizes %s.", \ scenario, static_cast<size_t>(expectedDimNum), #tensor, op::ToString(tensor->GetViewShape()).GetString()); \ retExpr; \ } #define OP_CHECK_DTYPE_NOT_SUPPORT_WITH_SCENARIO(tensor, supportList, scenario, retExpr) \ if (!CheckType(tensor->GetDataType(), supportList)) { \ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "In [%s] scenario, dtype check failed: Tensor %s not implemented for %s, should be in dtype support list %s.", \ scenario, #tensor, op::ToString(tensor->GetDataType()).GetString(), op::ToString(supportList).GetString()); \ retExpr; \ } #define OP_CHECK_DTYPE_NOT_SAME_WITH_SCENARIO(tensor1, tensor2, scenario, retExpr) \ if (tensor1->GetDataType() != tensor2->GetDataType()) { \ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "In [%s] scenario, dtype consistency check failed: Expected both tensors to have same dtype, but found %s %s and %s %s.", \ scenario, #tensor1, op::ToString(tensor1->GetDataType()).GetString(), \ #tensor2, op::ToString(tensor2->GetDataType()).GetString()); \ retExpr; \ } ``` **风险分析**: - **风险等级**: 中等 - **触发条件**: 当传入的 tensor 参数为 nullptr 时 - **影响后果**: 导致空指针解引用,程序崩溃 - **实际风险**: 较低,因为调用这些宏的函数通常已经在上层进行了空指针检查 **修复建议**: 建议在宏定义中增加空指针检查,与 OP_CHECK_NULL 宏保持一致: ```cpp #define OP_CHECK_WRONG_DIMENSION_WITH_SCENARIO(tensor, expectedDimNum, scenario, retExpr) \ if (IsNullptr(tensor, #tensor)) { \ retExpr; \ } \ if (tensor->GetViewShape().GetDimNum() != expectedDimNum) { \ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "In [%s] scenario, dimension check failed: Expected %zu dimension input, but got %s with sizes %s.", \ scenario, static_cast<size_t>(expectedDimNum), #tensor, op::ToString(tensor->GetViewShape()).GetString()); \ retExpr; \ } #define OP_CHECK_DTYPE_NOT_SUPPORT_WITH_SCENARIO(tensor, supportList, scenario, retExpr) \ if (IsNullptr(tensor, #tensor)) { \ retExpr; \ } \ if (!CheckType(tensor->GetDataType(), supportList)) { \ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "In [%s] scenario, dtype check failed: Tensor %s not implemented for %s, should be in dtype support list %s.", \ scenario, #tensor, op::ToString(tensor->GetDataType()).GetString(), op::ToString(supportList).GetString()); \ retExpr; \ } #define OP_CHECK_DTYPE_NOT_SAME_WITH_SCENARIO(tensor1, tensor2, scenario, retExpr) \ if (IsNullptr(tensor1, #tensor1) || IsNullptr(tensor2, #tensor2)) { \ retExpr; \ } \ if (tensor1->GetDataType() != tensor2->GetDataType()) { \ OP_LOGE(ACLNN_ERR_PARAM_INVALID, "In [%s] scenario, dtype consistency check failed: Expected both tensors to have same dtype, but found %s %s and %s %s.", \ scenario, #tensor1, op::ToString(tensor1->GetDataType()).GetString(), \ #tensor2, op::ToString(tensor2->GetDataType()).GetString()); \ retExpr; \ } ``` **注意**: 如果需要保持与原有宏的一致性,可以暂不添加空指针检查,但需要在调用这些宏的函数中确保已经进行了空指针检查。 --- ## 红线问题检查结果 ### ✅ 通过的红线检查项 | 规范编号 | 检查项 | 结果 | 说明 | |---------|--------|------|------| | cpp-secure-1.1 | 保证静态类型安全 | ✅ 通过 | 无类型转换问题 | | cpp-secure-1.2 | 保证内存安全 | ✅ 通过 | 无内存操作 | | cpp-secure-1.3 | 禁止使用未定义行为 | ✅ 通过 | 无未定义行为 | | cpp-secure-2.1 | 有符号整数运算不溢出 | ✅ 通过 | 不涉及整数运算 | | cpp-secure-2.2 | 无符号整数运算不回绕 | ✅ 通过 | 不涉及整数运算 | | cpp-secure-2.3 | 除法/余数运算除零保护 | ✅ 通过 | 不涉及除法运算 | | cpp-secure-3.1 | 禁止使用未初始化的变量 | ✅ 通过 | 所有变量均正确初始化 | | cpp-secure-3.3 | 数组索引校验 | ✅ 通过 | 不涉及数组操作 | | cpp-secure-3.4 | 禁止 sizeof 指针 | ✅ 通过 | 不涉及 sizeof | | cpp-secure-3.5 | 指针使用前判空 | ✅ 通过 | 见TOPK问题1(建议性) | | cpp-secure-4.1 | 外部输入合法性校验 | ✅ 通过 | 宏定义中包含校验 | | cpp-secure-4.2 | 内存操作长度校验 | ✅ 通过 | 不涉及内存操作 | ### 🔴 发现的红线问题 无严重红线问题。 --- ## 代码质量检查结果 ### ✅ 代码质量优点 1. **代码风格一致**:新增的宏定义与原有宏定义保持一致的代码风格和命名规范 2. **错误信息清晰**:新增的场景信息使得错误信息更加明确,便于问题定位 3. **向后兼容**:保留了原有的宏定义,不影响现有代码 4. **场景覆盖完整**:覆盖了KC、KCDYN、MX三种量化场景 5. **参数匹配正确**:所有宏调用的参数数量和类型均正确 ### 🟡 发现的代码质量问题 #### 问题2:场景常量定义位置建议优化 **严重级别**: 🟡 中等(建议修复) **影响范围**: matmul_allto_all_util.h **问题描述**: 新增的三个场景常量 KC_SCENEKCDYN_SCENEMX_SCENE 定义在头文件中,且使用了 constexpr char[] 类型。这些常量可能会在多个编译单元中重复定义,导致链接时出现符号重复定义的问题。 **代码位置**: ```cpp // 文件:mc2/matmul_allto_all/op_api/matmul_allto_all_util.h // 行号:31-33 constexpr char KC_SCENE[] = "KC quantization(x1QuantMode=3, x2QuantMode=2)"; constexpr char KCD[] = "KCDYN quantization(x1QuantMode=7, x2QuantMode=2)"; constexpr char MX_SCENE[] = "MX quantization(x1QuantMode=6, x2QuantMode=6)"; ``` **修复建议**: 建议将场景常量定义为 inline 变量或使用字符串字面量: ```cpp // 方案1:使用 inline 变量(C++17+) inline constexpr char KC_SCENE[] = "KC quantization(x1QuantMode=3, x2QuantMode=2)"; inline constexpr char KCDYN_SCENE[] = "KCDYN quantization(x1QuantMode=7, x2QuantMode=2)"; inline constexpr char MX_SCENE[] = "MX quantization(x1QuantMode=6, x2QuantMode=6)"; // 方案2:使用字符串字面量(推荐) #define KC_SCENE "KC quantization(x1QuantMode=3, x2QuantMode=2)" #define KCDYN_SCENE "KCDYN quantization(x1QuantMode=7, x2QuantMode=2)" #define MX_SCENE "MX quantization(x1QuantMode=6, x2QuantMode=6)" ``` **注意**: 如果项目中已经使用了类似的常量定义方式且没有出现问题,可以保持现状。但从代码质量和可移植性角度考虑,建议使用方案2(宏定义)。 --- ## 性能影响分析 ### 性能影响评估 | 影响方面 | 评估结果 | 说明 | |---------|---------|------| | 编译时间 | 无影响 | 仅增加宏定义,不增加编译负担 | | 运行时性能 | 无影响 | 仅在错误情况下执行,正常路径无影响 | | 内存占用 | 无影响 | 仅增加少量字符串常量 | | 代码体积 | 轻微增加 | 增加约26行代码 | ### 性能优化建议 无性能优化建议,代码修改对性能无负面影响。 --- ## 精度影响分析 ### 精度影响评估 | 影响方面 | 评估结果 | 说明 | |---------|---------|------| | 计算精度 | 无影响 | 不涉及数值计算 | | 数据类型 | 无影响 | 不涉及数据类型转换 | | 边界处理 | 无影响 | 不涉及边界值处理 | --- ## 安全性分析 ### 安全性评估 | 安全方面 | 评估结果 | 说明 | |---------|---------|------| | 空指针安全 | 🟡 良好 | 见TOPK问题1(建议性) | | 内存安全 | ✅ 优秀 | 无内存操作 | | 输入验证 | ✅ 优秀 | 宏定义中包含校验 | | 日志安全 | ✅ 优秀 | 参数匹配正确 | --- ## 可维护性分析 ### 可维护性评估 | 维护方面 | 评估结果 | 说明 | |---------|---------|------| | 代码可读性 | ✅ 优秀 | 错误信息清晰,易于理解 | | 代码可扩展性 | ✅ 优秀 | 宏定义易于扩展新场景 | | 代码可测试性 | ✅ 优秀 | 宏定义易于测试 | | 文档完整性 | 🟡 良好 | 建议添加宏使用说明 | ### 可维护性建议 建议在 matmul_allto_all_util.h 文件头部添加宏使用说明注释: ```cpp /** * @brief 带场景标识的校验宏,用于区分不同量化场景下的校验错误 * * 使用场景: * - KC_SCENE: KC量化场景(x1QuantMode=3, x2QuantMode=2) * - KCDYN_SCENE: KCDYN量化场景(x1QuantMode=7, x2QuantMode=2) * - MX_SCENE: MX量化场景(x1QuantMode=6, x2QuantMode=6) * * 注意事项: * - 调用这些宏前请确保tensor参数已进行空指针检查 * - 这些宏主要用于参数校验,不应在性能关键路径中使用 */ ``` --- ## 代码示例对比 ### 修改前(错误信息) ``` Expected 1 dimension input, but got x2Scale with sizes [128]. ``` ### 修改后(错误信息) ``` In [KCDYN quantization(x1QuantMode=7, x2QuantMode=2)] scenario, dimension check failed: Expected 1 dimension input, but got x2Scale with sizes [128]. ``` ### 改进效果 - ✅ 明确了当前量化场景(KCDYN) - ✅ 提供了量化模式的详细信息(x1QuantMode=7, x2QuantMode=2) - ✅ 便于用户快速定位问题原因 --- ## 检视结论 ### 总体评价 该PR的代码修改质量优秀,主要改进了错误信息的清晰度,使得用户在遇到参数校验错误时能够快速定位问题所在的具体量化场景。代码风格与现有代码保持一致,没有引入新的安全风险或性能问题。 ### 检视结论 **✅ 通过检视,建议合并** ### 评分详情 | 评分维度 | 得分 | 满分 | 权重 | 加权得分 | |---------|------|------|------|-- See merge request: cann/ops-transformer!41641 个月前
修复A2A3环境下EsTranspose和aclrtGetArgsFromExceptionInfo符号未定义问题 Co-authored-by: y00951989<yangshengjun3@huawei.com> # message auto-generated for no-merge-commit merge: !5077 merge A2A3_pr into master 修复A2A3环境下EsTranspose和aclrtGetArgsFromExceptionInfo符号未定义问题 Created-by: yangshengjun703 Commit-by: y00951989 Merged-by: cann-robot Description: ## 描述 解决A2A3环境下EsTranspose和aclrtGetArgsFromExceptionInfo符号未定义问题 ## 关联Issue 关联的Issue [https://gitcode.com/cann/ops-transformer/issues/2334](url) ## 测试 完成线上A5 A2 A3 rdv 及 本地问题单复现场景A2A3的用例测试,精度通过 # Ascend C 算子代码检视报告 ## 1. 检视概要 **检视文件**:C:\y00951989\5077.diff(171行) **检视模式**:PR 检视(C++安全检视) **检视范围**: - **文件1**:mc2/common/utils/mc2_exception_dump.h - 异常处理动态库加载改造 - **文件2**:mc2/matmul_allto_all/op_graph/fusion_pass/matmul_all_to_all_transpose_a5_fusion_pass.cpp - fusion pass 动态库加载 **核心变更**: - 使用 dlopen/dlsym 动态加载 API 函数,替代直接调用 - 目的:解决符号依赖问题,提升版本兼容性 **问题统计**: - **CRITICAL级别**:2个(空指针解引用、资源泄露) - **MEDIUM级别**:2个(外部输入校验、LOG安全) - **LOW级别**:0个 **检视结论**:该PR引入动态库加载机制解决版本兼容性问题,但存在**2个CRITICAL级别安全风险**,必须在合并前修复。 --- ## 2. 问题详情(按严重级别排序) ### CRITICAL-1:空指针解引用风险(cpp-secure 3.5) **严重级别**:CRITICAL(高) **假设检验过程**: | 步骤 | 假设与证据 | 自信值 | |------|-----------|-------| | **H0** | func 指针在使用前已判空 | 0% | | **证据1** | 行152:static EsTransposeFunc func = GetEsTransposeFunc(); 从 GetEsTransposeFunc() 获取指针 | +40% | | **证据2** | GetEsTransposeFunc() 可能返回 nullptr(dlopen 或 dlsym 失败时,第139、145行) | +30% | | **证据3** | TransposeDL 函数中第154行直接调用 func(...),未进行判空检查 | +30% | | **H1** | **func 指针可能为 nullptr,直接调用会导致程序崩溃** | **100%** | **关联条款**:cpp-secure 3.5(指针使用前判空)、TOPK-1(必须校验函数返回值) **代码路径**:mc2/matmul_allto_all/op_graph/fusion_pass/matmul_all_to_all_transpose_a5_fusion_pass.cpp(diff行152-154) **问题类型**:内存安全 - 空指针解引用 **问题代码片段**: ```cpp // 行150-157(TransposeDL 函数) ge::es::EsTensorHolder TransposeDL(const ge::es::EsTensorLike& x, const ge::es::EsTensorLike& perm) { static EsTransposeFunc func = GetEsTransposeFunc(); // ❌ 可能返回 nullptr auto* builder = ge::es::ResolveBuilder(x, perm); auto result = func(x.ToTensorHolder(builder).GetCTensorHolder(), // ❌ 直接调用,未判空 perm.ToTensorHolder(builder).GetCTensorHolder()); return result; } ``` **修改建议**: ```cpp // ✅ 正确:添加判空检查 ge::es::EsTensorHolder TransposeDL(const ge::es::EsTensorLike& x, const ge::es::EsTensorLike& perm) { static EsTransposeFunc func = GetEsTransposeFunc(); if (func == nullptr) { OPS_LOG_E("MatmulAllToAllTransposeA5FusionPass", "EsTranspose function not loaded"); return ge::es::EsTensorHolder(); // 返回空对象或抛出异常 } auto* builder = ge::es::ResolveBuilder(x, perm); auto result = func(x.ToTensorHolder(builder).GetCTensorHolder(), perm.ToTensorHolder(builder).GetCTensorHolder()); return result; } ``` --- ### CRITICAL-2:资源泄露风险(cpp-secure 5.2) **严重级别**:CRITICAL(高) **假设检验过程**: | 步骤 | 假设与证据 | 自信值 | |------|-----------|-------| | **H0** | dlopen handle 资源正确释放 | 0% | | **证据1** | 行136:dlopen("libes_math.so", RTLD_LAZY | RTLD_GLOBAL) 使用 RTLD_LAZY | RTLD_GLOBAL 标志 | +40% | | **证据2** | RTLD_LAZY | RTLD_GLOBAL 标志会增加动态库的引用计数 | +30% | | **证据3** | 整个函数作用域内无 dlclose 调用(第136-148行) | +30% | | **证据4** | handle 为局部变量,函数返回后丢失,无法后续释放 | +20% | | **H1** | **dlopen 增加了引用计数,但未配对 dlclose,导致资源泄露** | **100%** | **关联条款**:cpp-secure 5.2(资源申请和释放必须匹配) **代码路径**:mc2/matmul_allto_all/op_graph/fusion_pass/matmul_all_to_all_transpose_a5_fusion_pass.cpp(diff行136-148) **问题类型**:资源泄露 - dlopen未配对dlclose **问题分析**: - RTLD_LAZY | RTLD_GLOBAL 标志会加载库并增加引用计数 - 函数返回后 handle 局部变量丢失,无法后续调用 dlclose - 如果库被多次加载(虽然 static func 缓存了结果,但每次检查都会执行 dlopen),会导致库无法被正常卸载 **修改建议**: **方案1:使用 RTLD_NOLOAD,仅查询不增加引用计数**(推荐) ```cpp // ✅ 正确:使用 RTLD_NOLOAD,不增加引用计数 EsTransposeFunc GetEsTransposeFunc() { void* handle = dlopen("libes_math.so", RTLD_NOLOAD | RTLD_LAZY); // 仅查询 if (!handle) { OPS_LOG_E("MatmulAllToAllTransposeA5FusionPass", "dlopen failed: %s", dlerror()); return nullptr; } dlerror(); auto func = reinterpret_cast<EsTransposeFunc>(dlsym(handle, "EsTranspose")); if (dlerror() != nullptr) { OPS_LOG_E("MatmulAllToAllTransposeA5FusionPass", "dlsym EsTranspose failed"); return nullptr; } return func; // RTLD_NOLOAD 不增加引用计数,无需 dlclose } ``` --- ### MEDIUM-1:外部输入参数未判空(cpp-secure 4.1) **严重级别**:MEDIUM(中) **假设检验过程**: | 步骤 | 假设与证据 | 自信值 | |------|-----------|-------| | **H0** | args 参数正确校验 | 0% | | **证据1** | args 参数作为 aclrtExceptionInfo 指针,属于外部输入(来自异常回调) | +40% | | **证据2** | diff 第81行直接使用 args 参数调用函数,未显示判空检查 | +30% | | **证据3** | 虽然理论上异常回调不应传入 nullptr,但规范要求对外部输入必须校验 | +20% | | **H1** | **args 参数作为外部输入,建议添加判空检查** | **70%** | **关联条款**:cpp-secure 4.1(外部输入数据合法性校验) **代码路径**:mc2/common/utils/mc2_exception_dump.h(diff行81) **问题类型**:外部输入校验 - 参数未判空 **问题代码片段**: ```cpp // 行81(Mc2ExceptionImpl 函数) auto ret = aclrtGetArgsFromExceptionInfoFunc(args, &devArgsPtr, &devArgsLen); // args 未判空 ``` **修改建议**: ```cpp // ✅ 正确:添加参数校验 inline void Mc2ExceptionImpl(aclrtExceptionInfo *args, void *userdata, const char *op) { // 添加外部输入校验 if (args == nullptr) { OP_LOGE(OP_NAME, "args is nullptr, invalid exception info"); return; } // Get addr of hccl context from ExceptionInfo void* devArgsPtr = nullptr; uint32_t devArgsLen = 0; ... } ``` --- ### MEDIUM-2:LOG API 潜在空指针风险(cpp-secure 11.1) **严重级别**:MEDIUM(中) **假设检验过程**: | 步骤 | 假设与证据 | 自信值 | |------|-----------|-------| | **H0** | dlerror() 返回值作为 LOG 参数安全 | 0% | | **证据1** | dlerror() 函数在无错误时返回 nullptr | +40% | | **证据2** | 代码中直接将 dlerror() 作为 %s 参数传入 OP_LOGE(第34、37、55、60行) | +30% | | **证据3** | 虽然在错误分支调用理论上应返回错误字符串,但不同平台行为可能有差异 | +20% | | **H1** | **dlerror() 可能返回 nullptr,作为 %s 参数可能导致段错误** | **50%** | **结论**:自信值 **50%** < 60%,无法推翻原假设H0,但存在**需关注**风险点。 **关联条款**:cpp-secure 11.1(LOG API 禁止传入空指针作为字符串参数) **代码路径**:mc2/common/utils/mc2_exception_dump.h(diff行34、37、55、60) **问题类型**:LOG安全 - 潜在空指针风险 **问题代码片段**: ```cpp // 行34、37、55、60 OP_LOGE(OP_NAME, "dlsym aclrtGetArgsFromExceptionInfo failed: %s", dlerror()); // ❌ dlerror() 可能为 nullptr OP_LOGE(OP_NAME, "dlopen failed: %s", dlerror()); // ❌ dlerror() 可能为 nullptr ``` **修改建议**: ```cpp // ✅ 正确:判空或使用安全格式 // 方案1:判空 const char* errMsg = dlerror(); OP_LOGE(OP_NAME, "dlopen failed: %s", errMsg ? errMsg : "unknown error"); // 方案2:使用安全格式 OP_LOGE(OP_NAME, "dlopen failed, error code: %p", dlerror()); // 打印指针地址 ``` --- ## 3. 通过条款 以下条款经检视后确认代码符合规范: ### TOPK-13:禁止 thread_local 变量 - ✅ **通过**:代码中使用 static 变量,未使用 thread_local 关键字 ### TOPK-1:必须校验函数返回值 - ✅ **通过**:dlopen、dlsym、aclrtGetArgsFromExceptionInfo、acldumpGetPath 等关键函数均有返回值校验 ### cpp-secure 3.1:禁止使用未初始化的变量 - ✅ **通过**:所有 static 变量均显式初始化(func = nullptrinitialized = false) ### cpp-secure 11.3:LOG API 参数类型必须与格式化说明符匹配 - ✅ **通过**:%s 对应 dlerror() 返回值(char*),%d 对应 aclError 类型(整型),类型匹配 ### mc2_exception_dump.h 中的 RTLD_NOLOAD 使用 - ✅ **合理**:GetAclrtGetArgsFromExceptionInfoFunc() 和 GetAcldumpGetPathFunc() 使用 RTLD_NOLOAD | RTLD_LAZY,仅查询库是否已加载,不增加引用计数,无需 dlclose --- ## 4. 整体评价 ### 优点总结: 1. **架构设计合理**:使用动态加载机制解决版本兼容性问题,避免硬编码符号依赖 2. **函数指针管理规范**:使用 static 变量缓存函数指针,避免重复加载开销 3. **错误处理完善**:dlopen/dlsym 失败时记录日志,提供错误信息 4. **返回值校验完整**:关键函数调用均有返回值校验和错误处理 5. **RTLD_NOLOAD 使用正确**:mc2_exception_dump.h 中使用 RTLD_NOLOAD 避免增加引用计数 ### 需改进项总结: **必须修改(CRITICAL)**: 1. ✅ TransposeDL 函数添加 func 指针判空检查(防止空指针解引用崩溃) 2. ✅ GetEsTransposeFunc() 修改为 RTLD_NOLOAD 或添加 dlclose(防止资源泄露) **建议修改(MEDIUM)**: 1. ✅ Mc2ExceptionImpl 函数添加 args 参数判空检查(外部输入校验) 2. ✅ LOG 宏中的 dlerror() 返回值判空或使用安全格式(防止段错误) ### 综合评分: | 维度 | 评分 | 说明 | |------|------|------| | **安全编码** | 60/100 | 2个CRITICAL安全问题需立即修复 | | **API使用** | 75/100 | dlopen/dlsym 使用基本规范,但存在资源泄露风险 | | **性能优化** | 90/100 | static 缓存设计合理,避免重复加载 | | **代码规范** | 85/100 | 注释清晰,格式规范 | | **版本兼容性** | 95/100 | 动态加载机制解决符号依赖问题 | **总分**:**81/100** --- ## 5. 结论与建议 ### 检视结论: 该PR引入动态库加载机制(dlopen/dlsym)解决版本兼容性问题,架构设计合理。但存在**2个CRITICAL级别的安全风险**(空指针解引用、资源泄露),必须在合并前修复。 ### 修改要求: **必须修复(阻塞合并)**: 1. ✅ **TransposeDL 函数添加判空检查**(cpp-secure 3.5) - 添加 if (func == nullptr) 检查,防止空指针解引用崩溃 - 返回空对象或抛出异常作为错误处理 2. ✅ **GetEsTransposeFunc() 资源泄露修复**(cpp-secure 5.2) - **方案1(推荐)**:改用 RTLD_NOLOAD | RTLD_LAZY,仅查询不增加引用计数 - **方案2**:缓存 handle 并添加清理函数,确保引用计数匹配 **建议修复(推荐)**: 1. ✅ Mc2ExceptionImpl 函数添加 args 参数校验(cpp-secure 4.1) 2. ✅ LOG 宏中 dlerror() 返回值判空(cpp-secure 11.1) ### 建议操作: 1. **立即修复 CRITICAL 问题**:优先修复空指针解引用和资源泄露问题 2. **补充单元测试**:测试 dlopen/dlsym 失败场景,验证错误处理逻辑 3. **添加文档说明**:在 README 或代码注释中说明动态加载机制的使用场景和注意事项 4. **代码 Review**:邀请团队成员 Review 修复后的代码 5. **性能测试**:验证动态加载对性能的影响(虽然 static 缓存可避免重复加载) --- **报告生成时间**:2026-05-08 **检视人**:AI Code Reviewer (ascendc-ops-reviewer) **检视模式**:PR检视(C++安全检视) **规范版本**:cpp-secure.md、ascendc-topk.md **检视状态**:已完成,发现2个 See merge request: cann/ops-transformer!507717 天前
fix-ccusmoke Co-authored-by: qq_43844249<fanglin17@huawei.com> # message auto-generated for no-merge-commit merge: !5138 merge fix-ccusmoke into master fix-ccusmoke Created-by: qq_43844249 Commit-by: qq_43844249 Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> # 代码检视报告 **项目名称**:ops-transformer MC2算子通信引擎修复检视报告 **检视模块**:6个Tiling文件(allto_all/matmul_allto_all系列) **检视人**:Ascend C Code Review Agent **检视日期**:2026-05-11 **检视模式**:PR检视(提交 a8bddade8) **代码侧别**:Tiling侧(Host侧) --- ## 🔍 检视概览 | 统计项 | 数值 | | ---- | ---- | | 检视条款总数 | 8 条 | | 通过条款 | 7 条 | | 需关注条款 | 1 条 | | 发现问题总数 | 0 个(无严重级违规) | | 需关注建议 | 1 个(建议添加注释) | | 检视置信度分布 | HIGH: 0个 / MED: 1个 / LOW: 2个 | **核心结论**:本次修改的技术合理性正确,代码安全性合规,无严重级违规问题。存在1处中等置信度的可读性改进建议(建议添加注释说明修改原因),2处低置信度的类型安全和常量语义提醒(属代码规范建议,非强制整改项)。 **修改概述**: - 修改内容:将 mc2tiling::A5_CCU_ENGINE (值为5) 改为硬编码数字 0 - 修改范围:6个文件,每个文件仅修改1行 - 技术背景:根据 mc2_tiling_utils.h 注释,5 对应 CCU_MS引擎,仅在 A2/3架构支持,A5不支持;改为默认值 0 可解决 CCU Smoke 测试问题 --- ## 📊 检视条款执行详情 | 条款编号 | 条款名称 | 适用范围 | 检视结果 | 置信度 | 备注 | |---------|---------|---------|---------|--------|------| | CLAUSE-1 | 总体原则-静态类型安全(1.1) | All | ✅ PASS | LOW | 存在隐式类型转换(int→uint8_t),但值在范围内 | | CLAUSE-2 | 总体原则-内存安全(1.2) | All | ✅ PASS | - | 不涉及内存操作 | | CLAUSE-3 | 总体原则-禁止未定义行为(1.3) | All | ✅ PASS | - | 合法C++行为 | | CLAUSE-4 | 接口变更兼容性(10.12) | All | ⚠️ 需关注 | MED | 建议添加注释说明修改原因 | | CLAUSE-5 | 返回值校验(TOPK-1) | Host | ✅ PASS | - | 已有 isSuccess() 检查 | | CLAUSE-6 | 外部输入校验(TOPK-7) | Host | ✅ PASS | - | 不引入新的外部输入 | | CLAUSE-7 | 常量单一职责(4.3) | All | ✅ PASS | LOW | 建议添加注释说明语义 | | CLAUSE-8 | 禁止未初始化变量(5.5) | All | ✅ PASS | - | 不涉及变量声明 | --- ## ⚠️ 需关注建议详情 ### 建议 ID:SUGGESTION-001 | 严重级别:MEDIUM(建议) #### 🔬 假设检验过程 **代码段**:SetHcclTiling() 函数中的 withCommEngine(0) 调用 **假设**:H0: 修改不影响代码可读性和可维护性 | 证据序号 | 证据类型 | 规范ID | 证据描述 | 分值增量 | 累计自信值 | |---------|---------|--------|---------|---------|-----------| | 1 | 规范违反(轻) | cpp-secure.md 10.12 | 接口参数值变更未添加注释说明 | +40% | 40% | | 2 | 可读性降低 | - | 硬编码数字 0 缺乏语义说明 | +30% | 70% | **结论**:自信值 **70%** > 60%,**推翻原假设H0**,建议添加注释提升可维护性。 --- **关联规范条款**:cpp-secure.md 10.12(接口变更兼容性) **代码路径**:6个文件的 SetHcclTiling() 函数 - mc2/allto_all_matmul/op_host/op_tiling/arch35/allto_all_fp_matmul_tiling_base.cpp:192 - mc2/allto_all_matmul/op_host/op_tiling/arch35/allto_all_kc_quant_matmul_tiling_base.cpp:236 - mc2/allto_all_matmul/op_host/op_tiling/arch35/allto_all_mx_quant_matmul_tiling_base.cpp:493 - mc2/matmul_allto_all/op_host/op_tiling/arch35/fp_matmul_allto_all_tiling_base.cpp:177 - mc2/matmul_allto_all/op_host/op_tiling/arch35/kc_quant_matmul_allto_all_tiling_base.cpp:148 - mc2/matmul_allto_all/op_host/op_tiling/arch35/mx_quant_matmul_allto_all_tiling_base.cpp:608 **问题类型**:代码可读性建议 **问题描述**:修改将语义明确的常量 mc2tiling::A5_CCU_ENGINE 改为硬编码数字 0,降低了代码的可读性和可维护性。后续维护者需要查阅注释才能理解 0 的含义(默认通信引擎),增加了理解成本。虽用户明确排除魔鬼数字规范检查,但从工程实践角度,建议添加注释说明修改原因和技术背景。 --- #### 修改建议 **修改前代码**: ```cpp // reducetype接口附带的数据类型优先于调用通信接口传入的数据类型,因此这里需要设置 AscendC::Mc2CcTilingConfig allToAllTilingConfig = allToAllBuilder.withCommEngine(0) .withReduceType(opName_, AscendC::HcclReduceOp::HCCL_REDUCE_SUM, contextInfo_.args_.geAType, contextInfo_.args_.geAType) .build(); ``` **修改后代码**: ```cpp // reducetype接口附带的数据类型优先于调用通信接口传入的数据类型,因此这里需要设置 // 【CCU Smoke Fix】A5架构不支持CCU_MS引擎(值为5),改用默认引擎(值为0) // 参考:mc2_tiling_utils.h注释:"5:CCU_MS(A2/3支持 A5不支持)" AscendC::Mc2CcTilingConfig allToAllTilingConfig = allToAllBuilder.withCommEngine(0) // 默认通信引擎,适配A5架构 .withReduceType(opName_, AscendC::HcclReduceOp::HCCL_REDUCE_SUM, contextInfo_.args_.geAType, contextInfo_.args_.geAType) .build(); ``` **修改说明**:添加注释说明修改原因和技术背景,提升代码可维护性。注释包含: 1. 修改原因:解决 A5 架构 CCU Smoke 测试问题 2. 技术背景:引用 mc2_tiling_utils.h 注释,说明 5 在 A5 不支持 3. 语义说明:标注 0 表示默认通信引擎 --- ## ✅ 通过条款补充说明 ### CLAUSE-1:静态类型安全(置信度 LOW) **分析**:修改将 int 类型字面量 0 传递给可能期望 uint8_t 的 API(根据常量定义推断),存在隐式类型转换。但: - C++ 允许 intuint8_t 的隐式转换(缩窄转换) - 值 0uint8_t 表示范围内(0-255) - 无类型溢出风险 **建议**:类型转换风险较低,但建议添加注释说明类型兼容性。 --- ### CLAUSE-7:常量单一职责(置信度 LOW) **分析**:硬编码数字 0 的语义明确(根据注释"0:默认值"),保持单一职责(表示默认通信引擎)。但可读性有所降低,建议添加注释辅助理解。 --- ## 🔧 技术合理性验证 ### 修改背景分析 根据 mc2_tiling_utils.h 第 51-56 行注释: ```cpp /** 当前通信API未提供枚举,后续会提供 0:默认值 1:HOST_TS(A2/3支持 A5不支持)2:AICPU_TS(A2/3支持 A5不支持) 3:AIV 4:AIV_ONLY(A2/3支持 A5不支持) 5:CCU_MS(A2/3支持 A5不支持) 6:CCU_SCHED(A2/3支持 A5不支持) 7:AICPU_UB/ROCE(A5不支持) **/ ``` **技术合理性**: - mc2tiling::A5_CCU_ENGINE = 5 对应 CCU_MS,注释明确标注"**A5不支持**" - 改为默认值 0 是合理的修复方案 - 其他算子(moe_distribute 系列)仍使用 A5_CCU_ENGINE,可能需要后续修复 ### 功能影响评估 **正面影响**: - 解决 A5 架构 CCU Smoke 测试失败问题 - 使用默认通信引擎,适配 A5 硬件限制 **潜在风险**: - 默认引擎 0 在 A5 上的性能是否与预期一致?建议验证性能 - 其他算子(moe_distribute)是否需要相同修复?建议统一处理 --- ## 📝 整改建议汇总 | 建议编号 | 建议类型 | 严重级别 | 建议内容 | 优先级 | |---------|---------|---------|---------|--------| | SUGGESTION-001 | 可读性改进 | MEDIUM | 添加注释说明修改原因和技术背景 | P2(建议执行) | | SUGGESTION-002 | 代码一致性 | LOW | 检查 moe_distribute 系列算子是否需要相同修复 | P3(可选) | | SUGGESTION-003 | 性能验证 | LOW | 验证默认引擎 0 在 A5 架构上的性能表现 | P3(可选) | --- ## ✅ 检视结论 **合规性评估**: - ✅ C++安全编码规范:8条条款全部通过(无严重级违规) - ✅ TOPK问题清单:相关条款全部通过 - ⚠️ 代码可读性:建议添加注释(非强制整改项) **技术合理性评估**: - ✅ 修改背景清晰:A5架构不支持CCU_MS引擎(值为5) - ✅ 修复方案合理:改为默认值(0) - ⚠️ 需验证性能和一致性 **整改建议**: 1. **建议执行**:添加注释说明修改原因(6个文件统一修改) 2. **可选执行**:检查 moe_distribute 系列算子是否需要相同修复 3. **可选执行**:验证默认引擎在 A5 上的性能表现 **最终结论**:本次修改**技术合理性正确,安全性合规**,建议添加注释提升可维护性,无需强制整改。 --- ## 📄 报告生成信息 **报告生成时间**:2026-05-11 **报告状态**:已完成检视,建议整改(非强制) **检视覆盖率**:8/8 条款(100%覆盖) **检视方法**:假设检验驱动 + 证据链追溯 --- ## 附录:修改文件列表 | 序号 | 文件路径 | 修改行 | 修改内容 | |-----|---------|--------|---------| | 1 | mc2/allto_all_matmul/op_host/op_tiling/arch35/allto_all_fp_matmul_tiling_base.cpp | 192 | mc2tiling::A5_CCU_ENGINE0 | | 2 | mc2/allto_all_matmul/op_host/op_tiling/arch35/allto_all_kc_quant_matmul_tiling_base.cpp | 236 | mc2tiling::A5_CCU_ENGINE0 | | 3 | mc2/allto_all_matmul/op_host/op_tiling/arch35/allto_all_mx_quant_matmul_tiling_base.cpp | 493 | mc2tiling::A5_CCU_ENGINE0 | | 4 | mc2/matmul_allto_all/op_host/op_tiling/arch35/fp_matmul_allto_all_tiling_base.cpp | 177 | mc2tiling::A5_CCU_ENGINE0 | | 5 | mc2/matmul_allto_all/op_host/op_tiling/arch35/kc_quant_matmul_allto_all_tiling_base.cpp | 148 | mc2tiling::A5_CCU_ENGINE0 | | 6 | mc2/matmul_allto_all/op_host/op_tiling/arch35/mx_quant_matmul_allto_all_tiling_base.cpp | 608 | mc2tiling::A5_CCU_ENGINE0 | ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [x] 🐛 Bug 修复 - [ ] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [ ] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: See merge request: cann/ops-transformer!513818 天前
mmalltoall代际隔离 Co-authored-by: qzzzy1<qiziyu2@huawei.com> # message auto-generated for no-merge-commit merge: !4924 merge master into master mmalltoall代际隔离 Created-by: qzzzy1 Commit-by: qzzzy1 Merged-by: cann-robot Description: ## 描述 mmalltoall代际隔离 ## 关联的Issue 关联issue 2241 ## 测试 二级冒烟,本地自测试 ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] 🐛 Bug 修复 - [ ] ✨ 新特性 - [x] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [ ] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: See merge request: cann/ops-transformer!492422 天前
mmalltoall代际隔离 Co-authored-by: qzzzy1<qiziyu2@huawei.com> # message auto-generated for no-merge-commit merge: !4924 merge master into master mmalltoall代际隔离 Created-by: qzzzy1 Commit-by: qzzzy1 Merged-by: cann-robot Description: ## 描述 mmalltoall代际隔离 ## 关联的Issue 关联issue 2241 ## 测试 二级冒烟,本地自测试 ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] 🐛 Bug 修复 - [ ] ✨ 新特性 - [x] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [ ] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: See merge request: cann/ops-transformer!492422 天前
MmA2A_init Co-authored-by: 何梓洋_蓝区<heziyang5@h-partners.com> # message auto-generated for no-merge-commit merge: !765 merge MmA2a_master into master MmA2A_init Created-by: Hilfsblaetter Commit-by: 何梓洋_蓝区 Merged-by: cann-robot Description: ## 描述 新增算子 MatmulAlltoAll ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-transformer!7654 个月前
MatmulAlltoAll和AlltoAllMatmul增加通信引擎约束描述 Co-authored-by: adamlwang<wangjingquan2@huawei.com> # message auto-generated for no-merge-commit merge: !5068 merge doc into master MatmulAlltoAll和AlltoAllMatmul增加通信引擎约束描述 Created-by: adamlwang Commit-by: adamlwang Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> 增加MatmulAlltoAll和AlltoAllMatmul的通信约束描述。 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> https://gitcode.com/cann/ops-transformer/issues/2310 ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] 🐛 Bug 修复 - [ ] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [x] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: See merge request: cann/ops-transformer!506820 天前
README.md

MatmulAlltoAll

产品支持情况

产品 是否支持
Ascend 950PR/Ascend 950DT
Atlas A3 训练系列产品/Atlas A3 推理系列产品
Atlas A2 训练系列产品/Atlas A2 推理系列产品
Atlas 200I/500 A2 推理产品 ×
Atlas 推理系列产品 ×
Atlas 训练系列产品 ×

功能说明

  • 算子功能:完成量化的Matmul计算、Permute(保证通信后地址连续)和AlltoAll通信的融合,先计算后通信,支持非量化、K-C量化和mx量化模式

  • 计算公式:假设x1的shape为(BS, H1),x2的shape为(H1, H2),rankSize为NPU卡数。

    • Atlas A2 训练系列产品/Atlas A2 推理系列产品:

      • 非量化场景:

        computeOut=x1@x2+biaspermutedOut=computeOut.view(BS,rankSize,H2/rankSize).permute(1,0,2)output=AlltoAll(permutedOut).view(rankSize∗BS,H2/rankSize)computeOut = x1 @ x2 + bias \\ permutedOut = computeOut.view(BS, rankSize, H2/rankSize).permute(1, 0, 2) \\ output = AlltoAll(permutedOut).view(rankSize*BS, H2/rankSize)

      • K-C量化场景:

        computeOut=(x1@x2)∗x1Scale∗x2Scale+biaspermutedOut=computeOut.view(BS,rankSize,H2/rankSize).permute(1,0,2)output=AlltoAll(permutedOut).view(rankSize∗BS,H2/rankSize)computeOut = (x1 @ x2) * x1Scale * x2Scale + bias \\ permutedOut = computeOut.view(BS, rankSize, H2 / rankSize).permute(1, 0, 2) \\ output = AlltoAll(permutedOut).view(rankSize * BS, H2 / rankSize)

    • Atlas A3 训练系列产品/Atlas A3 推理系列产品:

      • 非量化场景:

        computeOut=x1@x2+biaspermutedOut=computeOut.view(BS,rankSize,H2/rankSize).permute(1,0,2)output=AlltoAll(permutedOut).view(rankSize∗BS,H2/rankSize)computeOut = x1 @ x2 + bias \\ permutedOut = computeOut.view(BS, rankSize, H2/rankSize).permute(1, 0, 2) \\ output = AlltoAll(permutedOut).view(rankSize*BS, H2/rankSize)

    • Ascend 950PR/Ascend 950DT:

      • 非量化场景:

        computeOut=x1@x2+biaspermutedOut=computeOut.view(BS,rankSize,H2/rankSize).permute(1,0,2)output=AlltoAll(permutedOut).view(rankSize∗BS,H2/rankSize)computeOut = x1 @ x2 + bias \\ permutedOut = computeOut.view(BS, rankSize, H2/rankSize).permute(1, 0, 2) \\ output = AlltoAll(permutedOut).view(rankSize*BS, H2/rankSize)

      • K-C量化场景:

        computeOut=(x1@x2+bias)∗x1Scale∗x2ScalepermutedOut=computeOut.view(BS,rankSize,H2/rankSize).permute(1,0,2)output=AlltoAll(permutedOut).view(rankSize∗BS,H2/rankSize)computeOut = (x1 @ x2 + bias) * x1Scale * x2Scale \\ permutedOut = computeOut.view(BS, rankSize, H2 / rankSize).permute(1, 0, 2) \\ output = AlltoAll(permutedOut).view(rankSize * BS, H2 / rankSize)

      • mx量化场景:

        computeOut=∑0⌊kblockSize=32⌋(x1@x2∗(x1Scale∗x2Scale))+biaspermutedOut=computeOut.view(BS,rankSize,H2/rankSize).permute(1,0,2)output=AlltoAll(permutedOut).view(rankSize∗BS,H2/rankSize)computeOut = \sum_{0}^{\left \lfloor \frac{k}{blockSize=32} \right \rfloor} (x1 @ x2 * (x1Scale * x2Scale)) + bias \\ permutedOut = computeOut.view(BS, rankSize, H2 / rankSize).permute(1, 0, 2) \\ output = AlltoAll(permutedOut).view(rankSize * BS, H2 / rankSize)

参数说明​

参数名 输入/输出/属性 描述 数据类型 数据格式
x1 输入 MatMul左矩阵,即公式中的输入x1。 FLOAT16、BFLOAT16、FLOAT8_E4M3FN、FLOAT8_E5M2、FLOAT4_E2M1、INT8 ND
x2 输入 MatMul右矩阵,即公式中的输入x2。 FLOAT16、BFLOAT16、FLOAT8_E4M3FN、FLOAT8_E5M2、FLOAT4_E2M1、INT8 ND
bias 可选输入 可选输入,阵乘运算后累加的偏置,对应公式中的bias。 FLOAT16、BFLOAT16、FLOAT32 ND
x1_scale 可选输入 左矩阵的量化系数,对应公式中的x1Scale。 FLOAT32、FLOAT8_E8M0 ND
x2_scale 可选输入 右矩阵的量化系数,对应公式中的x2Scale。 FLOAT32、FLOAT8_E8M0 ND
comm_scale 可选输入 预留参数,低比特通信的量化系数。 - -
x1_offset 可选输入 预留参数,左矩阵的量化偏置。 - -
x2_offset 可选输入 预留参数,右矩阵的量化偏置。 - -
y 输出 计算+通信的结果,即公式中的输出output。 FLOAT16、BFLOAT16、FLOAT32 ND
group 必选属性 Host侧标识列组的字符串,即通信域名称,通过Hccl接口HcclGetCommName获取commName作为该参数,字符串长度要求(0, 128)。 STRING -
world_size 必选属性 使用的npu卡数,公式中的rankSize。 INT -
all2all_axes 可选属性 AlltoAll和Permute数据交换的方向,支持配置空或者[-1, -2],传入空时默认按[-1, -2]处理,表示将输入由(BS, H2)转为(BS*rankSize, H2/rankSize)。 aclIntArray*(元素类型INT64) -
x1_quant_mode 可选属性 左矩阵的量化方式,按照实际场景配置。 INT -
x2_quant_mode 可选属性 右矩阵的量化方式,按照实际场景配置。 INT -
comm_quant_mode 可选属性 低比特通信的量化方式,预留参数,当前仅支持配置为0,表示不量化。 INT -
comm_quant_dtype 可选属性 低比特通信的量化类型,预留参数,当前仅支持配置为-1,表示ACL_DT_UNDEFINED。 INT -
transpose_x1 可选属性 标识左矩阵是否转置过,暂不支持配置为True。 bool -
transpose_x2 可选属性 标识右矩阵是否转置过,配置为True时右矩阵Shape为(H2,H1)。 bool -
group_size 可选属性 用于Matmul计算三个方向上的量化分组大小,仅在scale输入都是2维及以上数据时取值有效,其他场景默认传入0即可。 INT -

x1QuantMode、x2QuantMode、commQuantMode的枚举值与量化模式关系如下:

  • 0: 不量化
  • 1: pertensor
  • 2: perchannel
  • 3: pertoken
  • 4: pergroup
  • 5: perblock
  • 6: mx量化
  • 7: pertoken动态量化

约束说明

  • 默认支持确定性计算。
  • NPU卡数(world_size),根据设备型号有不同限制:
    • Atlas A2 训练系列产品/Atlas A2 推理系列产品:支持2、4、8卡。
    • Atlas A3 训练系列产品/Atlas A3 推理系列产品:支持2、4、8、16卡。
    • Ascend 950PR/Ascend 950DT:支持2、4、8、16卡。
  • 空tensor和非连续tensor的支持度根据不同设备型号有不同的限制:
    • Atlas A2 训练系列产品/Atlas A2 推理系列产品:不支持任何空tensor;不支持任何非连续tensor。
    • Atlas A3 训练系列产品/Atlas A3 推理系列产品、Ascend 950PR/Ascend 950DT:仅支持非量化场景下输入x1的第一维度(BS)为0的空tensor,其它空tensor均不支持;仅支持输入x2的转置非连续tensor,其它非连续tensor均不支持。
  • 输入x1必须是2维,其shape为(BS, H1),BS*rankSize和H2的值不得超过2147483647(INT32_MAX)。
  • 输入x2必须是2维,其shape为(H1, H2),H2必须整除NPU卡数,H1范围仅支持[1,65535],H2的值不超过2147483647(INT32_MAX)。
  • bias若非空,其维度必须为1维,shape为(H2)。
  • x1_scale若非空,在mx量化场景时,其维度为3维,shape为(BS, ceil(H1/64), 2);其它场景中其维度为1维,shape为(BS)。
  • x2_scale若非空,在mx量化场景时,其维度为3维,shape为(H2, ceil(H1/64), 2);其它场景中其维度为1维,shape为(H2)。
  • all2all_axes为1维数组,shape必须为(2)。
  • 目前支持的量化模式,根据设备型号有不同限制:
    • Atlas A2 训练系列产品/Atlas A2 推理系列产品:支持K-C量化模式,x1QuantMode=3,x2QuantMode=2。
    • Atlas A3 训练系列产品/Atlas A3 推理系列产品:目前不支持量化场景。
    • Ascend 950PR/Ascend 950DT:支持K-C量化模式,x1QuantMode=3,x2QuantMode=2;mx量化模式,x1QuantMode=6,x2QuantMode=6。
  • 非量化场景x1、x2计算输入的数据类型要和output计算输出的数据类型一致,传入的x1、x2与output均不为空指针。
  • 量化场景传入的x1、x2、x1Scale、x2Scale与output均不为空指针,且
    • Atlas A2 训练系列产品/Atlas A2 推理系列产品:bias不支持传入空指针。
  • x1、x2和bias计算输入的数据类型根据不同设备型号有不同的限制:
    • Atlas A2 训练系列产品/Atlas A2 推理系列产品:
      • 非量化场景下,x1/x2计算输入的数据类型为FLOAT16时,bias计算输入的数据类型支持FLOAT16;x1/x2计算输入的数据类型为BFLOAT16时,bias计算输入的数据类型支持FLOAT32。
      • 量化场景下,支持K-C量化模式后加bias,x1、x2计算输入的数据类型必须为INT8;output计算输出的数据类型为BFLOAT16时,bias的数据类型为FLOAT或BFLOAT16;output的数据类型为FLOAT16时,bias的数据类型为FLOAT16。
    • Atlas A3 训练系列产品/Atlas A3 推理系列产品:
      • 非量化场景下,output计算输出的数据类型为FLOAT16时,bias计算输入的数据类型支持FLOAT16;output计算输出的数据类型为BFLOAT16时,bias计算输入的数据类型支持FLOAT32。
      • A3目前不支持量化场景。
    • Ascend 950PR/Ascend 950DT:
      • 非量化场景下,x1/x2计算输入的数据类型为FLOAT16时,bias计算输入的数据类型支持FLOAT16和FLOAT32;x1/x2计算输入的数据类型为BFLOAT16时,bias计算输入的数据类型支持BFLOAT16和FLOAT32。
      • 量化场景下,支持K-C量化模式和mx量化模式,x1、x2计算输入的数据类型为FLOAT8_E4M3FN、FLOAT8_E5M2、FLOAT4_E2M1,bias的数据类型为FLOAT32或者bias为空,具体类型组合详见量化aclnn约束说明
      • mx量化模式下,当x1和x2的数据类型为FLOAT4_E2M1时,两者的数据类型必须一致。
  • 通算融合算子不支持并发调用,不同的通算融合算子也不支持并发调用。
  • 不支持跨超节点通信,只支持超节点内。
  • 通信引擎约束:
    • Atlas A2 训练系列产品/Atlas A2 推理系列产品:支持MTE通信。
    • Atlas A3 训练系列产品/Atlas A3 推理系列产品:支持AICPU通信。
    • Ascend 950PR/Ascend 950DT:支持CCU通信。

调用说明

调用方式 样例代码 说明
aclnn接口 test_aclnn_matmul_allto_all.cpp 通过aclnnMatMulAlltoAll接口方式调用非量化场景的MatMulAlltoAll算子。
aclnn接口 test_aclnn_quant_matmul_allto_all.cpp 通过aclnnQuantMatMulAlltoAll接口方式调用量化场景的MatMulAlltoAll算子。