前言

CANN(Compute Architecture for Neural Networks)作为一套面向 AI 加速硬件的全栈异构计算平台,其 runtime 层不仅承担任务调度、内存管理、设备控制等核心职责,还集成了强大的维测功能组件(Diagnostics and Measurement Components)。这些组件为开发者提供了从模型精度异常、算子崩溃到系统级性能瓶颈的端到端可观测能力,是保障 AI 应用稳定高效运行的关键基础设施。

一、维测功能组件的整体架构与定位

根据 runtime/README.md 的描述,维测功能组件包含以下三个核心子系统:

  • adump:提供单算子或整网模型的输入/输出数据 Dump 能力,用于精度比对与异常定位;
  • msprof:性能调优工具,采集 AI 任务执行过程中的关键性能指标(如指令周期、内存带宽、Cache 命中率);
  • log:日志记录与设备侧状态导出模块,包含 msnpureport 命令行工具,支持查询设备日志、错误码、寄存器状态等。

这些模块均以内嵌形式集成于 runtime 核心库中,并通过统一的配置接口(如环境变量、API 参数)激活,无需修改用户业务代码即可启用。

注:尽管维测功能依赖底层驱动支持,但本文聚焦于 runtime 仓库自身实现,不涉及 driver 层细节。


二、adump:精度问题的“显微镜”

当 AI 模型在目标硬件上出现精度下降或数值异常时,adump 模块可精确捕获指定算子或整个网络的中间张量数据,供开发者与 CPU/GPU 参考结果进行比对。

2.1 触发机制与配置方式

adump 支持两种触发模式:

  • 主动 Dump:通过 API 或配置文件指定要 Dump 的算子名称、Tensor 名称;
  • 异常 Dump:当 runtime 捕获到硬件异常(如非法地址访问、浮点溢出)时,自动 Dump 异常算子的输入/输出及 Workspace 数据。

配置主要通过环境变量完成:

export ASCEND_SLOG_PRINT_TO_STDOUT=1
export DUMP_MODE="all"                # all / specific
export DUMP_OP_NAME="MatMul_0"        # 若为 specific 模式
export DUMP_PATH="/home/user/dump"

2.2 数据格式与存储结构

Dump 数据以 Protobuf + NPY 混合格式存储,兼顾结构化元信息与高效数值存储:

dump/
├── model_name/
│   ├── graph_0/
│   │   ├── op_MatMul_0/
│   │   │   ├── input_0.npy
│   │   │   ├── output_0.npy
│   │   │   └── tiling_info.pb
│   │   └── ...
│   └── dump_config.json

其中 tiling_info.pb 记录了算子分块(Tiling)策略,对理解 NPU 上的执行逻辑至关重要。

2.3 源码实现:拦截算子执行路径

adump 的核心在于在算子 Kernel 执行前后插入 Dump 钩子。相关代码位于 src/dfx/adump/ 目录。

AdumpManager::DumpTensor() 为例:

// src/dfx/adump/adump_manager.cpp
Status AdumpManager::DumpTensor(const std::string& op_name,
                                const std::string& tensor_name,
                                const void* data, size_t size,
                                const TensorDesc& desc) {
    if (!IsDumpEnabled(op_name)) return SUCCESS;

    // 构造文件路径
    std::string filepath = GetDumpPath() + "/" + op_name + "/" + tensor_name + ".npy";

    // 将 data 转换为 NPY 格式并写入
    NpyWriter writer(filepath);
    RETURN_IF_ERROR(writer.Write(data, desc.shape, desc.data_type));

    // 记录元信息到日志
    LOG(INFO) << "Dumped tensor " << tensor_name << " of op " << op_name;
    return SUCCESS;
}

该函数由 runtime 在 aclnnLaunchOp 等算子调度接口中调用,确保在 Kernel 启动前 Dump 输入,在回调完成后 Dump 输出。

最新提交(2026年1月)优化了 Dump 文件的 I/O 性能,避免大模型场景下磁盘写入成为瓶颈。


三、msprof:性能剖析的“雷达系统”

msprof 是 CANN runtime 提供的性能剖析工具,支持对 AI 任务进行全栈性能数据采集,涵盖 Host 侧(CPU)、Device 侧(NPU)以及通信链路。

3.1 三层性能数据模型

msprof 定义了清晰的性能事件层级:

层级 内容 采集方式
Host Layer Python/PyTorch 调用栈、API 耗时 插桩(Instrumentation)
Runtime Layer 内存分配、流同步、任务提交延迟 runtime 内部计时器
Device Layer AI Core 指令周期、L2 Cache 命中率、DDR 带宽 硬件性能计数器(PMU)

3.2 动态剖析(Dynamic Profiling)流程

msprof 支持“运行时开启/关闭”的动态剖析模式,适用于长时间训练任务:

# 启动剖析服务
msprof --dynamic start

# 运行业务程序
python train.py

# 停止剖析并生成报告
msprof --dynamic stop --output ./profile_data

其内部通过 Unix Domain Socket 与 runtime 中的 Profiler Daemon 通信。

3.3 性能事件注册与采样

关键代码位于 src/dfx/msprof/。性能事件通过 MsprofRegisterEvent() 注册:

// src/dfx/msprof/profiler_api.cpp
void MsprofRegisterEvent(const char* event_name, MsprofEventType type) {
    auto& profiler = MsprofCore::GetInstance();
    profiler.RegisterEvent(event_name, type);
}

// 在算子执行前后插入事件
void LaunchOpWithProfiling(...) {
    MsprofBeginEvent("MatMul_0");
    aclrtLaunchKernel(...);
    MsprofEndEvent("MatMul_0");
}

对于 Device 层事件,runtime 通过 ioctl 向驱动请求启动 PMU 采样,采样数据以环形缓冲区形式返回。

3.4 报告生成与可视化

采集结束后,msprof analyze 命令将原始数据转换为多种格式:

  • JSON:供自动化分析脚本使用;
  • HTML Trace Viewer:类似 Chrome DevTools 的时间线视图;
  • Flame Graph:展示函数调用栈的 CPU/NPU 时间分布。

2025 年底的 PR #380 新增了对 多设备同步时间戳 的支持,确保多卡训练场景下的事件对齐。


四、log 与 msnpureport:设备状态的“黑匣子”

当系统发生严重故障(如设备挂死、驱动崩溃)时,常规日志可能无法获取。log 模块结合 msnpureport 工具,提供了从设备固件层提取关键状态的能力。

4.1 日志分级与输出控制

runtime 日志采用五级分类(DEBUG/INFO/WARNING/ERROR/FATAL),通过环境变量控制输出:

export ASCEND_GLOBAL_LOG_LEVEL=3  # 3=WARNING, 仅输出警告及以上
export ASCEND_SLOG_PRINT_TO_STDOUT=1  # 同时输出到 stdout

日志内容包含:

  • API 调用参数与返回码;
  • 内存分配/释放记录;
  • 流(Stream)与事件(Event)状态变更;
  • 驱动交互错误码。

4.2 msnpureport:设备侧状态导出

msnpureport 是一个独立命令行工具,位于 src/dfx/log/msnpureport/,可直接与设备固件通信:

# 导出设备0的全部日志
msnpureport -g -d 0 > device0.log

# 查询设备健康状态
msnpureport -q health -d 0

# 获取最后发生的错误码
msnpureport -q error_code -d 0

其底层通过 /dev/davinciX 的特殊 ioctl 命令(如 DRIVER_CMD_GET_FW_LOG)读取固件日志缓冲区。

4.3 错误码映射与根因分析

runtime 维护了一套完整的错误码映射表(src/include/acl/acl_base.h):

// 常见错误码示例
#define ACL_ERROR_RT_AICORE_OVERFLOW        (-1073741823)  // AI Core 浮点溢出
#define ACL_ERROR_RT_MEMORY_ALLOCATION      (-1073741822)  // 内存分配失败
#define ACL_ERROR_DRV_DEVICE_LOST           (-1073741821)  // 设备丢失(可能过热或掉电)

当应用捕获到 aclError 时,可结合 msnpureport 输出的设备日志,快速定位是软件配置错误还是硬件异常。


五、维测组件的协同工作流程

在实际故障排查中,三大组件往往协同使用。以下是一个典型场景:

问题:某 Transformer 模型在推理时偶发输出全零。

排查步骤

  1. 启用 adump,Dump 异常样本对应的 Attention 算子输入/输出;
  2. 发现某次 MatMul 输出全为 Inf,怀疑数值溢出;
  3. 使用 msprof 采集该批次的性能数据,确认无硬件 stall;
  4. 检查 runtime 日志,发现 ACL_ERROR_RT_AICORE_OVERFLOW 错误;
  5. 运行 msnpureport -q error_code,确认设备侧记录相同错误码;
  6. 结论:模型权重或输入数据存在极端值,需在预处理阶段增加裁剪。

此流程体现了 CANN 维测体系“数据驱动、层层下钻”的设计理念。


六、本地验证与 UT 测试机制

runtime 仓库提供了完整的单元测试(UT)框架,验证维测功能正确性。

例如,adump 的 UT 用例位于 tests/ut/dfx/adump/

// tests/ut/dfx/adump/adump_test.cpp
TEST_F(AdumpTest, DumpTensorSuccess) {
    SetEnv("DUMP_MODE", "specific");
    SetEnv("DUMP_OP_NAME", "TestOp");
    SetEnv("DUMP_PATH", "/tmp/test_dump");

    // 模拟算子执行
    void* data = malloc(1024);
    AdumpManager::GetInstance().DumpTensor("TestOp", "input_0", data, 1024, desc);

    // 验证文件是否存在
    EXPECT_TRUE(FileExists("/tmp/test_dump/TestOp/input_0.npy"));
    free(data);
}

msprof 的 UT 则通过 Mock Profiler Daemon 验证事件注册与时间戳精度。

2026 年初的提交优化了 UT 的覆盖率统计,确保维测路径被充分测试。


七、总结

CANN runtime 的维测功能组件(adump、msprof、log)构成了一个立体化、多层次的可观测性体系。它不仅支持传统的日志记录,更通过精准数据 Dump、硬件级性能采样、设备状态直连等手段,将“黑盒”AI加速过程变为“白盒”。这种设计极大降低了开发者在复杂异构环境下的调试成本,尤其在大模型、多卡训练等高价值场景中,其价值尤为凸显。

随着 CANN 生态的持续演进,维测组件将进一步融合 AI 编译器(GE)的图优化信息、支持更细粒度的 Tile 级性能剖析,并探索与云原生日志系统(如 Prometheus + Grafana)的集成,为 AI 应用的稳定高效运行保驾护航。


相关链接:

Logo

昇腾计算产业是基于昇腾系列(HUAWEI Ascend)处理器和基础软件构建的全栈 AI计算基础设施、行业应用及服务,https://devpress.csdn.net/organization/setting/general/146749包括昇腾系列处理器、系列硬件、CANN、AI计算框架、应用使能、开发工具链、管理运维工具、行业应用及服务等全产业链

更多推荐