ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CANN opbase 中 aclnnFinalize 接口详解:单算子 API 执行框架的资源去初始化与进程安全退出

CANN opbase 中 aclnnFinalize 接口详解:单算子 API 执行框架的资源去初始化与进程安全退出 CANN opbase 中 aclnnFinalize 接口详解单算子 API 执行框架的资源去初始化与进程安全退出【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbaseaclnnFinalize 是 CANN opbase 单算子 API 执行框架aclnnXxx 系列接口中的资源去初始化函数用于在进程退出前释放 aclnn 相关资源避免因资源未释放导致系统内部错误。本文围绕该接口的功能定位、原型约束、与 aclnnInit/aclFinalize 的关系以及它在 aclnn_init.cpp 中的底层实现展开帮助开发者在 host 侧算子编排代码中正确完成 aclnn 资源的初始化与回收闭环。一、功能概述aclnnFinalize 的作用与使用场景在单算子 API 执行框架中进程调用aclnnXxx系列接口如aclnnXxxGetWorkspaceSize、aclnnXxx之前必须先调用aclnnInit完成 aclnn 资源的初始化读取环境变量、解析配置文件、加载资源库等。与之对应在进程退出前必须调用aclnnFinalize释放进程内已占用的 aclnn 相关资源否则会导致系统内部出错影响业务正常运行。aclnnFinalize的典型使用场景是 host 侧单算子调用程序的收尾阶段当一次或多次算子执行完成后、进程退出前通过一次aclnnFinalize()调用将 aclnn 框架持有的内部资源AI CPU 任务空间、Tiling 解析上下文等统一清理保证进程可以干净退出。二、函数原型与参数说明aclnnFinalize的函数原型定义如下aclnnStatus aclnnFinalize()参数无。该接口不接收任何输入参数因此调用前无需准备任何配置或上下文对象。声明位置接口声明位于 include/nnopbase/aclnn/aclnn_base.h通过ACL_FUNC_VISIBILITY导出供算子 host 侧代码以 C 接口形式调用。从原型可以看出aclnnFinalize是一个全局级接口它并不针对某个具体的算子或 Tensor而是对进程内 aclnn 框架整体状态做回收这与它的初始化对应接口aclnnInit的全局语义保持一致。三、返回值与错误码返回值含义0ACLNN_SUCCESS去初始化成功非 0去初始化失败需结合错误码定位问题返回 0 表示成功返回其他值表示失败。完整返回码列表参见 Common API Return Codes中文版见 公共接口返回码其中与本接口相关的核心返回码包括错误码值描述ACLNN_SUCCESS0成功ACLNN_ERR_PARAM_NULLPTR161001参数校验错误参数中包含无效的nullptrACLNN_ERR_PARAM_INVALID161002参数校验错误例如两个输入数据类型不满足类型推导要求ACLNN_ERR_RUNTIME_ERROR361001调用 NPU Runtime API 时发生异常ACLNN_ERR_INNER_XXX561xxx内部 API 异常如 561101 创建aclOpExecutor失败、561102 未调用uniqueExecutor ReleaseTo、561103 内部空指针需要说明的是从当前仓库的 aclnn_init.cpp 实现看aclnnFinalize目前总是返回ACLNN_SUCCESS清理过程内部异常会通过日志记录。即便如此文档仍建议在调用后检查返回值以便在后续版本或异常路径下第一时间发现问题。若需获取更详细的错误信息可调用 Runtime API 中的aclGetRecentErrMsg获取最近一次错误消息。四、与 aclnnInit 配套aclnn 资源生命周期管理aclnnFinalize必须与aclnnInit配套使用二者共同构成 aclnn 资源的初始化/去初始化闭环aclnnInit(configPath)在调用任何aclnnXxx算子接口前执行完成 aclnn 资源初始化例如读取环境变量、解析 JSON 配置文件、加载算子资源库op::opploader::LoadAllOppPackage()。aclnnFinalize()在进程退出前执行释放 aclnn 相关资源与aclnnInit形成配对。从源码看aclnnInit的实现aclnn_init.cpp依次执行op::opploader::LoadAllOppPackage()加载全部算子包再调用InitSystemConfig(configPath)完成系统配置解析而aclnnFinalize则反向执行资源回收。二者一建一拆保证 aclnn 框架内部状态在进程生命周期内完整、有序。aclnnInit的完整调用约束、configPath配置文件JSON 格式支持op_debug_config.enable_debug_kernel调试开关及配套的初始化代码示例请参见 aclnnInit 接口文档。五、aclnnFinalize 与 aclFinalize 的差异对比文档明确说明调用aclnnFinalize或aclFinalize均能实现资源去初始化但二者作用范围不同对比项aclnnFinalizeaclFinalize释放范围仅释放 aclnn 相关资源释放 acl 接口中的各类资源包含 aclnn轻量程度更轻量回收动作更少较重回收范围更广重复调用单进程内只允许一次与 aclFinalize 自身约束一致因此如果业务代码中只使用了 aclnn 单算子接口优先选择aclnnFinalize避免因调用更重的aclFinalize引入不必要的开销或依赖。文档同时指出即使两个接口都被调用也不会返回失败消息即二者并非互斥。六、底层实现原理从声明到资源回收的完整调用链aclnnFinalize的实现位于 src/nnopbase/common/api/aclnn_init.cppaclnnStatus aclnnFinalize() { op::internal::aclnnAicpuFinalize(); op::internal::gKernelMgr.ReleaseTilingParse(); return ACLNN_SUCCESS; }整个去初始化过程分为两个阶段AI CPU 任务空间清理与Tiling 解析上下文释放。下面结合源码逐一展开。6.1 阶段一AI CPU 任务空间清理aclnnAicpuFinalizeop::internal::aclnnAicpuFinalize()的实现位于 src/nnopbase/aicpu/task_handler/aicpu_task_base.cppvoid aclnnAicpuFinalize() { OP_LOGD(Entering func: aclnnAicpuFinalize, size%zu., gAicpuTaskSpaceSet.size()); const std::lock_guardstd::mutex lk(gAicpuTaskSpaceMutex_); for (auto space : gAicpuTaskSpaceSet) { if (space ! nullptr) { space-Clear(); } } gAicpuTaskSpaceSet.clear(); OP_LOGD(Leaving func: aclnnAicpuFinalize); }该函数在gAicpuTaskSpaceMutex_互斥锁保护下遍历全局gAicpuTaskSpaceSet集合中的每个 AI CPU 任务空间对象并调用其Clear()方法最后清空整个集合。这样在算子执行过程中通过SaveAicpuTaskSpace保存下来的任务空间都会被逐一回收避免内存与设备侧资源泄漏。该接口在 aicpu_task.md 中被登记为AI CPU 模块去初始化函数。6.2 阶段二Tiling 解析上下文释放ReleaseTilingParseop::internal::gKernelMgr.ReleaseTilingParse()的实现位于 src/nnopbase/common/inc/kernel_mgr.hvoid ReleaseTilingParse() { for (size_t i 0; i kernel_.size(); i) { kernel_[i].ReleaseTilingParse(); } }内核管理器KernelMgr遍历其管理的全部OpKernel逐一释放各自的 Tiling 解析上下文。OpKernel::ReleaseTilingParse的实现位于 src/nnopbase/composite_op/aclnn_engine/op_kernel.h遍历该算子二进制对应的OpKernelBin集合对其持有的TilingParseCtxHolder依次执行ReleaseTilingParse()从而释放算子 Tiling 解析阶段缓存的内存资源。6.3 从源码结构可推断的实现要点aclnnFinalize本身不接收参数、不依赖具体算子属于框架级收口函数其两个清理动作分别覆盖AI CPU 侧任务空间与host 侧 Tiling 解析缓存两条资源链。清理动作以幂等方式设计即使进程内没有任何算子执行记录遍历空集合也不会出错这保证了接口调用的安全性。单进程内只允许调用一次的限制与gAicpuTaskSpaceSet等全局集合的一次性清空语义一致二次调用时集合已为空清理对象不复存在。七、调用示例aclnnFinalize本身无独立示例其调用通常出现在完整的单算子调用流程末尾。以下代码摘自 aclnnInit 接口文档 的调用示例仅作流程参考不可直接复制执行// 1. 初始化资源。 auto ret aclnnInit(/home/acl.json); ... // 2. 创建算子 API 参数对象。 ret aclCreate***(...); ... // 3. 调用两段式算子接口。 ret aclnnXxxGetWorkspaceSize(...); ret aclnnXxx(...); ... // 4. 销毁算子 API 参数对象。 ret aclDestroy***(); ... // 5. 去初始化资源本接口主题。 ret aclnnFinalize();流程要点先初始化任何aclnnXxx调用前必须先执行aclnnInit可传NULL或 JSON 配置文件路径参数对象有借有还aclCreate***创建的 Tensor、Scalar、数组等参数对象在使用完毕后调用aclDestroy***释放最后收口所有算子执行与对象销毁完成后调用aclnnFinalize()释放 aclnn 框架级资源再让进程退出。八、使用约束与最佳实践必须与 aclnnInit 配套使用aclnnFinalize需与aclnnInit配对分别完成 aclnn 资源的初始化与去初始化不可单独使用。单进程内只能调用一次一个进程中只允许调用一次aclnnFinalize不支持重复调用aclnnInit同样只允许调用一次二者应遵循严格的一建一拆顺序。优先选择轻量接口若业务仅依赖 aclnn 单算子接口使用aclnnFinalize而非aclFinalize可缩小资源释放范围、降低收尾开销两者同时调用也不会报错。在进程退出路径上保证调用应在主流程正常结束与异常退出的公共出口处确保aclnnFinalize被调用否则进程持有的 aclnn 资源未释放可能导致系统内部错误。检查返回值尽管当前实现总是返回成功仍建议检查返回值并配合aclGetRecentErrMsg排查异常。九、相关文档与延伸阅读初始化对应接口aclnnInit含 JSON 配置文件与两段式调用完整示例返回码定义Common API Return Codes接口总览00_aclnn_api_list.md底层实现aclnn_init.cpp、aicpu_task_base.cpp、kernel_mgr.h、op_kernel.h单元测试验证tests/nnopbase/ut/composite_op/test_acl_op_api.cpp 中的aclnnInit/aclnnFinalize用例后者直接断言aclnnFinalize()返回ACLNN_SUCCESS以及 ST 侧 tests/nnopbase/st/composite_op/test_acl_op_api.cpp 中的同名用例可作为接口行为的最小可验证参考。【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表