- CANN
- Ascend
- 人工智能
- 任务调度
【免费下载链接】runtime
本项目提供CANN运行时组件和维测功能组件。
导读
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.h | X-Macro 元数据表RUNTIME_ERROR_CODE_TABLE | GetParamNames()/PrintErrMsgToLog(),实现于 rt_log.cc |
1.1 error_code.json:外部错误码元数据
json 文件以error_info_list数组组织每条错误码,核心字段包括ErrCode、ErrMessage、Arglist与suggestion。从 ParseJsonFormatString 的实现可以看到,程序运行时读取ErrCode、ErrMessage、Arglist(按逗号切分得到参数名列表),以及suggestion下的Possible Cause与Solution,并注册进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 模板本身是否合规,逐条核对:
- 首字母大写:模板中第一个英文字母应大写(占位符
%s除外,因为其内容运行时才确定); - 末尾句号:完整句子末尾应有句号。唯一例外是:最后
%s是独立的extend_info且模板设计上无句号,属于有意的设计选择; %s数量与 Arglist 匹配:模板中%s占位符数量必须等于 Arglist 参数数量,多一个或少一个都会在运行时校验或替换时出错;- 禁用
[%s]方括号格式:模板中字符串变量禁止写成[%s],应直接使用%s或融入句式。方括号会让日志文本显得生硬且难以阅读; - 对象 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)是外部上报路径中面向用户的关键文案,逐条核对:
- 缺少 suggestion:json 中必须提供
suggestion字段; - 不使用换行符
\n:多条信息用空格分隔(观察 error_code.json 中多处使用1. xxx 2. xxx双空格分隔的写法),确有特殊情况再特殊处理; - 编号后缺空格:
1./2.编号后应有空格; - 统一使用 N/A:
NA必须写为N/A(源码 error_manager.cc 在拼装输出时会显式跳过值为N/A的 possible_cause 与 solution,因此必须统一拼写才能正确生效); - 首字母大写:suggestion 文本首字母大写;
- 末尾句号:完整句子末尾加句号;
N/A不需要; - 语法错误:检查主谓一致、时态、介词与拼写。
五、参数数量校验(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:
- 最底层宏
RT_LOG_OUTER_MSG_IMPL:不自动添加任何参数,调用者传入什么就是什么; 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__;- 专用宏:为简化使用通常自动处理通用参数,有效参数需按实际展开链计算。以 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_DESC、ACL_REQUIRES_POSITIVE_REPORT_WITH_FUNC_DESC):使用调用者传入的funcDesc字符串,便于在跨层调用时给出语义化描述;- 手动调用
ReportInputError:func值由调用者自行传入,非接口层代码应传入语义化描述而非__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-size、non-zero、divide-by-zero、zero-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.h | X-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.h | ErrorCode枚举 +GetParamNames/PrintErrMsgToLog/RtFmtMsg声明 |
| src/runtime/core/inc/common/error_message_manage.hpp | COND_*封装宏 + 专用宏(EE1003/EE1010/EE1017/EE1013 等) |
| src/runtime/core/src/common/rt_log.cc | GetParamNames+PrintErrMsgToLog+DispatchErrMsg实现 |
| src/dfx/error_manager/error_manager.cc | ErrorManager实现:json 解析、ReportErrMessage、ATCReportErrMessage、错误消息拼装输出 |
| src/dfx/error_manager/error_manager.h | ErrorManager类声明与REPORT_INPUT_ERROR/REPORT_INNER_ERROR宏 |
九、结语
错误码检视不是"文案润色",而是直接决定运行时打屏与 ATC 上报两条路径可靠性的工程质量关卡。以 error_code_meta.h 与 error_code.json 的双源一致性为底线,以GetParamNames的参数数量为刚性约束,再叠加文本与 suggestion 的规范性要求,即可系统性地规避大多数错误码质量问题。对每个改动提交,都建议对照本文清单逐项过检,让错误码从"能上报"走向"报得准、看得懂、可定位"。
- CANN
- Ascend
- 人工智能
- 任务调度
【免费下载链接】runtime
本项目提供CANN运行时组件和维测功能组件。
相关推荐
CANN Runtime 错误消息(ErrMsg)开发规范全指南:错误码、上报宏与检视流程
CANN Runtime 错误消息(ErrMsg)开发规范全指南:错误码、上报宏与检视流程 导读 本文基于 CANN/runtime 仓库中 error_mes
CANNAscend人工智能任务调度CANN Runtime 错误信息(ErrMsg)整改全流程指南:从整改建议模板到错误码与宏规范
CANN Runtime 错误信息(ErrMsg)整改全流程指南:从整改建议模板到错误码与宏规范 导读 本文面向 CANN Runtime 与 ACL 的错误信
CANNAscend人工智能任务调度CANN Runtime ErrMsg 上报宏使用规范:错误码上报宏的分类、参数风格与选型指南
CANN Runtime ErrMsg 上报宏使用规范:错误码上报宏的分类、参数风格与选型指南 本篇技术指南以 CANN/runtime 开源仓库中 docs/
CANNAscend人工智能任务调度
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考