CANN Runtime 异常处理接口深度指南:错误获取、异常回调、UCE 修复与任务中止
【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime
CANN Runtime 在异步执行模型推理或算子任务时,设备侧(如 AI Core、内存、链路)可能发生异常,而异步任务本身不会直接向 Host 侧抛出错误码。本文基于 CANN Runtime 异常处理官方文档,系统梳理 Runtime 提供的错误信息获取、进程级异常回调注册、内存 UCE 查询与修复、设备任务中止与故障恢复等一整套异常处理接口,并对照本仓库源码(include/external/acl/acl_rt.h、src/acl/aclrt_impl/callback.cpp、src/acl/aclrt_impl/device.cpp)说明底层实现机理。读完本文,你将能够在模型推理或算子执行异常时准确定位出错的 Task/Stream/Device,并在遇错即停场景下完成任务中止与故障恢复的完整闭环。
一、异常处理接口全景
本章节描述的 CANN Runtime 异常处理接口覆盖四个维度:错误信息获取、异常回调注册、内存 UCE 修复及任务中止。全部接口清单如下:
| 接口 | 功能 | 所属类别 |
|---|---|---|
aclGetRecentErrMsg() | 获取并清空同一进程或线程中其它 acl 接口调用失败时的错误描述信息 | 错误信息获取 |
aclrtPeekAtLastError(level) | 获取当前线程的 Runtime 错误码,仅获取不清空 | 错误信息获取 |
aclrtGetLastError(level) | 获取当前线程的 Runtime 错误码,获取后清空 | 错误信息获取 |
aclrtSetExceptionInfoCallback(callback) | 设置进程级异常回调函数(废弃接口) | 异常回调 |
aclrtExceptionInfoCallbackRegister(callback) | 注册进程级异常回调函数,支持多个 | 异常回调 |
aclrtExceptionInfoCallbackUnregister(callback) | 注销已注册的进程级异常回调函数 | 异常回调 |
aclrtGetTaskIdFromExceptionInfo(info) | 获取异常信息中的任务 ID | 异常信息读取 |
aclrtGetStreamIdFromExceptionInfo(info) | 获取异常信息中的 Stream ID | 异常信息读取 |
aclrtGetThreadIdFromExceptionInfo(info) | 获取异常信息中的线程 ID | 异常信息读取 |
aclrtGetDeviceIdFromExceptionInfo(info) | 获取异常信息中的 Device ID | 异常信息读取 |
aclrtGetErrorCodeFromExceptionInfo(info) | 获取异常信息中的错误码 | 异常信息读取 |
aclrtGetMemUceInfo(deviceId, array, size, retSize) | 获取内存 UCE(不可纠正错误)的错误虚拟地址(试验特性) | UCE 修复 |
aclrtMemUceRepair(deviceId, array, arraySize) | 修复内存 UCE 的错误虚拟地址(试验特性) | UCE 修复 |
aclrtDeviceTaskAbort(deviceId, timeout) | 停止指定 Device 上正在执行的任务,丢弃已下发任务(试验特性) | 任务中止 |
aclrtGetErrorVerbose(deviceId, errorInfo) | 设备故障后获取详细错误信息(试验特性) | 故障恢复 |
aclrtRepairError(deviceId, errorInfo) | 基于详细错误信息进行故障恢复(试验特性) | 故障恢复 |
aclrtSetDeviceTaskAbortCallback(regName, callback, args) | 注册在aclrtDeviceTaskAbort前后触发的回调函数 | 任务中止 |
这些接口的声明与数据结构统一定义在头文件 include/external/acl/acl_rt.h,并在 src/acl/aclrt_impl/acl_rt_wrapper.h 中以统一宏的形式打包转发到底层 RT 接口(rtTaskFailCallback、rtSetTaskFailCallback等),最终由src/acl/aclrt_impl/目录下的实现文件完成。
产品支持情况汇总
各接口在不同产品上的支持情况不完全一致,以下为汇总(详细情况可对照原文档各接口的产品支持说明):
| 接口 | Ascend 950PR/950DT | Atlas A3 系列 | Atlas A2 系列 | Atlas 200I/500 A2 | Atlas 推理系列 | Atlas 训练系列 | IPV350 |
|---|---|---|---|---|---|---|---|
aclGetRecentErrMsg | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 不支持 |
aclrtSetExceptionInfoCallback | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 不支持 |
aclrtExceptionInfoCallbackRegister/Unregister | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 不支持 |
aclrtGetTaskId/StreamId/ThreadId/DeviceId/ErrorCodeFromExceptionInfo | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 不支持 |
aclrtPeekAtLastError/aclrtGetLastError | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
aclrtGetMemUceInfo/aclrtMemUceRepair | 支持 | 支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 |
aclrtDeviceTaskAbort | 支持 | 支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 |
aclrtGetErrorVerbose/aclrtRepairError | 支持 | 支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 |
aclrtSetDeviceTaskAbortCallback | 支持 | 支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 |
二、错误信息获取:aclGetRecentErrMsg
const char *aclGetRecentErrMsg()功能说明
获取并清空与本接口在同一个进程或线程中的其它 acl 接口调用失败时的错误描述信息。获取的是进程级还是线程级的错误描述信息,由 aclInit 接口中的err_msg_mode配置控制,默认线程级别。
使用该接口需要注意以下几点:
- 建议每次 acl 接口调用失败时都调用本接口,以便获取异常时的错误描述信息用于定位问题,否则可能导致错误信息堆积、丢失。
- 同一个进程或线程中多次调用
aclGetRecentErrMsg后,只有最后一次调用返回的错误描述字符串指针有效。之前调用返回的指针不能继续使用,否则可能导致内存非法访问。 - 本接口获取多条错误描述信息时,最上面的错误描述信息为最新的。
参数与返回值
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| 无 | — | 无参数 |
返回错误描述字符串的指针;获取失败时返回nullptr。返回的字符串由 Runtime 内部管理,仅最后一次调用的结果有效,业务侧不应长期保存该指针。
三、线程级 Runtime 错误码:aclrtPeekAtLastError 与 aclrtGetLastError
这两个接口用于获取当前线程的 Runtime(运行时管理模块)错误码,区别在于是否清空:
aclError aclrtPeekAtLastError(aclrtLastErrLevel level) // 仅获取,不清空 aclError aclrtGetLastError(aclrtLastErrLevel level) // 获取后清空aclrtPeekAtLastError:仅获取但不清空错误码,可反复调用多次查看同一错误。aclrtGetLastError:获取后清空当前线程的错误码。清空后,在线程中无新增错误码之前,调用本接口获取到的是ACL_SUCCESS。
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| level | 输入 | 指定获取错误码的级别,当前仅支持线程级别。类型定义参见 aclrtLastErrLevel。 |
返回 0 表示成功,返回其他值表示失败,错误码含义参见 aclError。aclrtLastErrLevel在头文件中定义为枚举ACL_RT_THREAD_LEVEL = 0(见 acl_rt.h),当前只存在线程级别一个取值。
与aclGetRecentErrMsg相比,这两个接口返回的是结构化错误码而非文本描述,适合在程序中做分支判断;而文本化描述信息更适合打印日志。
四、进程级异常回调机制
4.1 核心概念
Device 上的任务(如 AI Core 算子)异步执行,执行异常不会同步返回到调用侧。Runtime 通过进程级异常回调机制,在任务执行异常时向用户注册的回调函数传入一个aclrtExceptionInfo结构体指针,其中包含任务 ID、Stream ID、线程 ID、Device ID 以及错误码。用户可以在回调中调用读取接口获取这些字段,从而定位是哪个任务在哪个流上出了错。
回调函数原型与结构体定义(include/external/acl/acl_rt.h、acl_rt.h):
typedef struct rtExceptionInfo aclrtExceptionInfo; // 不透明结构体,仅由 Runtime 内部管理 typedef void (*aclrtExceptionInfoCallback)(aclrtExceptionInfo* exceptionInfo);使用前提:在执行异步任务之前完成回调的设置或注册;否则可能收不到任务的异常通知。
典型场景举例:在调用aclopExecuteV2接口前设置/注册异常回调函数,当算子在 Device 上执行异常时,系统会传入包含任务 ID、Stream ID、线程 ID、Device ID 以及错误码的aclrtExceptionInfo指针并执行回调。
4.2 aclrtSetExceptionInfoCallback(废弃)
aclError aclrtSetExceptionInfoCallback(aclrtExceptionInfoCallback callback)须知:此接口已废弃,请使用 aclrtExceptionInfoCallbackRegister 或 aclrtExceptionInfoCallbackUnregister 接口替代。头文件声明处同样带有
ACL_DEPRECATED_MESSAGE编译期废弃提示(见 acl_rt.h)。
功能要点:
- 设置进程级异常回调函数;如果想清空回调函数,可将入参设置为空指针(
NULL)。 - 若多次调用本接口设置异常回调函数,以最后一次设置为准。
- 不影响通过
aclrtExceptionInfoCallbackRegister接口注册的异常回调函数。
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| callback | 输入 | 指定要注册的回调函数,原型为typedef void (*aclrtExceptionInfoCallback)(aclrtExceptionInfo* exceptionInfo); |
约束说明:
- 回调函数涉及共享资源(例如锁),因此使用需慎重:在回调函数内调用资源申请&释放、Stream 同步、Device 同步、任务下发、任务终止等接口,可能导致错误或死锁。
- 当 Device 上的任务执行异常时,系统向回调函数传入包含任务 ID、Stream ID、线程 ID、Device ID 以及错误码的
aclrtExceptionInfo指针并执行回调。 exceptionInfo由 Runtime 管理,仅在本次回调执行期间有效。回调函数不得保存、释放或修改该指针及其内容。
4.3 aclrtExceptionInfoCallbackRegister 注册
aclError aclrtExceptionInfoCallbackRegister(aclrtExceptionInfoCallback callback)与废弃接口的关键差异在于支持注册多个不同的回调函数:
- 通过本接口可注册多个函数指针值不同的异常回调函数。
- 重复调用本接口注册同一个回调函数时返回成功,但 Runtime 只会保留最后一次注册信息。
- 本接口注册的回调与
aclrtSetExceptionInfoCallback(废弃)设置的回调可以共存,Device 任务异常进入 Runtime 异常通知流程时,两类回调都会被通知。 - 同一个回调函数既通过废弃接口设置、又通过本接口注册时,Runtime 会将其保存为两个相互独立的注册项,本次通知中该回调会被调用两次,两次调用的先后顺序不做保证。
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| callback | 输入 | 要注册的回调函数,不能为 NULL,原型为typedef void (*aclrtExceptionInfoCallback)(aclrtExceptionInfo *exceptionInfo); |
入参为 NULL 时返回参数错误。
从源码看注册实现:在 src/acl/aclrt_impl/callback.cpp 中,aclrtExceptionInfoCallbackRegisterImpl调用MakeExceptionCallbackRegName(rtCallback)将回调函数指针映射为一个字符串注册名,再转发到底层rtSetTaskFailCallback注册接口。也就是说,底层 RT 层以"注册名 + 回调指针"的形式管理注册项,这正解释了文档中"不同函数指针视为不同回调"与"重复注册同一回调仅保留最后一次"的语义;注销接口aclrtExceptionInfoCallbackUnregisterImpl(callback.cpp)则通过同样的注册名反查注销。
多回调并存的额外约束:
- Runtime 不保证同一个回调函数只在单个线程中执行。不同异常通知可能在不同线程中并发调用同一个回调函数,回调函数需自行保证其访问的数据线程安全。
- Runtime 不对各回调函数进行异常隔离。任一回调函数抛出异常可能中断本次通知,使尚未执行的其他回调函数不再被调用,并可能中断 Runtime 后续异常处理。
4.4 aclrtExceptionInfoCallbackUnregister 注销
aclError aclrtExceptionInfoCallbackUnregister(aclrtExceptionInfoCallback callback)- 注销通过
aclrtExceptionInfoCallbackRegister注册的进程级异常回调函数。 - 不支持注销通过
aclrtSetExceptionInfoCallback(废弃)接口设置的回调函数。 callback为 NULL 时返回参数错误;注销未注册的 callback 时,不执行操作并返回成功。
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| callback | 输入 | 待注销的回调函数,不能为 NULL。 |
额外的语义约束:
- Runtime 不记录调用本接口的调用方身份。进程内任意调用方只要持有已注册的相同函数指针,均可注销该注册项。
- 本接口不会等待已经进入异常通知流程或正在执行的回调函数结束。接口返回成功后,后续开始分发的异常通知不再包含该注册项,但已经进入通知流程的回调仍可能执行。因此释放回调函数访问的资源前,需通过业务同步确认所有在途回调均已结束。
4.5 多回调注册与注销示例
以下示例仅展示多个回调函数的注册和注销顺序,省略初始化、任务下发及异常处理逻辑:
void callbackA(aclrtExceptionInfo *exceptionInfo) { // 读取并处理callbackA关注的异常信息 deviceId = aclrtGetDeviceIdFromExceptionInfo(exceptionInfo); streamId = aclrtGetStreamIdFromExceptionInfo(exceptionInfo); taskId = aclrtGetTaskIdFromExceptionInfo(exceptionInfo); ...... } void callbackB(aclrtExceptionInfo *exceptionInfo) { // 读取并处理callbackB关注的异常信息 deviceId = aclrtGetDeviceIdFromExceptionInfo(exceptionInfo); streamId = aclrtGetStreamIdFromExceptionInfo(exceptionInfo); taskId = aclrtGetTaskIdFromExceptionInfo(exceptionInfo); ...... } aclrtExceptionInfoCallbackRegister(callbackA); aclrtExceptionInfoCallbackRegister(callbackB); // 下发异步任务并处理任务执行结果 aclrtExceptionInfoCallbackUnregister(callbackA); aclrtExceptionInfoCallbackUnregister(callbackB); // 注销接口不等待在途回调结束 // 释放回调函数访问的资源前,需通过业务同步确认所有在途回调均已结束五、异常信息读取接口
Runtime 向异常回调函数传入aclrtExceptionInfo指针后,用户可在回调内通过以下五个只读接口取出各个字段:
| 接口 | 返回内容 | 异常时的特殊返回值 |
|---|---|---|
uint32_t aclrtGetTaskIdFromExceptionInfo(const aclrtExceptionInfo *info) | 任务 ID | 0xFFFFFFFF 表示 Device 异常 |
uint32_t aclrtGetStreamIdFromExceptionInfo(const aclrtExceptionInfo *info) | Stream ID | 0xFFFFFFFF 表示 Device 异常 |
uint32_t aclrtGetThreadIdFromExceptionInfo(const aclrtExceptionInfo *info) | 线程 ID | 0xFFFFFFFF 表示 Device 异常 |
uint32_t aclrtGetDeviceIdFromExceptionInfo(const aclrtExceptionInfo *info) | Device ID | 0xFFFFFFFF 表示 Device 异常 |
uint32_t aclrtGetErrorCodeFromExceptionInfo(const aclrtExceptionInfo *info) | 错误码 | 0xFFFFFFFF 表示 Device 异常 |
参数info为异常信息指针(输入),即在执行任务之前通过废弃接口设置或通过注册接口注册回调时,系统将产生异常的任务 ID、Stream ID、线程 ID、Device ID(以及错误码)存放在aclrtExceptionInfo结构体中。该指针由 Runtime 管理,仅在本次回调执行期间有效。
六、AI Core 异常信息获取的完整流程与示例
使用场景:执行整网模型推理时(不支持动态 Shape 场景),如果产生 AI Core 报错,可以按照本章内容获取报错算子的描述信息,再做进一步错误排查。
推荐的接口调用顺序如下:
- 定义并实现异常回调函数 fn(
aclrtExceptionInfoCallback类型)。- 在 fn 内调用
aclrtGetDeviceIdFromExceptionInfo、aclrtGetStreamIdFromExceptionInfo、aclrtGetTaskIdFromExceptionInfo分别获取 Device ID、Stream ID、Task ID。 - 在 fn 内调用
aclmdlCreateAndGetOpDesc获取算子的描述信息。 - 在 fn 内调用
aclGetTensorDescByIndex获取指定算子输入/输出的 tensor 描述。 - 在 fn 内调用如下接口获取 tensor 描述中的数据做进一步分析:
aclGetTensorDescAddress(tensor 数据的内存地址,可从该地址读取 tensor 数据)、aclGetTensorDescType(数据类型)、aclGetTensorDescFormat(Format)、aclGetTensorDescNumDims(Shape 维度个数)、aclGetTensorDescDimV2(Shape 中指定维度的大小)。
- 在 fn 内调用
- 调用
aclrtSetExceptionInfoCallback(或aclrtExceptionInfoCallbackRegister)设置/注册异常回调函数。 - 执行模型推理;如果存在 AI Core 报错,则触发回调函数 fn,获取算子信息进行进一步分析。
以下是 AI Core 异常信息获取功能的关键步骤代码示例,不能直接拷贝编译运行,仅供参考(调用接口后需增加异常处理分支,并记录报错日志、提示日志):
...... // 1.模型加载,加载成功后,返回标识模型的modelId // 2.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output // 3.实现异常回调函数 void callback(aclrtExceptionInfo *exceptionInfo) { deviceId = aclrtGetDeviceIdFromExceptionInfo(exceptionInfo); streamId = aclrtGetStreamIdFromExceptionInfo(exceptionInfo); taskId = aclrtGetTaskIdFromExceptionInfo(exceptionInfo); char opName[256]; aclTensorDesc *inputDesc = nullptr; aclTensorDesc *outputDesc = nullptr; size_t inputCnt = 0; size_t outputCnt = 0; // 用户可以将获取的算子信息写入到文件,或者另起线程,当发生异常回调时触发线程处理函数,在线程处理函数中将算子信息在屏幕上显示 aclmdlCreateAndGetOpDesc(deviceId, streamId, taskId, opName, 256, &inputDesc, &inputCnt, &outputDesc, &outputCnt); // 可以调用tensor的相关接口,获取算子的相关信息,用户可以根据自己需要调用 for (size_t i = 0; i < inputCnt; ++i) { const aclTensorDesc *desc = aclGetTensorDescByIndex(inputDesc, i); aclGetTensorDescAddress(desc); aclGetTensorDescFormat(desc); } for (size_t i = 0; i < outputCnt; ++i) { const aclTensorDesc *desc = aclGetTensorDescByIndex(outputDesc, i); aclGetTensorDescAddress(desc); aclGetTensorDescFormat(desc); } aclDestroyTensorDesc(inputDesc); aclDestroyTensorDesc(outputDesc); } // 4.设置异常回调(新接口为 aclrtExceptionInfoCallbackRegister) aclrtSetExceptionInfoCallback(callback); // 5.执行模型 aclmdlExecute(modelId, input, output); // 6.处理模型推理结果 ...... // 7.释放描述模型输入/输出信息、内存等资源,卸载模型 ......七、内存 UCE 查询与修复
UCE(uncorrectable error)指系统硬件不能直接处理并恢复的内存错误。Runtime 提供查询与修复两个接口,二者均为试验特性,后续版本可能变更,不支持应用于生产环境。
7.1 aclrtGetMemUceInfo:获取 UCE 错误虚拟地址
aclError aclrtGetMemUceInfo(int32_t deviceId, aclrtMemUceInfo *memUceInfoArray, size_t arraySize, size_t *retSize)| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| deviceId | 输入 | Device ID,与 aclrtSetDevice 接口中保持一致 |
| memUceInfoArray | 输入&输出 | aclrtMemUceInfo数组的指针,类型定义参见 aclrtMemUceInfo |
| arraySize | 输入 | 传入aclrtMemUceInfo数组的长度 |
| retSize | 输出 | 实际返回的aclrtMemUceInfo数组的有效长度 |
7.2 aclrtMemUceRepair:修复 UCE 错误虚拟地址
aclError aclrtMemUceRepair(int32_t deviceId, aclrtMemUceInfo *memUceInfoArray, size_t arraySize)| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| deviceId | 输入 | Device ID,与 aclrtSetDevice 接口保持一致 |
| memUceInfoArray | 输入 | aclrtMemUceInfo数组的指针 |
| arraySize | 输入 | 传入aclrtMemUceInfo数组的长度 |
7.3 数据结构
aclrtMemUceInfo结构体定义在头文件 acl_rt.h:
#define MAX_MEM_UCE_INFO_ARRAY_SIZE 128 #define UCE_INFO_RESERVED_SIZE 14 typedef struct aclrtMemUceInfo { void* addr; // UCE 错误虚拟地址 size_t len; // 地址长度 size_t reserved[UCE_INFO_RESERVED_SIZE]; } aclrtMemUceInfo;典型使用顺序:先用aclrtGetMemUceInfo查询出发生 UCE 的错误虚拟地址数组(实际有效长度由retSize返回),再将该数组交给aclrtMemUceRepair进行修复,形成"查询 → 修复"的闭环。
八、设备故障处理与任务中止
当 Device 发生严重故障时,需要依次执行"获取故障详情 → 中止任务 → 修复故障"的流程,配套接口为aclrtGetErrorVerbose、aclrtDeviceTaskAbort、aclrtRepairError,以及任务中止的前后置回调接口aclrtSetDeviceTaskAbortCallback。这四个接口均为试验特性,不支持应用于生产环境。
8.1 aclrtGetErrorVerbose:获取设备故障详细信息
aclError aclrtGetErrorVerbose(int32_t deviceId, aclrtErrorInfo *errorInfo);调用时机:用于在发生设备故障后获取详细错误信息。必须在获取故障事件之后、提交任务中止之前调用。
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| deviceId | 输入 | Device ID,与 aclrtSetDevice 接口保持一致 |
| errorInfo | 输出 | 错误信息,结构体定义如下 |
aclrtErrorInfo相关类型完整定义(与 acl_rt.h 一致):
typedef enum { ACL_RT_NO_ERROR = 0, // 无错误 ACL_RT_ERROR_MEMORY = 1, // 内存错误 ACL_RT_ERROR_L2 = 2, // L2 Buffer错误 ACL_RT_ERROR_AICORE = 3, // AI Core错误 ACL_RT_ERROR_LINK = 4, // 网络错误 ACL_RT_ERROR_L3_PORT = 5, // L3端口错误 ACL_RT_ERROR_OTHERS = 0xFFFF, // 其它错误 } aclrtErrorType; typedef enum aclrtAicoreErrorType { ACL_RT_AICORE_ERROR_UNKNOWN, // 未知错误 ACL_RT_AICORE_ERROR_SW, // 建议排查软件错误 ACL_RT_AICORE_ERROR_HW_LOCAL, // 建议排查当前Device的硬件错误 } aclrtAicoreErrorType; #define ACL_RT_MEM_UCE_INFO_MAX_NUM 20 typedef struct { size_t arraySize; // memUceInfoArray数组大小 aclrtMemUceInfo memUceInfoArray[ACL_RT_MEM_UCE_INFO_MAX_NUM]; // 内存UCE的错误虚拟地址数组 } aclrtMemUceInfoArray; typedef union aclrtErrorInfoDetail { aclrtMemUceInfoArray uceInfo; // 内存UCE(uncorrect error) aclrtAicoreErrorType aicoreErrType; // AI Core错误 } aclrtErrorInfoDetail; typedef struct aclrtErrorInfo { uint8_t tryRepair; // 是否需要修复,0表示无需修复,1表示需修复 uint8_t hasDetail; // 是否有详细报错信息,0表示没有,1表示有 uint8_t reserved[2]; // 预留参数 aclrtErrorType errorType; // 错误类型 aclrtErrorInfoDetail detail; // 错误详细信息 } aclrtErrorInfo;约束说明:
- 如果通过 aclrtGetOpTimeOutInterval 接口查询到的超时最短时间间隔小于 100ms 时,本接口返回的故障详细信息可能不准确。
- 对于 Atlas A3 训练系列产品/Atlas A3 推理系列产品、Atlas A2 训练系列产品/Atlas A2 推理系列产品,仅支持获取
ACL_RT_NO_ERROR(无错误)、ACL_RT_ERROR_MEMORY(内存错误)、ACL_RT_ERROR_OTHERS(其它错误)。
8.2 aclrtDeviceTaskAbort:停止指定 Device 上的任务
aclError aclrtDeviceTaskAbort(int32_t deviceId, uint32_t timeout)停止指定 Device 上的正在执行的任务,同时丢弃指定 Device 上已下发的任务。支持永久等待或配置具体的超时时间:
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| deviceId | 输入 | Device ID,与 aclrtSetDevice 接口保持一致 |
| timeout | 输入 | 超时时间:0 表示永久等待;>0 表示配置具体的超时时间,单位毫秒,最大超时时间 36 分钟 |
约束说明:当前接口仅支持遇错即停场景下使用,否则会出现不可预知的异常问题。默认模式为遇错继续模式,如需调用本接口,请先设置遇错即停模式,具体可参考接口 aclrtSetStreamFailureMode。
从源码看实现:aclrtDeviceTaskAbortImpl实现于 src/acl/aclrt_impl/device.cpp,调用前会记录deviceId与timeout的日志,再向下转发到 RT 层任务中止接口。
8.3 aclrtRepairError:基于故障详情进行恢复
aclError aclrtRepairError(int32_t deviceId, const aclrtErrorInfo *errorInfo)基于aclrtGetErrorVerbose接口获取的详细信息进行故障恢复,此接口应该在提交任务中止之后调用。参数errorInfo为aclrtErrorInfo结构体(输入),其定义见 8.1 节。
8.4 aclrtSetDeviceTaskAbortCallback:任务中止前后回调
aclError aclrtSetDeviceTaskAbortCallback(const char *regName, aclrtDeviceTaskAbortCallback callback, void *args)注册回调函数,用于在调用aclrtDeviceTaskAbort接口前后触发该回调函数。不支持重复注册。
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| regName | 输入 | 注册名称,保持唯一,不能为空,输入保证字符串以\0结尾 |
| callback | 输入 | 回调函数。若 callback 不为 NULL,表示注册回调函数;若为 NULL,表示取消注册回调函数。原型见下方定义 |
| args | 输入 | 待传递给回调函数的用户数据的指针 |
回调函数原型(与 acl_rt.h、acl_rt.h 一致):
typedef enum { ACL_RT_DEVICE_TASK_ABORT_PRE = 0, // 任务中止前 ACL_RT_DEVICE_TASK_ABORT_POST, // 任务中止后 } aclrtDeviceTaskAbortStage; typedef int32_t (*aclrtDeviceTaskAbortCallback)( int32_t deviceId, aclrtDeviceTaskAbortStage stage, uint32_t timeout, void* args);其中timeout表示期望回调函数执行的最长时间。
8.5 故障恢复完整调用序列
综合以上接口,设备故障恢复的推荐调用序列为:
- 收到设备故障事件;
- 调用
aclrtGetErrorVerbose获取详细错误信息(必须在任务中止之前); - 调用
aclrtDeviceTaskAbort停止 Device 上正在执行/已下发的任务(若需在前后挂接业务逻辑,可先用aclrtSetDeviceTaskAbortCallback注册回调); - 调用
aclrtRepairError基于获取到的aclrtErrorInfo进行故障恢复(必须在任务中止之后); - 根据
aclrtErrorInfo.errorType与detail判断是内存、L2、AI Core、链路等哪类错误,决定是否需要进一步排查软硬件。
九、接口返回值与错误码约定
所有aclError类型的接口均遵循统一约定:
- 返回 0 表示成功;
- 返回其他值表示失败,错误码含义请参见 aclError。
异常信息读取接口(Task/Stream/Thread/Device/ErrorCode)在返回值为0xFFFFFFFF(十六进制)时表示Device 异常,此时各字段不再具有实际意义,应优先按设备级故障处理流程(见第八章)处理。
十、总结与最佳实践
- 错误描述与错误码双通道:文本化描述用
aclGetRecentErrMsg(每次失败后立即调用,注意只有最后一次返回的指针有效),结构化错误码用aclrtGetLastError/aclrtPeekAtLastError(线程级,前者读取即清空)。 - 异步异常定位靠回调:在异步任务下发前设置或注册进程级异常回调,在回调内通过
aclrtGetTaskIdFromExceptionInfo等接口拿到任务、流、线程、设备与错误码,再结合aclmdlCreateAndGetOpDesc、aclGetTensorDescByIndex等接口还原出错算子的描述信息。新开发代码应使用aclrtExceptionInfoCallbackRegister/aclrtExceptionInfoCallbackUnregister,而非已废弃的aclrtSetExceptionInfoCallback。 - 回调内谨慎操作:不要在回调内做资源申请/释放、Stream/Device 同步、任务下发与终止等可能引发死锁的操作;多回调并存时要保证数据访问的线程安全。
- 设备级故障走完整闭环:遇错即停模式下,按"获取故障事件 →
aclrtGetErrorVerbose→aclrtDeviceTaskAbort(可配aclrtSetDeviceTaskAbortCallback前后置回调)→aclrtRepairError"的顺序处理。 - 注意版本与产品限制:UCE 修复、任务中止、故障恢复类接口均为试验特性,且 Atlas 200I/500 A2、Atlas 推理系列、Atlas 训练系列等产品不支持,投产前需确认目标产品的支持情况(见产品支持情况汇总)。
- 源码阅读指引:接口声明与数据结构见 include/external/acl/acl_rt.h;回调注册/注销的实现见 src/acl/aclrt_impl/callback.cpp;任务中止实现见 src/acl/aclrt_impl/device.cpp;接口转发封装见 src/acl/aclrt_impl/acl_rt_wrapper.h。
【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考