
CANN Runtime异步错误码获取与解读指南从返回成功到定位Device侧故障【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime导读在 CANN Runtime 的编程模型中aclrtMemcpyAsync、Kernel Launch 等异步接口在 Host 侧将任务下发到 Stream 后即返回接口返回值只反映参数校验与任务下发是否成功无法立即反映 Device 侧的实际执行结果。这导致开发中常见的困惑异步接口返回ACL_RT_SUCCESS但算子或拷贝任务在 Device 侧实际执行失败错误延迟到后续某个同步接口才暴露出来。本文将基于当前仓库的 FAQ 文档、公共头文件与错误码定义系统讲解 Runtime 异步错误码的产生机制、错误码数值含义、五种错误获取与定位手段同步接口、错误查询接口、详细错误信息、遇错即停模式、plog 日志与 Event/Host 回调辅助定位并提供可直接复制使用的代码示例帮助你在多任务 Stream 场景下快速定位首个失败任务与根因。问题现象异步接口返回成功但执行失败现象1异步接口返回成功但 Device 侧实际执行失败调用 Runtime 异步接口如aclrtMemcpyAsync、Kernel Launch 等时接口返回成功ACL_RT_SUCCESS但实际执行时 Device 侧发生了错误。典型代码如下aclrtStream stream; aclrtCreateStream(stream); // 异步接口返回成功仅表示任务下发成功 aclError error aclrtMemcpyAsync(devPtr, devSize, hostPtr, hostSize, ACL_MEMCPY_HOST_TO_DEVICE, stream); // error ACL_RT_SUCCESS但Device侧可能执行失败现象2异步错误延迟传播导致难以定位Device 侧的异步错误会延迟到后续某个 Runtime 接口调用时返回可能不是实际发生错误的接口导致错误定位困难。报错日志示例如下[ERROR] RUNTIME: Aicore kernel execute failed, ret507015, aicore exception fault kernel_nameAdd_ee98c6628030785f610b924ab1557b31其中507015即错误码ACL_ERROR_RT_AICORE_EXCEPTIONaicore exceptionkernel_name给出了发生异常的算子名称。日志中的ret507015与aclrtSynchronizeStream等接口返回的aclError数值是同一套错误码体系。现象3遇错继续模式下多个错误覆盖在遇错继续模式ACL_CONTINUE_ON_FAILURE默认模式下如果 Stream 上多个任务执行失败后发生的错误可能覆盖先前的错误信息导致无法获取首次错误// 后续操作基于错误假设继续执行 myKernel8, nullptr, stream(); aclrtMemcpyAsync(hostPtr, hostSize, devPtr, devSize, ACL_MEMCPY_DEVICE_TO_HOST, stream); aclrtSynchronizeStream(stream); // 此时才发现错误但难以定位是哪个异步任务失败可能原因异步执行机制与错误传播链路异步执行机制Runtime 异步接口在 Host 侧下发任务后立即返回Device 侧任务异步执行。接口返回值仅反映 Host 侧参数校验和任务下发是否成功无法报告 Device 侧的实际执行错误。这是返回成功但执行失败现象产生的根本原因。错误传播延迟Device 侧的异步错误会延迟到后续某个 Runtime 接口调用典型如aclrtSynchronizeStream、aclrtSynchronizeDevice时返回该接口往往不是实际发生错误的接口从而造成定位困难。错误覆盖问题在遇错继续模式下如果 Stream 上多个任务执行失败后发生的错误可能覆盖先前的错误信息导致无法获取首次错误。从仓库的公共头文件 include/external/acl/error_codes/rt_error_codes.h 可以看到ACL_RT_SUCCESS定义为0其余所有错误码均为非零值这正是判断返回值是否等于ACL_RT_SUCCESS这一习惯用法的依据#define ACL_RT_SUCCESS 0 // success先读懂错误码107000 / 207000 / 507000 三段式编码体系要解读异步错误首先需要理解 Runtime 错误码的数值分布。以仓库 include/external/acl/error_codes/rt_error_codes.h 的定义为准ACL_ERROR_RT_*系列错误码按前缀数字分为三大区间分别对应不同错误类别错误码区间类别典型错误码示例含义107000段参数与上下文校验类ACL_ERROR_RT_PARAM_INVALID(107000)参数非法ACL_ERROR_RT_INVALID_DEVICEID(107001)非法 Device IDACL_ERROR_RT_CONTEXT_NULL(107002)当前 Context 为空ACL_ERROR_RT_STREAM_CONTEXT(107003)Stream 不在当前 ContextACL_ERROR_RT_WAIT_TIMEOUT(107019)等待超时207000段特性支持与资源类ACL_ERROR_RT_FEATURE_NOT_SUPPORT(207000)特性不支持ACL_ERROR_RT_MEMORY_ALLOCATION(207001)内存分配失败OOMACL_ERROR_RT_AICORE_OVER_FLOW(207003)AICore 溢出ACL_ERROR_RT_NO_DEVICE(207004)无可用 DeviceACL_ERROR_RT_DEVICE_OOM(207018)Device 内存耗尽507000段执行期与内核级异常ACL_ERROR_RT_AICORE_TIMEOUT(507014)AICore 执行超时ACL_ERROR_RT_AICORE_EXCEPTION(507015)AICore 异常上文日志中的 ret507015ACL_ERROR_RT_AICPU_TIMEOUT(507017)AICPU 超时ACL_ERROR_RT_VECTOR_CORE_EXCEPTION(507035)向量核异常ACL_ERROR_RT_STREAM_SYNC_TIMEOUT(507046)Stream 同步超时一般规律107000段错误多发生在接口调用阶段可直接通过接口返回值捕获207000段反映资源与特性约束问题507000段多为 Device 侧执行阶段的内核级异常正是异步任务失败后经同步接口延迟返回的典型错误码。完整的错误码定义、对应解释以及配套的错误码参考文档如 EE1019 Execution_Error均可在仓库中查阅。方法1异步接口后立即同步获取异步错误在异步接口调用后立即调用同步接口获取 Device 侧的实际执行结果。这是最直观、开销也最小的错误获取手段适用于单任务或任务序列较短、可接受同步等待的场景aclrtStream stream; aclrtCreateStream(stream); // 下发异步任务 aclError error aclrtMemcpyAsync(devPtr, devSize, hostPtr, hostSize, ACL_MEMCPY_HOST_TO_DEVICE, stream); // 立即同步并获取错误码 error aclrtSynchronizeStream(stream); if (error ! ACL_RT_SUCCESS) { // 处理错误 printf(Async task failed with error: %d\n, error); char *errMsg aclGetRecentErrMsg(); printf(Error message: %s\n, errMsg); } aclrtDestroyStream(stream);aclrtSynchronizeStream会阻塞等待 Stream 上已下发任务执行完成并将 Device 侧的执行结果以错误码形式返回是异步错误最主要的出口。仓库公共头文件 include/external/acl/acl_rt.h 中对该系列接口的声明如下接口原型均为ACL_FUNC_VISIBILITY导出的 C 接口可在 C/C 中直接调用ACL_FUNC_VISIBILITY const char* aclGetRecentErrMsg(); ACL_FUNC_VISIBILITY aclError aclrtPeekAtLastError(aclrtLastErrLevel level); ACL_FUNC_VISIBILITY aclError aclrtGetLastError(aclrtLastErrLevel level); ACL_FUNC_VISIBILITY aclError aclrtSetStreamFailureMode(aclrtStream stream, uint64_t mode);方法2使用错误查询接口查看与重置线程错误状态使用aclrtPeekAtLastError或aclrtGetLastError查询当前线程的错误状态。二者的区别在于aclrtPeekAtLastError只查看不重置aclrtGetLastError在返回错误码的同时将错误状态重置为ACL_RT_SUCCESS。aclrtStream stream; aclrtCreateStream(stream); aclrtSetStreamFailureMode(stream, ACL_STOP_ON_FAILURE); // 下发多个异步任务 aclrtMemcpyAsync(devPtr, devSize, hostPtr, hostSize, ACL_MEMCPY_HOST_TO_DEVICE, stream); myKernel8, nullptr, stream(); aclrtMemcpyAsync(hostPtr, hostSize, devPtr, devSize, ACL_MEMCPY_DEVICE_TO_HOST, stream); // 同步并检查错误 aclrtSynchronizeStream(stream); // 查看错误但不重置 aclError lastError aclrtPeekAtLastError(ACL_RT_THREAD_LEVEL); if (lastError ! ACL_RT_SUCCESS) { printf(Last error: %d\n, lastError); } // 获取并重置错误状态 lastError aclrtGetLastError(ACL_RT_THREAD_LEVEL); // 此时错误状态已重置为ACL_RT_SUCCESS从 include/external/acl/acl_rt.h 的源码可以看出错误等级参数aclrtLastErrLevel目前定义了一个枚举值typedef enum aclrtLastErrLevel { ACL_RT_THREAD_LEVEL 0, } aclrtLastErrLevel;即当前查询维度为线程级ACL_RT_THREAD_LEVEL 0错误状态与发起调用的线程绑定。由于错误状态是线程私有的在实际工程中应确保下发任务、同步等待、查询错误发生在同一线程否则可能查不到预期的错误码。方法3获取详细错误信息与错误码分类处理通过aclGetRecentErrMsg()获取最近一次错误的详细描述字符串并结合错误码进行分门别类的处理。注意该接口返回的字符串由 Runtime 内部管理调用方不应自行释放aclError error aclrtSynchronizeDevice(); if (error ! ACL_RT_SUCCESS) { char *errMsg aclGetRecentErrMsg(); if (errMsg ! nullptr) { printf(Error detail: %s\n, errMsg); } // 根据错误码进行分类处理 // 实际错误码定义请参考 rt_error_codes.h 头文件 switch (error) { case ACL_ERROR_RT_PARAM_INVALID: // 107000 printf(Invalid parameter\n); break; case ACL_ERROR_RT_INVALID_DEVICEID: // 107001 printf(Invalid device ID\n); break; // ... 其他错误码处理 } }错误码的数值定义集中在仓库头文件 include/external/acl/error_codes/rt_error_codes.h 中。实际使用时建议优先使用宏名如ACL_ERROR_RT_AICORE_EXCEPTION而非裸数值进行判断宏名语义清晰且错误码数值在演进版本中可能调整而宏名保持稳定。头文件中共有 100 余个ACL_ERROR_RT_*宏覆盖参数校验、资源分配、执行期异常、IPC、快照、CCU 等各类场景需要按业务场景查阅对应区间的定义。方法4结合遇错即停模式在首个错误处停止执行配置遇错即停模式ACL_STOP_ON_FAILURE在首个错误发生时停止执行避免错误传播与覆盖从而准确定位首次失败的任务aclrtStream stream; aclrtCreateStream(stream); // 配置遇错即停 aclError error aclrtSetStreamFailureMode(stream, ACL_STOP_ON_FAILURE); if (error ! ACL_RT_SUCCESS) { printf(Failed to set failure mode\n); return error; } // 下发任务 aclrtMemcpyAsync(devPtr, devSize, hostPtr, hostSize, ACL_MEMCPY_HOST_TO_DEVICE, stream); myKernel8, nullptr, stream(); aclrtMemcpyAsync(hostPtr, hostSize, devPtr, devSize, ACL_MEMCPY_DEVICE_TO_HOST, stream); // 同步并检查 error aclrtSynchronizeStream(stream); if (error ! ACL_RT_SUCCESS) { // 首个错误发生时即停止便于定位 printf(First error occurred: %d\n, error); char *errMsg aclGetRecentErrMsg(); printf(Error message: %s\n, errMsg); } aclrtDestroyStream(stream);两种失败模式宏在 include/external/acl/acl_rt.h 中定义如下#define ACL_CONTINUE_ON_FAILURE 0x00000000U #define ACL_STOP_ON_FAILURE 0x00000001U使用前提与限制ACL_STOP_ON_FAILURE模式下首个任务出错后Runtime 会停止该 Context 下相关 Stream 上后续任务的执行这本身会改变任务调度行为且错误发生时失败任务之后的任务不会执行如果错误现场需要多跑几个任务收集信息则遇错即停模式反而不利。建议生产环境使用遇错即停模式定位问题期间可临时切回遇错继续模式收集更多现场信息。关于该模式的更多定位技巧分段同步、Event 边界标记、Host 回调等可进一步参考仓库文档 遇错即停模式下错误定位方法。方法5结合 plog 日志定位 Device 侧异常根因错误码只能回答哪个环节出错要回答为什么出错需要结合 plog 日志。上文示例日志中的关键字段具备明确语义[ERROR] RUNTIME: Aicore kernel execute failed, ret507015, aicore exception fault kernel_nameAdd_ee98c6628030785f610b924ab1557b31ret507015对应ACL_ERROR_RT_AICORE_EXCEPTIONAICore 执行异常kernel_nameAdd_...定位到具体失败的内核算子可用于反向回溯算子输入/上下文。针对长任务序列结合错误查询接口与日志定位的具体操作手法grep 关键字段如下# 查找失败的任务 grep Task run failed plog.log # 查找失败的内核名称 grep fault kernel_name plog.log # 查找错误码和类型 grep retCode\|errType plog.log # 查找错误模块 grep module_type\|module_name plog.log日志示例解读# [ERROR] Task run failed, device_id0, stream_id2, task_id1 # - 定位到具体的设备、流、任务ID # fault kernel_nameAdd_ee98c6628030785f610b924ab1557b31 # - 定位到具体失败的内核 # retCode0x31, [vector core exception] # - 错误原因向量核异常 # module_type5, module_nameEZ9999 # - 错误来源模块通过device_id / stream_id / task_id三元组可将问题精确锁定到某条 Stream 上的某个任务再结合kernel_name与错误模块信息定位根因。有关 Device 侧日志的更多背景知识可参考仓库文档 如何通过plog日志定位Device侧异常。纵深补充长任务序列中的三种辅助定位手段当 Stream 上串行下发大量任务且无法接受逐段同步的性能开销时可结合 Event 与 Host 回调辅助定位完整可运行示例见 遇错即停模式下错误定位方法使用 Event 标记任务边界在关键任务之间调用aclrtRecordEvent插入 Event错误发生后通过aclrtEventQuery查询各 Event 状态。最后一个状态为ACL_RT_EVENT_COMPLETE的 Event 与第一个状态为ACL_RT_EVENT_NOT_READY的 Event 之间即为失败任务所在区间。使用 Host 回调打印进度在任务之间插入aclrtLaunchHostFunc(stream, callback, userData)回调在对应任务完成后于 Host 侧执行并打印任务编号。错误发生后从回调输出可确定最后一个成功完成的任务其后即为失败任务。分段同步定位将长序列拆分为多个小段每段后调用aclrtSynchronizeStream检查配合aclGetRecentErrMsg逐步缩小失败范围。这是最朴素也最可靠的定位手段。最佳实践小结场景推荐做法关键接口/手段单任务或短任务序列异步接口后立即aclrtSynchronizeStreamaclrtSynchronizeStreamaclGetRecentErrMsg多任务同线程提交同步后查询线程错误状态aclrtPeekAtLastError/aclrtGetLastErrorACL_RT_THREAD_LEVEL生产环境防错误覆盖开启遇错即停获取首次错误aclrtSetStreamFailureMode(stream, ACL_STOP_ON_FAILURE)错误码语义解读优先使用宏名判断按 107/207/507 区间归类rt_error_codes.h根因深入分析结合 plog 日志的 device_id/stream_id/task_id/kernel_namegrep 日志关键字段长任务序列性能敏感Event 边界标记 Host 回调进度打印aclrtRecordEvent/aclrtEventQuery/aclrtLaunchHostFunc核心结论Runtime 异步接口的返回值只承诺任务已成功下发Device 侧执行结果必须通过同步接口、错误查询接口与日志三者配合获取。理解 107000 / 207000 / 507000 三段错误码语义是快速从ret507015这类原始日志跳转到具体故障根因的第一步。【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考