- CANN
- Ascend
- 人工智能
- 任务调度
【免费下载链接】runtime
本项目提供CANN运行时组件和维测功能组件。
CANN Runtime 的错误上报接口(Error Reporting APIs)是定制开发 CANN 组件与自定义算子场景下向统一错误管理框架注册、上报错误信息的标准入口。本文围绕liberror_manager提供的四个核心接口(ReportInnerErrMsg、ReportPredefinedErrMsg、ReportUserDefinedErrMsg、RegisterFormatErrorMessage)展开,讲解其函数原型、参数语义、错误码编码规则、配套宏以及底层实现原理,并给出可直接落地的 JSON 注册与调用示例。读完本文,你将能够为自定义算子或定制组件设计符合 CANN 规范的错误码,并通过官方推荐的宏在进程加载期或运行期完成错误注册与上报。
使用须知:接口定位与依赖文件
该部分接口仅在定制开发 CANN 组件及自定义算子开发场景下使用,用于注册和上报各类预定义与自定义的错误信息。本文介绍这部分接口的功能、参数等,仅为了便于您了解这部分接口在 CANN 开放代码中的作用,进而更好地使用或修改 CANN 开放代码。
接口涉及的头文件与库文件路径如下(${INSTALL_DIR}请替换为 CANN 软件安装后文件存储路径,以 root 用户安装为例,默认路径为/usr/local/Ascend/cann):
- 头文件所在路径:
${INSTALL_DIR}/include/base/err_msg.h,该头文件中的接口命名空间为ge(底层实现在error_message命名空间,ge空间通过using声明复用)。 - 依赖的库文件所在路径:
${INSTALL_DIR}/lib64/liberror_manager.so。
在开源仓库中,该头文件的源码位于 include/dfx/base/err_msg.h,库的完整实现位于 src/dfx/error_manager/error_manager.cc,构建脚本 src/dfx/error_manager/CMakeLists.txt 展示了liberror_manager.so(以及静态库liberror_manager.a)的编译与安装方式。需要说明的是,错误上报接口的声明全部带有WEAK_SYMBOL弱符号属性,并同时导出了GE_FUNC_HOST_VISIBILITY与GE_FUNC_DEV_VISIBILITY可见性,因此无论链接到正式实现库还是 src/dfx/error_manager/stub/gen_stubapi.py 生成的 stub 库,调用方都能正常编译链接。
错误码编码规则:6 位字符的组成
在深入各接口前,先统一说明 CANN 错误码的编码约定。错误码以6 位字符形式体现,例如E19999、E10001、EU0001,其结构为:
| 位置 | 含义 | 取值 |
|---|---|---|
| 第 1 位 | 级别 | E(错误)、W(告警)、I(提示) |
| 第 2 位 | 模块标识 | 模块代号 |
| 后 4 位 | 错误码号 | 0000~8999 为用户类错误;9000~9999 为内部错误码 |
从源码 error_manager.cc 可印证该规则的落地实现:
IsValidErrorCode()强制校验错误码长度为 6 位(kErrorCodeValidLength = 6U);IsInnerErrorCode()判断后 4 位是否等于9999(kInterErrorCodePrefix = "9999"),或将后 4 位等于8888(kParamCheckErrorSuffix = "8888",参数校验类)的码也视为内部错误码;IsUserDefinedErrorCode()则要求错误码既不是内部错误码,也不在预定义错误码表中,满足条件即为合法的用户自定义码。
在error_message命名空间中,W 级(告警)错误会被写入独立的 warning 容器,E 级(错误)写入 error 容器,后续GetErrorMessage()/GetWarningMessage()会分别汇聚输出。
ReportInnerErrMsg:上报 CANN 内部错误
函数原型
int32_t ReportInnerErrMsg(const char_t *file_name, const char_t *func, uint32_t line, const char *error_code, const char_t *format, ...)函数功能
用于上报CANN 预定义好的内部错误信息,同时也会自动附带调用处的文件名、函数名以及行号,便于问题定位。内部错误码的后 4 位落在 9000~9999 区间,例如E19999。
该接口带有FORMAT_PRINTF(5, 6)编译属性(见 include/dfx/base/err_msg.h),编译器可对format与可变参数进行 printf 风格的类型/个数检查,减少格式化串写错的风险。
1024 字节长度限制
当用户提供的格式化字符串**长度超过 1024(包括末尾的\0)**时,接口返回错误码-1表示失败。该限制来源于实现中的LIMIT_PER_MESSAGE = 1024U(定义于 error_manager.h)。文档给出的判断示例如下:
- 若格式化字符串为
"Error:%s",传入的字符串长度为 1000,加上"Error:"与末尾'\0'后总长度为 1007,未超限,接口调用成功; - 若传入的字符串长度为 1020,加上
"Error:"与末尾'\0'后总长度变为 1027,超过 1024,接口调用失败并返回-1。
配套宏 REPORT_INNER_ERR_MSG
为简化调用,接口提供了封装宏REPORT_INNER_ERR_MSG,自动填充__FILE__、__FUNCTION__、__LINE__:
#define REPORT_INNER_ERR_MSG(error_code, format, ...) \ (void)ge::ReportInnerErrMsg(__FILE__, __FUNCTION__, __LINE__, (error_code), (format), ##__VA_ARGS__)实际宏定义见 include/dfx/base/err_msg.h,其中##__VA_ARGS__支持可变参数为空的情况。作为参考,仓库内部 src/acl/common/log_inner.cpp 即使用REPORT_INNER_ERR_MSG("EH9999", "%s", errorMsgStr)的方式上报 ACL 内部错误。
参数说明
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| file_name | 输入 | 文件名,表示用户在哪个文件中调用ReportInnerErrMsg接口,固定配置为__FILE__。 |
| func | 输入 | 函数名,表示用户在哪个函数中调用ReportInnerErrMsg接口,固定配置为__FUNCTION__。 |
| line | 输入 | 行号,表示用户在哪一行中调用ReportInnerErrMsg接口,固定配置为__LINE__。 |
| error_code | 输入 | CANN 预定义好的内部错误。错误码以 6 位字符形式体现,例如E19999;第 1 位表示级别(E/W/I);第 2 位表示模块;后 4 位中 9000~9999 为内部错误码。 |
| format | 输入 | 错误信息。在调用格式化函数时,format 中参数的类型、个数必须与实际参数类型、个数保持一致。 |
| ... | 输入 | format 中的可变参数,根据错误信息添加。 |
返回值
- 0:成功。
- -1:失败。
底层实现原理
从 error_manager.cc 的实现可以看到完整链路:ReportInnerErrMsg内部使用vsprintf_s按LIMIT_PER_MESSAGE长度对format与可变参数做安全格式化,随后通过sprintf_s在消息尾部追加[FUNC:%s][FILE:%s][LINE:%u]调用点信息(文件路径会经TrimPath只保留文件名部分),最后交给ErrorManager::ReportInterErrMessage完成内部错误码校验、work_stream_id 归属与去重入队。若格式化失败或错误码非内部错误码,均返回-1并记录 GELOGE 日志。
ReportPredefinedErrMsg:上报预定义用户类错误
函数原型
接口提供两个重载版本:
不带参数的错误码信息:
int32_t ReportPredefinedErrMsg(const char *error_code)带参数的错误码信息:
int32_t ReportPredefinedErrMsg(const char *error_code, const std::vector<const char *> &key, const std::vector<const char *> &value)
函数功能
用于上报CANN 预定义好的用户类错误信息。用户类错误码的后 4 位落在 0000~8999 区间,例如E10001。CANN 预定义好的用户类错误可参见仓库内的错误码参考文档(如 docs/zh/error_code_ref/README.md 及其下 ACL/FE/Profiling/RTS/TEfusion 等错误码章节)。
配套宏 REPORT_PREDEFINED_ERR_MSG
针对两个重载,提供了可变参数分派的封装宏REPORT_PREDEFINED_ERR_MSG,根据实参个数自动选择 1 参数或 3 参数版本:
#define REPORT_PREDEFINED_ERRMSG_CHOOSER(_1, _2, _3, NAME, ...) NAME #define REPORT_PREDEFINED_ERRMSG_1PARAMS(error_code) error_message::ReportPredefinedErrMsg(error_code) #define REPORT_PREDEFINED_ERRMSG_3PARAMS(error_code, key, value) \ error_message::ReportPredefinedErrMsg((error_code), (key), (value)) #define REPORT_PREDEFINED_ERR_MSG(...) \ REPORT_PREDEFINED_ERRMSG_CHOOSER(__VA_ARGS__, REPORT_PREDEFINED_ERRMSG_3PARAMS, , \ REPORT_PREDEFINED_ERRMSG_1PARAMS)(__VA_ARGS__)参数说明
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| error_code | 输入 | 错误码以 6 位字符形式体现,例如E10001。第 1 位表示级别(E/W/I);第 2 位表示模块;后 4 位中 0000~8999 为用户类错误。 |
| key | 输入 | 预定义的参数。每个错误码支持的参数可查看 error_code.json 文件中的Arglist字段(仓库内置的错误码清单见 src/dfx/error_manager/error_code.json)。 |
| value | 输入 | 参数 key 中参数对应的实际值。这些实际值会替换 error_code.json 文件中ErrMessage字段的占位符,得到最终的错误码信息。 |
返回值
- 0:成功。
- -1:失败。
底层实现原理
带参数版本在实现(见 error_manager.cc 的ReportPredefinedErrMsg)中会先校验key与value两个 vector 的长度是否相等,不等则直接返回-1;随后将二者组装为std::map<std::string, std::string> args_map,交给ErrorManager::ReportErrMessage处理。该函数从内存中解析好的error_map_中按error_code查找对应配置(error_title、error_message、possible_cause、solution、arg_list),并逐个用实际值替换ErrMessage中的%s占位符(按arg_list顺序替换,每个参数替换一个%s,kLength = 2即%s的长度)。若错误码未注册,返回-1并记录告警日志;若arg_list中某参数在 map 中缺失或ErrMessage中找不到%s占位符,同样返回-1。最终错误条目中还会携带suggestion中的 Possible Cause 与 Solution,供上层组装完整错误提示。
ReportUserDefinedErrMsg:上报自定义错误码
函数原型
int32_t ReportUserDefinedErrMsg(const char *error_code, const char *format, ...)函数功能
用于开发者上报自定义错误码,推荐使用 U 码段,例如EU0001。该接口同样带有FORMAT_PRINTF(2, 3)编译属性。
推荐形式为 6 位字符;对于空格、非 6 位字符、以 8888 或 9999 结尾等不推荐的形式,函数内部会以错误码EU0000进行上报。该兜底逻辑在 error_manager.cc 的ReportErrMsgWithoutTpl中实现:先调用IsUserDefinedErrorCode校验,若错误码不满足"非内部错误码、非预定义错误码的 6 位字符串"条件,则打印告警日志suggest using the recommended U segment. The error code EU0000 is reported!,并将最终错误码强制改写为EU0000。
与ReportInnerErrMsg相同,该接口也存在1024 字节长度限制:格式化结果(含末尾\0)超过 1024 时返回-1。判断方法与上文示例完全一致。
参数说明
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| error_code | 输入 | 用户自定义的错误码。 |
| format | 输入 | 错误码对应的错误信息。 |
| ... | 输入 | format 中的可变参数,表示 format 中占位符对应的变量值。 |
返回值
- 0:成功。
- -1:失败。
底层实现原理
实现中ReportUserDefinedErrMsg同样使用vsprintf_s以LIMIT_PER_MESSAGE为上限完成安全格式化(失败返回-1),随后调用ErrorManager::ReportErrMsgWithoutTpl。与预定义错误不同,自定义错误不经过错误模板表,直接以用户提供的最终文本作为error_message入队,因此该接口适合上报无法用统一模板描述的场景。
RegisterFormatErrorMessage:注册自定义错误码信息
函数原型
int32_t RegisterFormatErrorMessage(const char *error_msg, size_t error_msg_len)函数功能
按照规定的 JSON 格式,调用本接口给 CANN注册预定义的错误码信息后,再调用 ReportPredefinedErrMsg 接口上报错误码。可一次注册多个错误码,注册成功后即可通过ReportPredefinedErrMsg按注册的ErrCode上报并自动完成占位符替换。
同时为了方便使用,封装了宏REG_FORMAT_ERROR_MSG,用户可直接使用该宏注册。该宏直接定义静态变量,进程加载时就会完成注册:
#define REG_FORMAT_ERROR_MSG(error_msg, error_msg_len) \ REG_FORMAT_ERROR_MSG_UNIQ_HELPER((error_msg), (error_msg_len), __COUNTER__) #define REG_FORMAT_ERROR_MSG_UNIQ_HELPER(error_msg, error_msg_len, counter) \ REG_FORMAT_ERROR_MSG_UNIQ((error_msg), (error_msg_len), counter) #define REG_FORMAT_ERROR_MSG_UNIQ(error_msg, error_msg_len, counter) \ static const auto register_error_msg_##counter ATTRIBUTE_USED = []() -> int32_t { \ return error_message::RegisterFormatErrorMessage((error_msg), (error_msg_len)); \ }()宏中利用__COUNTER__保证多次调用生成互不重复的静态变量名,ATTRIBUTE_USED(GCC 下展开为__attribute__((used)))确保静态变量在编译优化下不被丢弃,从而保证注册逻辑一定被执行。
参数说明
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| error_msg | 输入 | 错误码信息,可一次注册多个错误码。错误码信息需按 JSON 格式组织,示例请参见下方调用示例。 |
| error_msg_len | 输入 | error_msg 长度,不包含末尾的\0。 |
返回值
- 0:成功。
- -1:失败。
调用示例
error_msg错误码信息需按照 JSON 格式组织,error_info_list是一个包含错误信息对象的数组,至少需要包含一个元素,其中各字段含义如下:
errClass:错误分类。errTitle:错误标题。ErrCode:错误码。注意不要与当前已有的错误码重复,已有的错误码可参考 docs/zh/error_code_ref/README.md 中的错误码章节。ErrMessage:错误消息,可以包含格式化占位符(%s)。Arglist:参数列表,用于说明ErrMessage中占位符对应的参数,参数列表长度与ErrMessage里格式化占位符个数必须相等。suggestion:建议信息,包含:Possible Cause:可能的原因。Solution:解决方法。
#include <string> #include "base/err_msg.h" const std::string error_msg = R"( { "error_info_list": [ { "errClass": "GE Errors", "errTitle": "Invalid_Dynamic_Shape_Argument", "ErrCode": "E10018", "ErrMessage": "Value [%s] for shape [%s] is invalid. When [--dynamic_batch_size] is included, only batch size N can be -1 in [--input_shape].", "Arglist": "shape,index", "suggestion": { "Possible Cause": "When [--dynamic_batch_size] is included, only batch size N can be -1 in the shape.", "Solution": "Try again with a valid [--input_shape] argument. Make sure that non-batch size axes are not -1." } }, { "errClass": "GE Errors", "errTitle": "Invalid_--input_shape_Argument", "ErrCode": "E10019", "ErrMessage": "When [--dynamic_image_size] is included, only the height and width axes can be -1 in [--input_shape].", "Arglist": "", "suggestion": { "Possible Cause": "When [--dynamic_image_size] is included, only the height and width axes can be -1 in the shape.", "Solution": "Try again with a valid [--input_shape] argument. Make sure that axes other than height and width are not -1." } } ] } )"; REG_FORMAT_ERROR_MSG(error_msg.c_str(), error_msg.size());注意:上例中E10018、E10019仅为说明 JSON 结构所用示例错误码,实际注册时务必与仓库内置错误码(见 src/dfx/error_manager/error_code.json)保持不重复,避免覆盖或冲突。
底层实现原理
RegisterFormatErrorMessage的实现位于 error_manager.cc:先用nlohmann::json对传入的error_msg按[error_msg, error_msg + error_msg_len)区间解析,JSON 语法错误直接返回-1;解析成功后调用ErrorManager::ParseJsonFormatString,并传入priority = 1。
ParseJsonFormatString会做以下校验与处理:
- 必须包含
error_info_list字段,且该字段必须是非空的数组,否则返回-1; - 遍历每个错误对象,读取
ErrCode、ErrMessage,可选读取errTitle与suggestion(含Possible Cause、Solution),Arglist按逗号分割成参数列表; - 对每个错误码执行"注册/更新"决策:若错误码尚未注册则直接加入
error_map_;若已存在,则优先级更高者覆盖。用户通过RegisterFormatErrorMessage注册的priority = 1高于内置 error_code.json 文件的默认priority = 0,因此用户注册的定义可覆盖同名内置错误码。
仓库内置错误码文件 src/dfx/error_manager/error_code.json 与上文 JSON 结构完全一致(error_info_list数组,元素含errClass、errTitle、ErrCode、ErrMessage、Arglist、suggestion),其内容涵盖 FE Errors、GE Errors、ACL Errors、Profiling Errors、Dump Errors、RTS Errors 等多个分类,是了解预定义错误模板的最佳参考资料。该文件在运行时由ErrorManager::Init从库目录下的../conf/error_manager/error_code.json加载解析,并通过懒初始化(EnsureInitialized)保证多线程并发调用下只执行一次解析。
补充:上下文粒度与 C 语言接口
除上述四个面向开发者的上报接口外,仓库还提供了配套的底层设施,理解它们有助于在定制组件中正确使用错误上报:
- 错误消息模式(ErrorMsgMode):定义于 pkg_inc/base/err_mgr.h,
INTERNAL_MODE(默认,推理按线程粒度、训练按 session 粒度记录)与PROCESS_MODE(以进程为粒度,所有错误汇聚到同一容器,输出时附加[THREAD:xxx]标识)。可通过ErrMgrInit(ErrorMessageMode)初始化。 - work_stream_id 上下文:
ErrorManager以线程局部error_context_维护当前 work_stream_id,默认由pid * 100000 + tid生成(GenWorkStreamIdDefault),也可通过GetErrMgrContext/SetErrMgrContext在父子线程间传递。 - 错误信息获取:
GetErrMgrErrorMessage、GetErrMgrWarningMessage、GetErrMgrRawErrorMessages可在上报后取回(并清空)当前上下文下的错误、告警及原始错误条目(含 error_id、error_title、possible_cause、solution、args、report_time 等),方便调用方自定义加工输出。 - C 语言接口:对 C 使用者,error_manager.h 通过
extern "C"导出了RegisterFormatErrorMessageForC、ReportPredefinedErrMsgForC、ReportInnerErrMsgForC三个等价接口,参数以const char**数组与arg_num传递,并对空指针入参做了防御性校验。
产品支持情况汇总
上述四个错误上报接口(ReportInnerErrMsg、ReportPredefinedErrMsg、ReportUserDefinedErrMsg、RegisterFormatErrorMessage)的产品支持情况完全一致,汇总如下:
| 产品系列 | 支持情况 |
|---|---|
| Ascend 950PR / Ascend 950DT | 支持 |
| Atlas A3 训练系列产品 / Atlas A3 推理系列产品 | 支持 |
| Atlas A2 训练系列产品 / Atlas A2 推理系列产品 | 支持 |
| Atlas 200I/500 A2 推理产品 | 支持 |
| Atlas 推理系列产品 | 支持 |
| Atlas 训练系列产品 | 支持 |
| IPV350 | 不支持 |
实践要点小结
- 选接口:内部组件问题用
REPORT_INNER_ERR_MSG(自动携带文件/函数/行号);上报 CANN 预定义用户错误用REPORT_PREDEFINED_ERR_MSG(自动做占位符替换);自定义错误信息用REPORT_USER_DEFINED_ERR_MSG直接传文本,错误码推荐 U 码段。 - 注册模板:需要带结构化 suggestion 与占位符替换的错误,用
REG_FORMAT_ERROR_MSG在进程加载期注册 JSON 模板,注册后再走ReportPredefinedErrMsg上报。 - 遵守约束:错误码必须为 6 位字符,用户自定义码不要以 8888/9999 结尾(否则会回退为
EU0000);格式化消息总长(含\0)不得超过 1024;注册的ErrCode不要与 src/dfx/error_manager/error_code.json 及 docs/zh/error_code_ref 中已有错误码重复。 - 编译链接:包含 include/dfx/base/err_msg.h 头文件,链接
liberror_manager.so(或静态库),即可在定制 CANN 组件与自定义算子中使用上述能力。
- CANN
- Ascend
- 人工智能
- 任务调度
【免费下载链接】runtime
本项目提供CANN运行时组件和维测功能组件。
相关推荐
CANN Runtime 错误消息(ErrMsg)开发规范全指南:错误码、上报宏与检视流程
CANN Runtime 错误消息(ErrMsg)开发规范全指南:错误码、上报宏与检视流程 导读 本文基于 CANN/runtime 仓库中 error_mes
CANNAscend人工智能任务调度CANN Runtime EZ2001 Execution_Error 错误码解析:AI Core 错误与 RAS 故障联动上报机制
CANN Runtime EZ2001 Execution_Error 错误码解析:AI Core 错误与 RAS 故障联动上报机制 EZ2001 是 CANN
CANNAscend人工智能任务调度CANN opbase 算子库 OP_LOGE_FOR_INVALID_CONFIGS_WITH_REASON 宏:多配置项无效错误的 ERROR 日志与 EZ0034 错误码上报指南
CANN opbase 算子库 OP_LOGE_FOR_INVALID_CONFIGS_WITH_REASON 宏:多配置项无效错误的 ERROR 日志与 EZ
人工智能算子库CANNAscend
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考