news 2026/9/20 14:21:27

CANN Runtime 对外 ACL 日志接口实战:acllog 系列 API 可运行样例全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CANN Runtime 对外 ACL 日志接口实战:acllog 系列 API 可运行样例全解析
  • CANN
  • Ascend
  • 人工智能
  • 任务调度

【免费下载链接】runtime

本项目提供CANN运行时组件和维测功能组件。

项目地址:https://gitcode.com/cann/runtime
点击查看免费下载

本篇文章以 CANN/runtime 仓库中 example/5_performance/log 目录下的 ACL 日志样例为骨架,完整讲解对外 ACL 日志接口(acllogRecordacllogVaListacllogCheckDebugLevelacllogRegisterCallbackacllogUnregisterCallback)的声明含义、日志级别与掩码机制、回调注册流程,并结合 main.cpp 源码与 run.sh 构建脚本给出可直接复现的运行方案。读完本文,你将掌握如何在自有模块中接入 CANN 的 ACL 日志通道,将调试日志、运行日志定向输出,并注册自定义回调对设备侧日志进行实时旁路。

一、样例概览:log 目录的定位与组成

example/5_performance/log是 CANN Runtime 对外 ACL 日志接口的可运行样例目录。目录级 README.md 说明其职责是“提供对外 ACL 日志接口的可运行样例,并通过目录级脚本输出统一的成功或失败结果”。整个目录包含以下内容:

  • 0_acl_log:覆盖acllogRecordacllogVaListacllogCheckDebugLevelacllogRegisterCallbackacllogUnregisterCallback五个接口的核心用法;
  • CMakeLists.txt:目录级 CMake 工程,负责收集 CANN 安装路径并下发子目录构建;
  • run.sh:目录级统一脚本,完成环境解析、构建、运行与结果校验,返回值为 0 表示全部步骤成功,非 0 表示构建或运行失败;
  • 0_acl_log/main.cpp:样例主体程序,演示调试日志、运行日志、va_list日志记录以及设备日志回调的注册与注销。

该样例属于性能与可观测性(performance/log)示例家族,核心价值在于:用户模块无需关心日志平台内部实现,仅通过公开头文件 acl_log.h 声明的 5 个接口即可把日志写入 CANN 日志体系,同时可获取调试级别开关状态以做日志开销裁剪。

二、对外 ACL 日志接口全景:头文件声明逐项解读

所有对外 ACL 日志接口均声明在 include/dfx/base/acl_log.h 中,头文件通过LOG_FUNC_VISIBILITY宏(定义于 include/dfx/base/log_types.h,非 Windows 平台展开为__attribute__((visibility("default"))))将符号导出为默认可见,调用方仅需#include "acl_log.h"并链接libascendalog.so即可。

2.1 回调句柄与输出类型

typedef uintptr_t acllogCallbackHandle; typedef enum { OUTPUT_TYPE_DEBUG = 0, OUTPUT_TYPE_RUN = 1, OUTPUT_TYPE_BOTH = 2, OUTPUT_TYPE_MAX } acllogOutputLogType;
  • acllogCallbackHandleuintptr_t表示回调句柄,由注册接口回填,注销时原样传回;
  • acllogOutputLogType决定回调接收哪类日志:OUTPUT_TYPE_DEBUG(仅调试日志)、OUTPUT_TYPE_RUN(仅运行日志)、OUTPUT_TYPE_BOTH(两类都接收)。样例中注册回调时传入OUTPUT_TYPE_BOTH,与日志接口按掩码区分调试/运行日志的机制对应。

2.2 五个核心接口签名

接口签名用途
acllogRegisterCallbackint32_t (acllogRecordCallback callbackFunc, void* userData, uint32_t outputLogType, acllogCallbackHandle* callbackHandle)注册设备日志记录回调,回调被触发时把日志内容转发给调用方
acllogUnregisterCallbackint32_t (acllogCallbackHandle callback)按句柄注销已注册的回调
acllogRecordvoid (int32_t moduleId, int32_t level, const char* fmt, ...)以格式化字符串方式记录日志,声明带format(printf, 3, 4)属性,编译期可校验格式串
acllogVaListvoid (int32_t moduleId, int32_t level, const char* fmt, va_list list)va_list方式记录日志,适用于把日志接口二次封装进可变参数函数
acllogCheckDebugLevelint32_t (int32_t moduleId, int32_t logLevel)查询指定模块在指定日志级别下调试日志是否开启,供上层做日志开销裁剪

回调函数类型定义如下:

typedef int32_t (*acllogRecordCallback)(void* userData, uint32_t outputLogType, const char* logContent, size_t length);

回调返回int32_t状态码,入参包括:注册时传入的userData、日志类型outputLogType、日志内容指针logContent与内容长度length(注意length为字节数,且内容不保证以\0结尾,样例中使用%.*s限定长度打印,这是正确的处理姿势)。

从源码结构看,acllogRecordacllogVaListacllogCheckDebugLevel三个记录/查询接口均带__attribute((weak))弱符号声明(见 acl_log.h),意味着它们属于“可选能力”:即便链接的运行时版本未导出这些符号,程序仍可正常链接,仅需在运行期判空。样例 main.cpp 正是据此在调用前做了空指针检查。

三、日志级别、掩码与模块 ID:log_types.h 中的基础概念

五个接口的levelmoduleId参数以及日志归类,都建立在 include/dfx/base/log_types.h 定义的公共常量之上。理解这些常量是正确使用 ACL 日志接口的前提。

3.1 日志级别

#define DLOG_DEBUG 0x0 // debug level id #define DLOG_INFO 0x1 // info level id #define DLOG_WARN 0x2 // warning level id #define DLOG_ERROR 0x3 // error level id #define DLOG_NULL 0x4 // don't print log

级别取值DLOG_DEBUG(0) ~DLOG_ERROR(3),DLOG_NULL(4) 表示不打印。样例中分别以DLOG_INFO记录调试日志与运行日志、以DLOG_WARN记录va_list日志,并用acllogCheckDebugLevel(kUserModuleId, DLOG_INFO)查询该级别是否使能。

3.2 日志掩码:调试日志与运行日志的分类机制

#define DEBUG_LOG_MASK (0x00010000U) // print log to directory debug #define SECURITY_LOG_MASK (0x00100000U) // print log to directory security #define RUN_LOG_MASK (0x01000000U) // print log to directory run #define STDOUT_LOG_MASK (0x10000000U) // print log to stdout

调试日志(写入 debug 目录)与运行日志(写入 run 目录)并不是通过level区分的,而是通过模块 ID 上叠加掩码。样例中:

acllogRecord(kUserModuleId, DLOG_INFO, "user debug log: %d\n", 1); acllogRecord(kUserModuleId | RUN_LOG_MASK, DLOG_INFO, "user run log: %d\n", 2);

第一条使用裸kUserModuleId记录为调试日志,第二条使用kUserModuleId | RUN_LOG_MASK(叠加0x01000000U)记录为运行日志。两条日志级别同为DLOG_INFO,却因掩码不同而进入不同的日志归类通道。相应地,注册回调时的OUTPUT_TYPE_DEBUG/OUTPUT_TYPE_RUN/OUTPUT_TYPE_BOTH正是对这一分类的消费端筛选。

3.3 模块 ID:从系统模块到用户应用

log_types.h定义了完整的模块 ID 枚举(SLOG=0、RUNTIME=7、HCCL=3、GE=45、ASCENDCL=48 等,直至INVALID_MODULE_ID=77),其中APP = 33预留给用户应用。样例并未使用 33,而是自定kUserModuleId = 0xff00(见 main.cpp),以规避与任何系统模块冲突,体现了“用户模块 ID 自行约定、避开系统枚举”的实践方式。此外还有MSG_LENGTH 1024表示单条日志最大长度,DLOG_TYPE_DEBUG = 0DLOG_TYPE_RUN = 1定义日志类型枚举,供日志落盘目录与回调类型换算使用。

四、样例源码逐段解析:一条完整日志链路的实现

0_acl_log/main.cpp 规模很小但流程完整,包含回调定义、va_list封装、注册、记录、注销五个环节。

4.1 自定义日志回调

int32_t LogCallback(void*, uint32_t outputLogType, const char* logContent, size_t length) { std::printf("[CALLBACK type=%u] %.*s", outputLogType, static_cast<int>(length), logContent); return 0; }

回调把日志类型与内容(按length精确截取)打印到标准输出。这里outputLogType的取值即前文acllogOutputLogType枚举值,可据此在回调内继续分流处理。

4.2 va_list 二次封装

void RecordWithVaList(int32_t moduleId, int32_t level, const char* format, ...) { va_list args; va_start(args, format); acllogVaList(moduleId, level, format, args); va_end(args); }

这是acllogVaList的典型使用场景:当你的业务代码需要对日志接口再做一层可变参数封装时,用va_start/va_end捕获参数列表后直接转交acllogVaList,避免重新解析格式化字符串。注意必须先va_start再调用,且成对使用va_end

4.3 主流程:注册 → 记录 → 注销

int main() { acllogCallbackHandle callbackHandle = 0; const int32_t registerResult = acllogRegisterCallback(LogCallback, nullptr, OUTPUT_TYPE_BOTH, &callbackHandle); if (registerResult != 0) { std::printf("[FAILURE] acllogRegisterCallback returned %d.\n", registerResult); return 1; } ... }

主流程先以OUTPUT_TYPE_BOTH注册回调(userDatanullptr,回调中未使用),注册失败立即以非 0 退出。随后在空指针保护下依次执行三条日志记录与一次级别查询;最后注销回调:

const int32_t unregisterResult = acllogUnregisterCallback(callbackHandle); if (unregisterResult != 0) { ... return 1; } std::printf("[SUCCESS] ACL log sample completed successfully.\n");

注销使用注册时回填的callbackHandle。整个样例的运行期行为可归纳为:

  1. 注册回调(输出类型为 BOTH)→ 打印注册结果;
  2. 记录一条调试日志(DLOG_INFO+ 裸模块 ID)→ 触发回调,类型为 DEBUG;
  3. 记录一条运行日志(DLOG_INFO+RUN_LOG_MASK)→ 触发回调,类型为 RUN;
  4. RecordWithVaListva_list记录一条DLOG_WARN日志;
  5. 查询acllogCheckDebugLevel返回的使能状态并打印;
  6. 注销回调 → 打印成功标记。

需要留意的是,第 2~5 步整体处于acllogRecord != nullptr && acllogVaList != nullptr && acllogCheckDebugLevel != nullptr的保护之下。若链接的运行时未导出这三个弱符号,程序会打印警告并仅验证回调注册/注销能力后正常结束,这正是弱符号设计带来的向前兼容性。

五、编译与运行:从环境解析到结果校验

5.1 运行前置条件

样例面向已安装 CANN 软件包的环境,0_acl_log/README.md 给出的运行方式为在 CANN 环境中执行上级目录的run.sh

source ${install_root}/cann/set_env.sh cd ${git_clone_path}/example/5_performance/log bash run.sh

其中${install_root}为 CANN 安装根目录,${git_clone_path}为本仓库克隆路径。脚本会检查构建和样例输出,失败时返回非 0 退出码。

5.2 run.sh 的执行链路

run.sh 采用set -euo pipefail严格模式,执行链路如下:

  1. 定位脚本自身目录并source ../../common/resolve_cann_env.sh
  2. 调用resolve_cann_env解析 CANN 安装路径(详见 5.3);
  3. 清理旧build目录后执行cmake -B build -DASCEND_CANN_PACKAGE_PATH="${ASCEND_INSTALL_PATH}"配置工程;
  4. 执行cmake --build build -j"$(nproc)"并行构建;
  5. 运行./build/0_acl_log/acl_log_sample并将输出同时落盘到output_msg.txt
  6. grep在输出中查找成功标记[SUCCESS] ACL log sample completed successfully.,命中则打印成功并返回 0,否则打印失败并返回 1。

即目录级 README 中“脚本返回值为 0 表示全部步骤成功,非 0 表示构建或运行失败;详细输出保存在output_msg.txt”的约定,其实现就是对样例输出文本的成功标记匹配。读者可自行把grep的成功标记替换为自定义标记以复用该骨架。

5.3 CANN 环境自动解析

example/common/resolve_cann_env.sh 是样例家族共享的环境解析脚本,其候选路径按优先级依次为:环境变量ASCEND_INSTALL_PATHASCEND_HOME_PATH${HOME}/Ascend/cann${HOME}/Ascend/ascend-toolkit/latest/usr/local/Ascend/cann/usr/local/Ascend/ascend-toolkit/latest/opt/Ascend/cann。对每个候选路径,脚本要求同时存在set_env.sh(或bin/setenv.bash)且具备 ACL 标准布局(include/acl/acl.h与对应lib64/libacl_rt.so同时存在),满足条件后导出ASCEND_INSTALL_PATHASCEND_HOME_PATHsource环境脚本。若全部路径均不可用,脚本打印已检查路径列表并提示手动source <cann_path>/set_env.shexport ASCEND_INSTALL_PATH=<cann_path>

5.4 CMake 构建细节

目录级 CMakeLists.txt 强制要求传入ASCEND_CANN_PACKAGE_PATH,未设置时FATAL_ERROR终止。子工程 0_acl_log/CMakeLists.txt 揭示了本样例的依赖关系:

add_executable(acl_log_sample main.cpp) target_include_directories(acl_log_sample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../../../include/dfx/base" "${ASCEND_CANN_PACKAGE_PATH}/include/base") target_link_libraries(acl_log_sample PRIVATE "${ASCEND_CANN_PACKAGE_PATH}/lib64/libascendalog.so")
  • 头文件搜索路径覆盖仓库内 include/dfx/base(提供acl_log.hlog_types.h)与 CANN 安装包的include/base
  • 链接的库为 CANN 安装包lib64目录下的libascendalog.so,即 ACL 日志功能库;
  • 最终生成可执行文件acl_log_sample

这一依赖关系印证了接口分层:对外头文件随仓库开源,实现库由 CANN 软件包提供,用户程序通过标准链接方式接入。

六、使用建议与注意事项

  • 日志级别与掩码配合使用:调试/运行日志的分类由模块 ID 叠加DEBUG_LOG_MASK/RUN_LOG_MASK决定,与DLOG_*级别正交。想让同一条日志进 run 目录,务必按样例写法叠加RUN_LOG_MASK0x01000000U)。
  • 回调按长度消费日志内容logContent不保证\0结尾,务必按回调传入的length处理,样例的%.*s是安全范式。
  • 弱符号判空acllogRecord/acllogVaList/acllogCheckDebugLevel为弱符号,调用前判空可保证旧版本运行时上的兼容降级。
  • 用户模块 ID 自定并避让系统枚举:系统模块 ID 从SLOG(0) 枚举到INVALID_MODULE_ID(77),用户模块建议像样例一样选用高位自定义值(如0xff00),或使用保留给用户应用的APP(33)。
  • 日志级别查询用于开销裁剪:在日志高频路径上先acllogCheckDebugLevel再决定是否拼装格式化参数,可避免无谓的字符串格式化开销。
  • 运行失败排查run.sh全部输出保存在output_msg.txt,若返回非 0,先查看该文件确认是构建失败、样例运行失败还是成功标记未命中;环境相关报错可参考resolve_cann_env.sh打印的“已检查路径列表”核对 CANN 安装位置与ASCEND_INSTALL_PATH

七、延伸阅读

  • 接口头文件:include/dfx/base/acl_log.h、include/dfx/base/log_types.h
  • 样例源码:example/5_performance/log/0_acl_log/main.cpp
  • 构建与运行脚本:example/5_performance/log/run.sh、example/common/resolve_cann_env.sh
  • 日志相关更多文档:docs/zh/log_ref(含日志总览、级别设置、日志查看等),以及环境变量 ASCEND_GLOBAL_LOG_LEVEL 与 ASCEND_MODULE_LOG_LEVEL 对日志级别控制的说明
  • CANN
  • Ascend
  • 人工智能
  • 任务调度

【免费下载链接】runtime

本项目提供CANN运行时组件和维测功能组件。

项目地址:https://gitcode.com/cann/runtime
点击查看免费下载

相关推荐

上一篇:如何评估Hermes-2-Pro-Mistral-7B-SFT性能?7个关键指标与测试方法
下一篇:如何永久保存微信聊天记录?WeChatMsg数据导出工具完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 14:20:45

RiskAgent 策略上线要等数天?TaoToken 这条模型通道这样接

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 14:19:02

Elasticsearch 9.x 中文分词:IK 插件部署与调优实战

简介&#xff1a;面向使用 Elasticsearch 9.0.2 的中文搜索场景&#xff0c;这份配套资源提供了 IK 分词插件的完整部署包。IK 作为主流中文分词方案&#xff0c;支持 ik_smart 与 ik_max_word 两种切分模式&#xff0c;前者适合搜索关键词提取&#xff0c;后者适合文本深度分析…

作者头像 李华
网站建设 2026/9/20 14:17:41

Pandas入门与实践:从安装配置到数据清洗与分组汇总

简介&#xff1a;Pandas入门与实践课件是一套面向Python数据分析初学者的教学PPT&#xff0c;聚焦Pandas在数据清洗、处理与分析中的核心应用&#xff0c;涵盖Series、DataFrame、Index等关键数据结构及缺失值处理、数据分组、拆分合并等常用操作。课件共1个pptx文件&#xff0…

作者头像 李华
网站建设 2026/9/20 14:16:14

工作流编排与原生多模态Agent:多模态任务的技术选型与实践

1. 两种方案背后的产品思路差异1.1 传统工作流编排&#xff1a;把复杂问题拆成流水线传统工作流编排的核心逻辑&#xff0c;一句话概括就是“分而治之”。它不是让一个模型从头到尾理解整个任务&#xff0c;而是把任务拆成多个原子节点&#xff0c;每个节点只做一件简单的事&am…

作者头像 李华