CANN Runtime 错误码检视清单深度实践:ErrMsg 宏合规与双源一致性保障
2026/9/20 12:01:50 网站建设 项目流程
  • CANN
  • Ascend
  • 人工智能
  • 任务调度

【免费下载链接】runtime

本项目提供CANN运行时组件和维测功能组件。

项目地址:https://gitcode.com/cann/runtime
点击查看免费下载

导读

CANN Runtime 的错误码体系采用"外部上报(ATC/对外接口)与运行时打屏(日志)"双通道模型,任何新增或修改错误码的改动都必须同时维护 error_code.json 与 error_code_meta.h 两个数据源,并确保 ErrMsg 宏调用参数与模板严格匹配。本文以仓库内 Error Message 检视清单 为骨架,结合源码实现逐条拆解检视项,帮助开发者快速完成合规审查,避免出现 ATC 上报与打屏消息不一致、参数数量校验失败、日志文本不合规等典型问题。

一、认识错误码双源架构

Runtime 的外部错误码(EE/EH/EZ/WE 系列)元数据同时存在于两个文件中,二者互为镜像,缺一不可:

文件用途消费方
src/dfx/error_manager/error_code.json外部错误码元数据(ErrMessage 模板、Arglist、suggestion)ErrorManager::ATCReportErrMessage(ATC / 外部上报路径),定义于 error_manager.h
src/runtime/core/inc/common/error_code_meta.hX-Macro 元数据表RUNTIME_ERROR_CODE_TABLEGetParamNames()/PrintErrMsgToLog(),实现于 rt_log.cc

1.1 error_code.json:外部错误码元数据

json 文件以error_info_list数组组织每条错误码,核心字段包括ErrCodeErrMessageArglistsuggestion。从 ParseJsonFormatString 的实现可以看到,程序运行时读取ErrCodeErrMessageArglist(按逗号切分得到参数名列表),以及suggestion下的Possible CauseSolution,并注册进error_map_ReportErrMessage会按arg_list顺序逐个将%s替换为调用方传入的参数值;若参数名不在 map 中,或模板中找不到%s,会直接报错返回(error_manager.cc)。

一个典型条目如下:

{ "errClass": "Runtime Errors", "errTitle": "Invalid_Argument", "ErrCode": "EE1011", "ErrMessage": "%s failed. Value %s for parameter %s is invalid. Reason: %s.", "Arglist": "func,value,param,reason", "suggestion": { "Possible Cause": "The parameter value is out of the valid range.", "Solution": "Adjust the parameter according to the documentation." } }

1.2 error_code_meta.h:X-Macro 元数据表

error_code_meta.h 中的RUNTIME_ERROR_CODE_TABLE是 X-Macro 表,每行格式为:

X(ErrorCode枚举名, "字符串名称", (参数名列表), "完整消息模板", 日志级别)

例如 EE1003 一行定义:

X(EE1003, "EE1003", ("func", "value", "param", "expect"), "%s failed because value %s for parameter %s is invalid. " "Expected value: %s. ErrorCode=EE1003.\n", DLOG_ERROR)

模板必须包含错误码后缀(如ErrorCode=EE1003.\n),且与PrintErrMsgToLog最终打屏输出完全一致。rt_log.h中对应的ErrorCode枚举(rt_log.h)与表内容一一对应。GetParamNames通过 X-Macro 展开自动生成switch,返回每个错误码的参数名向量(rt_log.cc)。

二、双源同步校验(核心检视项)

2.1 两处必须同时更新

新增或修改错误码时,必须同时更新 error_code.json 与 error_code_meta.h 两处并保持一致。只改一处会引发两类典型故障:

  • ATC 上报与运行时打屏消息不一致:json 与 X-Macro 表模板不同,同一错误码在不同消费路径输出不同文本,增加用户排查成本;
  • 参数数量校验失败:两处 Arglist 不一致时,PrintErrMsgToLog的参数数量校验会直接失败(详见第五节)。

2.2 一致性强制要求

  • ErrMessage 模板必须完全一致:含标点、空格、大小写都要逐字对齐(json 中模板不含ErrorCode=EE1003.\n这类日志专用后缀,对齐时以 X-Macro 表中的完整模板为准、剔除日志后缀后比对);
  • Arglist 参数名与参数数量必须完全一致:json 的Arglist是逗号分隔的字符串,X-Macro 表是括号包裹的字符串字面量列表,二者顺序也必须一致。

三、ErrMessage 文本校验

检视 ErrMessage 模板本身是否合规,逐条核对:

  1. 首字母大写:模板中第一个英文字母应大写(占位符%s除外,因为其内容运行时才确定);
  2. 末尾句号:完整句子末尾应有句号。唯一例外是:最后%s是独立的extend_info且模板设计上无句号,属于有意的设计选择;
  3. %s数量与 Arglist 匹配:模板中%s占位符数量必须等于 Arglist 参数数量,多一个或少一个都会在运行时校验或替换时出错;
  4. 禁用[%s]方括号格式:模板中字符串变量禁止写成[%s],应直接使用%s或融入句式。方括号会让日志文本显得生硬且难以阅读;
  5. 对象 ID 缺失:模板涉及 stream/model/event/notify 等对象时,必须打印其 ID 值。从源码可见,EE1010 的归属关系校验宏(如 error_message_manage.hpp)都会通过RtFmtMsg构造stream_id=%u/model_id=%u/label_id=%u等带 ID 的extendInfo,这正是"对象 ID 必须打印"规范的实现范式。

四、suggestion 校验

suggestion(Possible Cause/Solution)是外部上报路径中面向用户的关键文案,逐条核对:

  1. 缺少 suggestion:json 中必须提供suggestion字段;
  2. 不使用换行符\n:多条信息用空格分隔(观察 error_code.json 中多处使用1. xxx 2. xxx双空格分隔的写法),确有特殊情况再特殊处理;
  3. 编号后缺空格1./2.编号后应有空格;
  4. 统一使用 N/ANA必须写为N/A(源码 error_manager.cc 在拼装输出时会显式跳过值为N/A的 possible_cause 与 solution,因此必须统一拼写才能正确生效);
  5. 首字母大写:suggestion 文本首字母大写;
  6. 末尾句号:完整句子末尾加句号;N/A不需要;
  7. 语法错误:检查主谓一致、时态、介词与拼写。

五、参数数量校验(EE/EH 宏层)

PrintErrMsgToLog在打屏前会执行严格的参数数量校验(rt_log.cc):

const size_t expectedSize = GetParamNames(errCode).size(); if (values.size() != expectedSize) { RecordLog(DLOG_WARN, file, line, func, "Parameter count mismatch for error code %d. Expected %zu, got %zu.\n", ...); return; // 直接返回,不执行打屏 }

参数数量不匹配时,ErrMsg 打屏上报会失败,只打印一条警告日志。因此"有效参数数量 ==GetParamNames(ErrorCode)的大小"是铁律。

5.1 EE 层宏参数计算规则

EE 系列(Runtime 层)通过RT_LOG_OUTER_MSG_*宏链上报。宏定义位于 base.hpp:

  1. 最底层宏RT_LOG_OUTER_MSG_IMPL:不自动添加任何参数,调用者传入什么就是什么;
  2. RT_LOG_OUTER_MSG_WITH_FUNC:自动前置__func__作为第一个参数,即有效参数 = 1 + len(args),调用时切勿手动重复传__func__。其定义RT_LOG_OUTER_MSG_WITH_FUNC(error_code, ...) RT_LOG_OUTER_MSG_IMPL((error_code), __func__, ##__VA_ARGS__)清晰说明了这一点。RT_LOG_OUTER_MSG_WITH_FUNC_DESC及其封装宏(如RT_LOG_OUTER_MSG_INVALID_PARAM_WITH_DESC)行为类似,但自动添加的是调用者传入的funcDesc字符串而非__func__
  3. 专用宏:为简化使用通常自动处理通用参数,有效参数需按实际展开链计算。以 EE1003 专用的RT_LOG_OUTER_MSG_INVALID_PARAM(parm, expect)为例:
RT_LOG_OUTER_MSG_INVALID_PARAM(parm, expect) → RT_LOG_OUTER_MSG_WITH_FUNC(EE1003, (parm), #parm, expect) // 自动加 __func__ → RT_LOG_OUTER_MSG_IMPL(EE1003, __func__, (parm), #parm, expect)

展开后有效参数 = 3 + len(args)(__func__(parm)#parm三个固定参数 + 可变参数)。EE1003 的 Arglist 为func,value,param,expect共 4 个参数,因此可变参数应为 1 个(即期望值expect)。RT_LOG_OUTER_MSG_INVALID_PARAM_WITH_DESC(funcDesc, parm, expect)展开链相同,仅将__func__替换为funcDesc

5.2 EH 层(ACL 层)宏说明

EH 系列错误码(ACL 层)使用acl::AclErrorLogManager::ReportInputError上报,通过 key-value 字符串向量传参,不走RT_LOG_OUTER_MSG_*宏链。参数数量校验规则相同:传入的 value 数量必须等于 Arglist 参数数量

ACL 层宏的func参数来源分三种情况:

  • 无后缀宏(如ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT):自动通过GetFuncNameWithoutImplSuffix(__func__)获取函数名,并去除Impl后缀;
  • _WITH_FUNC_DESC/_AND_FUNC_DESC变体(如ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT_AND_FUNC_DESCACL_REQUIRES_POSITIVE_REPORT_WITH_FUNC_DESC):使用调用者传入的funcDesc字符串,便于在跨层调用时给出语义化描述;
  • 手动调用ReportInputErrorfunc值由调用者自行传入,非接口层代码应传入语义化描述而非__func__,避免日志中出现无意义的内部函数名。

六、参数值校验

6.1 避免 std::string 拼接,使用 RtFmtMsg

参数值应避免使用std::string拼接方式传参——拼接会创建临时变量,导致 so 体积变大。建议使用RtFmtMsg(定义于 rt_log.h),以格式化字符串方式构造参数后再传入宏。它内部使用vsnprintf_truncated_s保证截断安全,且固定缓冲上限为RT_MAX_LOG_BUF_SIZE = 896字节(slog 单条总长 1024 字节,头部占 128 字节)。例如 error_message_manage.hpp 中:

std::string extendInfo = RtFmtMsg("stream_id=%u, stream_ctx=%p, cur_ctx=%p", (stm)->Id_(), (stm)->Context_(), (curCtx)); RT_LOG_OUTER_MSG_IMPL(ErrorCode::EE1010, __func__, "stream", extendInfo);

6.2 末尾句号的取舍

通过结构化参数宏传入外部错误码时,参数是否需要末尾句号取决于 ErrMessage 模板:

  • 模板中%s之后有句号→ 传入参数不加句号(避免出现双句号..);
  • 模板中%s之后没有句号,且参数是完整英文句子 →应加句号

检视时必须同时查看模板与调用点,逐参数确认。

七、常见错误盘点

7.1 WITH_FUNC 与手动func重复

WITH_FUNC系列宏已自动前置__func__,再手动传入会导致参数多一个:

// ✗ WITH_FUNC 自动加 __func__,手动再传导致重复 → 参数=5,EE1011 期望 4 RT_LOG_OUTER_MSG_WITH_FUNC(ErrorCode::EE1011, __func__, ver, "ver", "msg"); // ✓ 只传可变参数 → 参数=1+3=4 RT_LOG_OUTER_MSG_WITH_FUNC(ErrorCode::EE1011, ver, "ver", "msg");

7.2 NA vs N/A

"suggestion": { "Solution": "NA" } // ✗ 应使用 "N/A" "suggestion": { "Solution": "N/A" } // ✓

7.3 句号重复

// ✗ EE1011 的 ErrMessage 模板最后一个 %s 后有句号,reason 参数再加句号导致重复 COND_RETURN_AND_MSG_OUTER(!trueStream->IsModelStream(), RT_ERROR_STREAM_MODEL, ErrorCode::EE1011, __func__, 0, "trueStream->modelNum", "The stream is not bound to a model."); // ✓ reason 参数不加句号 COND_RETURN_AND_MSG_OUTER(!trueStream->IsModelStream(), RT_ERROR_STREAM_MODEL, ErrorCode::EE1011, __func__, 0, "trueStream->modelNum", "The stream is not bound to a model");

注意:COND_RETURN_AND_MSG_OUTER展开为RT_LOG_OUTER_MSG_IMPL(不自动添加__func__),因此此处手动传入__func__是正确的,与 7.1 的 WITH_FUNC 重复问题不同。该宏定义见 error_message_manage.hpp。

7.4 日志中数值词汇未统一

日志和错误信息字符串中,独立单词zero应替换为0;连字符复合词(zero-sizenon-zerodivide-by-zerozero-copy)和技术术语(zero copy)不替换:

// ✗ count is zero, greater than zero // ✓ count is 0, greater than 0 // ✓ zero-size memcpy(连字符复合词不替换) // ✓ zero copy task(技术术语不替换)

八、检视流程建议与源文件索引

建议的检视流程:先在 json 与 X-Macro 表中逐字段比对双源一致性(模板、Arglist、顺序),再分别做文本质量校验(ErrMessage 与 suggestion),最后对每个调用点手算有效参数数量并与GetParamNames期望值核对,重点排查WITH_FUNC重复传__func__、句号重复、%s与 Arglist 不匹配三类高频问题。

源文件索引

文件作用
src/runtime/core/inc/common/error_code_meta.hX-Macro 错误码元数据表RUNTIME_ERROR_CODE_TABLE(GetParamNames / PrintErrMsgToLog 数据源)
src/dfx/error_manager/error_code.json外部错误码元数据(ATCReportErrMessage 数据源)
src/runtime/core/inc/base.hpp核心宏定义 +ErrorCodeProcess模板函数
src/runtime/core/inc/common/rt_log.hErrorCode枚举 +GetParamNames/PrintErrMsgToLog/RtFmtMsg声明
src/runtime/core/inc/common/error_message_manage.hppCOND_*封装宏 + 专用宏(EE1003/EE1010/EE1017/EE1013 等)
src/runtime/core/src/common/rt_log.ccGetParamNames+PrintErrMsgToLog+DispatchErrMsg实现
src/dfx/error_manager/error_manager.ccErrorManager实现:json 解析、ReportErrMessageATCReportErrMessage、错误消息拼装输出
src/dfx/error_manager/error_manager.hErrorManager类声明与REPORT_INPUT_ERROR/REPORT_INNER_ERROR

九、结语

错误码检视不是"文案润色",而是直接决定运行时打屏与 ATC 上报两条路径可靠性的工程质量关卡。以 error_code_meta.h 与 error_code.json 的双源一致性为底线,以GetParamNames的参数数量为刚性约束,再叠加文本与 suggestion 的规范性要求,即可系统性地规避大多数错误码质量问题。对每个改动提交,都建议对照本文清单逐项过检,让错误码从"能上报"走向"报得准、看得懂、可定位"。

  • CANN
  • Ascend
  • 人工智能
  • 任务调度

【免费下载链接】runtime

本项目提供CANN运行时组件和维测功能组件。

项目地址:https://gitcode.com/cann/runtime
点击查看免费下载

相关推荐

上一篇:gh0stzk dotfiles中的ZSH配置优化:告别插件臃肿的高效终端环境
下一篇:悟空引擎核心架构解析:揭秘高效索引与搜索的并发设计

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询