CANN Runtime 初始化与去初始化接口深度解析:aclInit/aclFinalize 及配套配置与回调机制
【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime
CANN Runtime(本开源仓库 cann/runtime)中,所有基于 acl 接口开发的应用程序都必须先完成 ACL 环境的初始化。本文以 docs/zh/api_ref/02_initialization_and_deinitialization.md 为骨架,系统讲解aclInit、aclFinalize、aclFinalizeReference三个核心生命周期接口,以及初始化/去初始化回调的注册与注销接口,并结合仓库源码(src/acl/aclrt_c/common/acl_rt.c、src/acl/aclrt_impl/acl.cpp)剖析其引用计数、配置解析与回调派发原理。读完本文,你将掌握:ACL 进程级初始化的正确时序与多线程/多模块场景下的安全用法、如何在aclInit配置文件中开启各类 Dump 与 Profiling 采集能力、如何通过引用计数实现多模块协同的去初始化,以及如何利用回调机制在初始化与去初始化阶段挂接自定义逻辑。
一、接口总览
初始化与去初始化接口共 6 个,覆盖"初始化—去初始化—回调注册—回调注销"完整生命周期:
| 接口 | 功能 |
|---|---|
aclError aclInit(const char *configPath) | 初始化函数,应用使用 acl 接口前必须调用 |
aclError aclFinalize() | 去初始化函数,释放进程内 acl 接口使用的相关资源(计数直接清零) |
aclError aclFinalizeReference(uint64_t *refCount) | 去初始化函数,基于引用计数逐次释放资源 |
aclError aclInitCallbackRegister(aclRegisterCallbackType type, aclInitCallbackFunc cbFunc, void *userData) | 注册初始化回调函数 |
aclError aclInitCallbackUnRegister(aclRegisterCallbackType type, aclInitCallbackFunc cbFunc) | 取消注册初始化回调函数 |
aclError aclFinalizeCallbackRegister(aclRegisterCallbackType type, aclFinalizeCallbackFunc cbFunc, void *userData) | 注册去初始化回调函数 |
aclError aclFinalizeCallbackUnRegister(aclRegisterCallbackType type, aclFinalizeCallbackFunc cbFunc) | 取消注册去初始化回调函数 |
其中aclFinalizeReference与aclInitCallbackRegister/aclInitCallbackUnRegister/aclFinalizeCallbackRegister/aclFinalizeCallbackUnRegister在 IPV350 上不支持,其余接口在 Ascend 950PR/Ascend 950DT、Atlas A3 训练/推理系列、Atlas A2 训练/推理系列、Atlas 200I/500 A2 推理产品、Atlas 推理系列、Atlas 训练系列产品上均支持。
二、aclInit:ACL 环境的初始化
2.1 功能与调用前提
aclError aclInit(const char *configPath)使用 acl 接口开发应用时,必须先调用aclInit接口,否则可能导致后续系统内部资源初始化出错,进而引发其它业务异常。从源码实现看,aclInit在底层完成的工作包括:
- 解析并校验配置文件,把配置字符串缓存到全局(src/acl/aclrt_impl/acl.cpp 中
aclInitImpl的GetStrFromConfigPath、SetConfigPathStr); - 初始化错误信息上报模块(
HandleErrorManagerConfig、ErrMgrInit)与 Device 日志模块(DlogReportInitialize); - 依次派发各功能模块的初始化回调(
acl_model、acl_op_executor、acl_dvpp及其他),并处理 Dump 配置、默认 Device、栈空间、Printf FIFO 等配置; - 注册 Profiling 回调(
MsprofRegisterCallback)并处理 Profiling 配置; - 最后把
aclInitRefCount置为 1,记录首次配置文件的哈希与路径。
2.2 参数说明
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| configPath | 输入 | 配置文件所在路径(包含文件名)的指针。配置文件内容为 JSON 格式(JSON 文件内{的层级最多为 10,[的层级最多为 10)。初始化时可通过该配置文件配置开启 Dump、配置 Profiling 采集信息等功能。如果默认配置已满足需求,可向aclInit接口传入NULL,或将配置文件配置为空 JSON 串(即配置文件中只有{})。 |
2.3 返回值说明
返回 0 表示成功,返回其他值表示失败,错误码含义参见 aclError 错误码参考。
2.4 重复初始化与引用计数约束
一个进程内支持多次调用aclInit初始化,但必须配套调用aclFinalize或aclFinalizeReference去初始化。约束要点如下:
配置一致性:每次调用
aclInit时,配置必须保持一致,否则仅首次调用的配置有效,后续调用可能导致报错或配置无效。源码中通过保存首次配置文件的哈希值aclInitJsonHash来校验:若第二次传入的配置内容哈希与首次不同,会返回ACL_ERROR_INVALID_PARAM(见 src/acl/aclrt_impl/acl.cpp)。兼容旧版本:重复调用
aclInit会返回ACL_ERROR_REPEAT_INITIALIZE错误码,可以忽略该错误继续处理业务。配合
aclFinalize(顺序调用):支持重复初始化、去初始化,但时序上仅支持顺序调用:aclInit-->业务处理-->aclFinalize-->aclInit-->业务处理-->aclFinalize该场景下,如果调用多次
aclInit后再去初始化,仅需调用一次aclFinalize,即可把aclInit的引用计数直接清零。配合
aclFinalizeReference(顺序或并发调用均可):aclFinalizeReference内部涉及引用计数实现——aclInit每被调用一次,引用计数加一;aclFinalizeReference每被调用一次,引用计数减一;当引用计数减到 0 时才会真正去初始化。顺序调用与并发调用两种时序如下:
源码中aclFinalizeReferenceImpl(src/acl/aclrt_impl/acl.cpp)正是按这一逻辑实现:计数大于 1 时仅减一返回;计数等于 1 时才真正执行aclFinalizeInternal释放资源;计数小于 1(未初始化就调用或重复调用)时返回ACL_ERROR_REPEAT_FINALIZE。
IPV350 特殊约束:IPV350 要求aclInit与aclFinalize数量匹配:
成对调用
aclInit、aclFinalize,每对之间正常处理业务,每次aclInit的 JSON 配置都能生效:aclInit-->业务处理-->aclFinalize-->aclInit-->业务处理-->aclFinalize连续调用 N 次
aclInit,也需连续调用 N 次aclFinalize才能真正去初始化,且只有第一次aclInit的 JSON 配置生效:aclInit-->aclInit-->业务处理-->aclFinalize-->aclFinalize若在
aclInit前调用 1 次或多次aclFinalize,不会触发去初始化流程;若调用 N 次aclInit后调用aclFinalize的次数大于 N,多余的aclFinalize也不会触发去初始化流程。多线程场景推荐如下两种用法,否则可能导致业务异常:
主线程调用
aclInit和aclFinalize,子线程做模型推理等业务处理,主线程等待子线程业务处理结束后再调用aclFinalize:各子线程均成对调用
aclInit和aclFinalize:
模型推理(同步)场景开启 Dump:只支持在一个进程中对一个或多个模型执行 Dump,由于资源限制,其它进程不建议启动推理程序,否则可能造成 Dump 异常。若对多个模型执行 Dump,多个模型必须串行;建议单线程内对模型执行 Dump,否则可能出现 Dump 数据文件路径中的序号(
data_index)不准确,导致 Dump 数据存放目录异常。模型推理(异步)场景开启 Dump:建议一次异步推理、一次流同步,否则可能出现 Dump 数据文件路径中的序号(
data_index)不准确,导致 Dump 数据存放目录异常。
三、aclInit 配置文件的核心配置场景
aclInit的配置文件是运行时能力的总开关,以下逐一说明各配置项的写法、取值与约束。
3.1 模型 Dump 配置与单算子 Dump 配置
模型 Dump 配置用于导出模型中每一层算子的输入和输出数据;单算子 Dump 配置用于导出单个算子的输入和输出数据。导出的数据用于与指定模型或算子进行比对,定位精度问题,比对方法参见《精度调试工具用户指南》。默认不启用该 Dump 配置。
通过本接口启用 Dump 配置,需通过dump_path参数配置保存 Dump 数据的路径。模型 Dump 配置示例如下:
{ "dump":{ "dump_list":[ { "model_name":"ResNet-101" }, { "model_name":"ResNet-50", "layer":[ "conv1conv1_relu", "res2a_branch2ares2a_branch2a_relu", "res2a_branch1", "pool1" ] } ], "dump_path":"/home/output", "dump_mode":"output", "dump_op_switch":"off", "dump_data":"tensor" } }单算子调用场景下,Dump 配置示例如下:
{ "dump":{ "dump_path":"/home/output", "dump_list":[{}], "dump_op_switch":"on", "dump_data":"tensor" } }IPV350 只支持模型 Dump 配置,不支持单算子 Dump 配置。若开启模型 Dump 配置、且在模型加载时加载 exeom 文件,则 dbg 文件需存放在 JSON 配置文件中dump_path参数指定的路径下,才能生成 Dump 数据文件用于精度问题定位;exeom 与 dbg 文件在模型转换时生成,参见《ATC 离线模型编译工具》中--mode相关说明。
3.2 异常算子 Dump 配置
异常算子 Dump 配置用于导出异常算子的输入输出数据、workspace 信息、Tiling 信息等,用于分析 AI Core Error 问题,默认不启用。通过配置dump_scene参数开启,以下示例表示开启轻量化的 exception dump:
{ "dump":{ "dump_path":"output", "dump_scene":"aic_err_brief_dump" } }dump_scene参数取值说明:
aic_err_brief_dump:轻量化 exception dump,导出 AI Core 错误算子的输入&输出、workspace 数据。aic_err_norm_dump:普通 exception dump,在轻量化基础上还会导出 Shape、Data Type、Format 以及属性信息。aic_err_detail_dump(Atlas A3/A2 训练、推理系列产品,需配套 25.0.RC1 或更高版本驱动):在轻量化基础上还会导出 AI Core 的内部存储、寄存器以及调用栈信息。注意事项:- 导出 dump 文件过程中会暂停问题算子所在的 AI Core,可能影响 Device 上其它业务进程;导出完成后 AI Core 自动恢复,因此多个 Host 侧用户业务进程指定同一个 Device 的场景不建议使用该选项;
- 导出 dump 文件后,会强制退出 Host 侧用户业务进程,强制退出过程中的报错不作为 AI Core 问题分析的输入;
- 若配置后生成了 dump 文件但不是
*.core文件,说明该功能未使能成功,系统会自动切换为按aic_err_brief_dump方式 dump。
lite_exception:轻量化 exception dump,为兼容旧版本,效果等同于aic_err_brief_dump。
dump_path是可选参数,表示导出 dump 文件的存储路径,路径优先级为:NPU_COLLECT_PATH环境变量 >ASCEND_WORK_PATH环境变量 > 配置文件中的dump_path> 应用程序的当前执行目录(环境变量详细描述参见《环境变量参考》)。异常算子 Dump 配置不能与模型 Dump 配置或单算子 Dump 配置同时开启。dump 文件内容的解析方法参见《故障处理》中 msaicerr 工具使用指导的"解析 Dump 文件"章节(若配置aic_err_detail_dump,需使用 msDebug 工具查看)。
3.3 溢出算子 Dump 配置
溢出算子 Dump 配置用于导出模型中溢出算子的输入和输出数据,用于分析溢出原因、定位模型精度问题,默认不启用。将dump_debug参数设置为on开启:
{ "dump":{ "dump_path":"output", "dump_debug":"on" } }配置说明与约束:
- 不配置
dump_debug或配置为off表示不开启溢出算子配置。 - 开启溢出算子配置后,
dump_path必须配置,表示导出 dump 文件的存储路径,支持绝对路径(以/开头,如/home)或相对路径(直接以目录名开始,如output)。 - 溢出算子 Dump 配置不能与模型 Dump 配置或单算子 Dump 配置同时开启,否则返回报错。
- 仅支持采集 AI Core 算子的溢出数据。
3.4 算子 Dump Watch 模式配置
算子 Dump Watch 模式用于开启指定算子输出数据的观察模式。在定位部分算子精度问题且已排除算子本身的计算问题后,若怀疑被其它算子踩踏内存导致精度问题,可开启 Dump Watch 模式。默认不开启。
将dump_scene参数设置为watcher开启,以下示例的效果为:(1)执行完 A 算子、B 算子时,把 C 算子和 D 算子的输出 Dump 出来;(2)执行完 C 算子、D 算子时,也会把 C 和 D 算子的输出 Dump 出来。比较两组 Dump 文件,用于排查 A、B 算子是否会踩踏 C、D 算子的输出内存:
{ "dump":{ "dump_list":[ { "layer":["A", "B"], "watcher_nodes":["C", "D"] } ], "dump_path":"/home/", "dump_mode":"output", "dump_level":"op", "dump_scene":"watcher" } }配置说明与约束:
- 开启 Dump Watch 模式后,不支持同时开启溢出算子 Dump(配置
dump_debug)或单算子模型 Dump(配置dump_op_switch),否则报错;该模式在单算子 API Dump 场景下不生效。 dump_list中通过layer配置可能踩踏其它算子内存的算子名称,通过watcher_nodes配置可能被踩踏输出内存的算子名称:- 若不指定
layer,则模型内所有支持 Dump 的算子在执行后,都会把watcher_nodes中配置算子的输出 Dump 出来; layer与watcher_nodes中的算子必须是静态图、静态子图中的算子,否则不生效;- 若
layer与watcher_nodes配置的算子名称相同,或layer配置的是集合通信类算子(算子类型以Hcom开头,如HcomAllReduce),则只导出watcher_nodes中所配置算子的 dump 文件; - 对于融合算子,
watcher_nodes必须配置融合后的算子名称,配置融合前的名称不导出 dump 文件; dump_list内暂不支持配置model_name。
- 若不指定
- 开启后
dump_path必须配置;此处收集的 dump 文件无法通过文本工具直接查看,需先转换为 numpy 格式再通过 Python 查看,转换步骤参见《精度调试工具用户指南》。 dump_mode用于控制导出watcher_nodes中算子的哪部分数据,当前仅支持output。dump_level设置 dump 数据级别:op(按算子级别 dump)、kernel(按 kernel 级别 dump)、all(默认值,op 与 kernel 级别都 dump)。默认配置下 dump 数据文件较多(例如有一些aclnn开头的 dump 文件),若对 dump 性能有要求或内存资源有限,可设置为op级别以提升性能、精简文件数量。
3.5 算子 Kernel 调测信息 Dump 配置
算子 Kernel 调测信息 Dump 配置用于导出 Ascend C 算子 Kernel 的调测信息,便于定位算子问题,默认不启用。支持的型号:Ascend 950PR/Ascend 950DT、Atlas A3 训练/推理系列、Atlas A2 训练/推理系列、Atlas 200I/500 A2 推理产品、Atlas 推理系列产品。
配置dump_kernel_data参数开启:
{ "dump":{ "dump_kernel_data":"printf,assert", "dump_path":"/home/" } }配置说明与约束:
dump_kernel_data:指定导出数据的类型,支持多个类型用英文逗号隔开。若未配置该字段但启用了模型 Dump 配置、单算子 Dump 配置,则默认按all导出。支持的类型:all:导出以下所有类型调测的输出数据;printf:导出通过AscendC::printf调测的输出数据;tensor:导出通过AscendC::DumpTensor调测的输出数据;assert:导出通过assert/ascendc_assert调测的输出数据;timestamp:导出通过AscendC::PrintTimeStamp调测的输出数据。
dump_path:启用该功能时必须配置,支持绝对路径或相对路径。存储路径优先级为:ASCEND_DUMP_PATH环境变量 >ASCEND_WORK_PATH环境变量 > 配置文件中的dump_path(详见《环境变量参考》)。导出的 Dump 文件无法通过文本工具直接查看,需使用show_kernel_debug_data工具解析为可读格式(参见《Ascend C 算子开发指南》)。
3.6 Profiling 采集信息配置
Profiling 采集信息配置的配置示例、说明及约束参见《性能调优工具用户指南》,默认不启用。注意:建议不要同时配置 Dump 信息和 Profiling 采集信息,否则 Dump 操作会影响系统性能,导致 Profiling 采集的性能数据指标不准确。
3.7 算子缓存信息老化配置
算子缓存信息老化配置:通过单算子模型方式执行单个算子时(aclopUpdateParams接口执行单算子除外),为节约内存和平衡调用性能,可通过max_opqueue_num参数配置"算子类型-单算子模型"映射队列的最大长度。长度达到最大时,会先删除长期未使用的映射信息及缓存中的单算子模型,再加载最新的映射信息与单算子模型。默认最大长度为 20000。
单算子模型执行是指基于图 IR 执行算子:先用 ATC 工具将 Ascend IR 定义的单算子描述文件编译成算子 om 模型文件,再调用 acl 接口加载算子模型(如aclopSetModelDir),最后调用 acl 接口执行算子(如aclopExecuteV2)。配置示例:
{ "max_opqueue_num": "10000" }配置说明与约束:
- 对于静态加载的算子(加载单算子编译成的
*.om文件,例如aclopSetModelDir),老化配置无效,不会对该部分算子信息做老化。 - 对于在线编译的算子(例如
aclopCompile、aclopCompileAndExecuteV2等),接口内部会按入参加载单算子模型,老化配置有效。若用aclopCompile编译、aclopExecuteV2执行,编译后需及时执行算子,否则算子信息可能已被老化而需要重新编译,建议改用aclopCompileAndExecuteV2编译并执行。 - 接口内部分开维护固定 Shape 和动态 Shape 算子的映射队列,最大长度都为
max_opqueue_num参数值。 max_opqueue_num的值是静态加载算子的单算子模型个数和在线编译算子的单算子模型个数的总和,因此应大于当前进程中可用的、静态加载算子的单算子模型个数,否则会导致在线编译算子的信息无法老化。
3.8 错误信息上报模式配置
错误信息上报模式配置用于控制 aclGetRecentErrMsg 接口按进程或线程级别获取错误信息,默认按线程级别。err_msg_mode取值:0 为默认值(线程级别),1 表示按进程级别。配置示例:
{ "err_msg_mode": "1" }3.9 默认 Device 配置
默认 Device 配置用于配置默认的计算设备。若同时通过 aclrtSetDevice 指定 Device,则aclrtSetDevice优先级更高。用户开启默认 Device 功能后,若需要显式创建 Context,仍需调用aclrtSetDevice,否则可能导致业务异常。
default_device处设置 Device ID,可设置为 0 或十进制正整数。调用 aclrtGetDeviceCount 获取可用 Device 数量后,Device ID 取值范围为 [0, 可用的Device数量-1]。配置示例:
{ "defaultDevice":{ "default_device":"0" } }从源码看,该配置在aclInit时由HandleDefaultDeviceAndStackSize解析并调用rtSetDefaultDeviced生效,去初始化时若启用了默认 Device,会通过rtSetDefaultDeviceId(ACL_DEFAULT_DEVICE_DISABLE)关闭(见 src/acl/aclrt_impl/acl.cpp 中aclFinalizeInternal)。
3.10 AI Core 栈空间大小配置
AI Core 栈空间大小配置用于控制进程中 Kernel 执行时为每个 AI Core 分配的栈空间大小,默认为 32KB。Ascend 950PR/Ascend 950DT 支持该配置且编译 AI Core 算子时无需打开 O0 开关;Atlas A3/A2 训练、推理系列与 Atlas 200I/500 A2 推理产品支持该配置,但编译 AI Core 算子时只有打开 O0 开关,此处配置才有效。
aicore_stack_size参数单位 Byte,取值要求:
- 必须是 16K 的整数倍,若不是则向上取整为 16K 的整数倍;
- 最小值为 32K,若传入小于 32KB 则按默认配置 32KB 处理;
- 各产品最大值:Ascend 950PR/Ascend 950DT 为 128KB;Atlas A3 训练/推理系列、Atlas A2 训练/推理系列为 192KB;Atlas 200I/500 A2 推理产品为 7680KB。
配置示例:
{ "StackSize":{ "aicore_stack_size":32768 } }3.11 SIMT 算子栈空间大小配置
SIMT(Single Instruction Multiple Thread)栈空间大小配置用于控制每个线程中 SIMT 算子的栈空间大小以及 SIMT 算子的分支(Divergence)栈空间大小,单位 Byte,仅 Ascend 950PR/Ascend 950DT 支持。
simt_stack_size:SIMT 算子每个线程的栈空间大小,默认值为 1152Byte;simt_divergence_stack_size:SIMT 算子的分支栈空间大小,默认值为 1024Byte。
两者取值都必须是 128 的整数倍,若不是,接口内部自动向上取整。配置示例:
{ "StackSize": { "simt_stack_size": 1024, "simt_divergence_stack_size": 512 } }3.12 SIMT Printf 维测空间大小配置
SIMT Printf 维测空间大小配置用于控制 SIMT 算子可以 Printf 打印的空间大小,单位 Byte,仅 Ascend 950PR/Ascend 950DT 支持。
simt_printf_fifo_size取值必须是 8 的整数倍(否则内部向上取整),默认值 2MB,最小值 1MB,最大值 64MB。配置示例:
{ "simt_printf_fifo_size": 1048576 }3.13 SIMD Printf 维测空间大小配置
SIMD(Single Instruction Multiple Data)Printf 维测空间大小配置用于控制每个 Core 上 SIMD 算子可以 Printf 打印的空间大小,单位 Byte,支持 Ascend 950PR/Ascend 950DT、Atlas A3 训练/推理系列、Atlas A2 训练/推理系列。
simd_printf_fifo_size_per_core取值必须是 8 的整数倍(否则内部向上取整),默认值 32KB,最小值 1KB,最大值 64MB。配置示例:
{ "simd_printf_fifo_size_per_core": 1048576 }四、aclFinalize:直接释放全部资源
aclError aclFinalize()功能:去初始化函数,用于释放进程内 acl 接口使用的相关资源。
默认延时:对于涉及 Device 业务日志回传到 Host 的场景,本接口默认增加 2000ms 延时(实际最大延时可达 2000ms),以确保 ERROR 级别和 EVENT 级别日志完整回传、防止丢失。可通过环境变量ASCEND_LOG_DEVICE_FLUSH_TIMEOUT取消该默认延时:
export ASCEND_LOG_DEVICE_FLUSH_TIMEOUT=0该环境变量的详细说明参见《环境变量参考》中的 "ASCEND_LOG_DEVICE_FLUSH_TIMEOUT"。
参数:无。
返回值:返回 0 表示成功,其他值表示失败,错误码参见 aclError 错误码参考。
约束:
- 应用进程退出前,应确保已调用
aclFinalize或 aclFinalizeReference 完成去初始化,否则可能导致异常(例如进程退出时有异常报错)。 - 不建议在析构函数中调用
aclFinalize或aclFinalizeReference,否则进程退出时可能因单例析构顺序未知而导致进程异常退出。
源码视角:aclFinalize的 C 层实现(src/acl/aclrt_c/common/acl_rt.c)通过ReleaseObjRef直接释放引用对象并执行DeinitHookFunc(依次GeDbgDeInit、GeFinalize、rtDeinit),与aclFinalizeImpl(src/acl/aclrt_impl/acl.cpp)中"重复去初始化返回ACL_ERROR_REPEAT_FINALIZE、最终将aclInitRefCount清零"的行为相互印证——即aclFinalize是"一键清零"式去初始化。
五、aclFinalizeReference:基于引用计数的去初始化
aclError aclFinalizeReference(uint64_t *refCount)功能:去初始化函数,内部涉及引用计数实现:aclInit每调用一次计数加一,aclFinalizeReference每调用一次计数减一,减到 0 时才真正去初始化。与aclFinalize的区别在于:调用aclFinalize会将计数清零、直接去初始化;而aclFinalizeReference适合多模块各自负责自身生命周期的场景——每个模块初始化时调用aclInit、退出时调用aclFinalizeReference,计数归零才真正释放公共资源。
参数说明:
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| refCount | 输入&输出 | 返回调用aclFinalizeReference后的引用计数;若不需要获取引用计数,可传nullptr。 |
返回值:返回 0 表示成功,其他值表示失败。
约束:与aclFinalize相同——进程退出前必须完成去初始化;不建议在析构函数中调用。
源码视角:aclFinalizeReferenceImpl(src/acl/aclrt_impl/acl.cpp)在持锁(GetAclInitMutex递归互斥锁)前提下,先回写当前计数到refCount,再分三种情况处理:计数 > 1 时减一并返回;计数 == 1 时执行aclFinalizeInternal真正释放资源;计数 < 1 时返回ACL_ERROR_REPEAT_FINALIZE。由于计数读写均在互斥锁保护下进行,因此支持多线程并发调用。
六、初始化与去初始化回调机制
回调接口用于在 ACL 初始化/去初始化阶段挂接自定义逻辑(例如统计资源、切换模式等),全部经由acl::InitCallbackManager单例统一管理(src/acl/aclrt_impl/callback_api.cpp、src/acl/aclrt_impl/init_callback_manager.cpp)。注册类型type按照功能区分,取值范围参见 aclRegisterCallbackType 枚举。
6.1 aclInitCallbackRegister:注册初始化回调
aclError aclInitCallbackRegister(aclRegisterCallbackType type, aclInitCallbackFunc cbFunc, void *userData)功能:注册初始化回调函数。若在aclInit之前调用本接口,则会在初始化时触发回调;若在aclInit之后调用,则会在注册时立即触发回调。
参数说明:
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| type | 输入 | 注册类型,按功能区分,参见 aclRegisterCallbackType。 |
| cbFunc | 输入 | 初始化回调函数,原型为typedef aclError (*aclInitCallbackFunc)(const char *configStr, size_t len, void *userData);,其中configStr与aclInit接口中的 JSON 文件内容保持一致,len表示 JSON 文件内容的长度(单位 Byte)。 |
| userData | 输入 | 待传递给回调函数的用户数据的指针。 |
返回值:返回 0 表示成功,其他值表示失败。
6.2 aclInitCallbackUnRegister:取消注册初始化回调
aclError aclInitCallbackUnRegister(aclRegisterCallbackType type, aclInitCallbackFunc cbFunc)功能:若不再需要触发初始化回调,可调用本接口取消注册。参数type、cbFunc含义同上。
返回值:返回 0 表示成功,其他值表示失败。
6.3 aclFinalizeCallbackRegister:注册去初始化回调
aclError aclFinalizeCallbackRegister(aclRegisterCallbackType type, aclFinalizeCallbackFunc cbFunc, void *userData)功能:注册去初始化回调函数。在aclFinalize之前调用本接口,去初始化时触发回调。
参数说明:
| 参数名 | 输入/输出 | 说明 |
|---|---|---|
| type | 输入 | 注册类型,参见 aclRegisterCallbackType。 |
| cbFunc | 输入 | 去初始化回调函数,原型为typedef aclError (*aclFinalizeCallbackFunc)(void *userData);。 |
| userData | 输入 | 待传递给回调函数的用户数据的指针。 |
返回值:返回 0 表示成功,其他值表示失败。
6.4 aclFinalizeCallbackUnRegister:取消注册去初始化回调
aclError aclFinalizeCallbackUnRegister(aclRegisterCallbackType type, aclFinalizeCallbackFunc cbFunc)功能:若不再需要触发去初始化回调,可调用本接口取消注册。
返回值:返回 0 表示成功,其他值表示失败。
6.5 源码中的回调派发顺序
从 src/acl/aclrt_impl/acl.cpp 可以看到,初始化时aclInitImpl按固定顺序派发回调:ACL_REG_TYPE_ACL_MODEL(模型模块)→ACL_REG_TYPE_ACL_OP_EXECUTOR(算子执行器)→ACL_REG_TYPE_ACL_DVPP(DVPP 模块)→ACL_REG_TYPE_OTHER(其他),且各回调都会收到与aclInit配置一致的configStr与长度。去初始化时aclFinalizeInternal的派发顺序为:ACL_REG_TYPE_ACL_OP_COMPILER→ACL_REG_TYPE_ACL_MODEL→ACL_REG_TYPE_ACL_DVPP→ACL_REG_TYPE_OTHER。这也解释了回调接口中configStr参数的设计来源——初始化回调天然可以感知aclInit传入的配置内容,从而按配置决定行为。
七、实践要点总结
- 初始化前置:任何 acl 接口调用前必须先
aclInit,配置无需调整时传入NULL或空 JSON{}即可。 - 单模块进程:使用
aclInit+aclFinalize的简单配对,注意重复调用aclInit返回的ACL_ERROR_REPEAT_INITIALIZE可以忽略。 - 多模块/多线程进程:优先使用
aclInit+aclFinalizeReference的引用计数模式,各模块成对调用、顺序或并发均可;使用aclFinalize时则必须保证顺序调用且只调用一次真正去初始化。 - 配置一致性:进程内多次
aclInit的配置内容必须保持一致,否则后续调用返回ACL_ERROR_INVALID_PARAM或配置不生效。 - Dump 与 Profiling 互斥:异常算子 Dump、溢出算子 Dump、Dump Watch 模式与模型/单算子 Dump 之间均存在互斥或配合约束;Dump 与 Profiling 不建议同时开启。
- 进程退出前必须去初始化,且不要在析构函数中调用
aclFinalize/aclFinalizeReference。 - 日志完整性:如无特殊要求,保留
aclFinalize默认的 2000ms Device 日志回传延时;仅在确认可接受日志丢失风险时设置ASCEND_LOG_DEVICE_FLUSH_TIMEOUT=0取消。 - 回调挂接:利用
aclInitCallbackRegister/aclFinalizeCallbackRegister在初始化/去初始化阶段注入自定义逻辑,注意初始化回调注册晚于aclInit时会立即触发。
以上接口的完整声明与配套数据类型可在仓库头文件 include/external/acl/acl_base_rt.h、include/external/acl/acl.h 中查看,实际应用示例可参考 example/0_quickstart/0_hello_cann/main.cpp 中aclInit/aclFinalize的调用方式,以及 docs/zh/quick_start/Runtime_overview.md 对运行时生命周期的整体描述。
【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考