昇腾 NPU 是面向 AI 训练与推理场景的异构计算硬件,应用开发过程离不开 NPU 驱动栈与工程构建体系。很多开发者在移植算子、编译 AscendCL 应用时,会遇到头文件找不到、库链接失败、驱动版本不匹配、make 编译报错等问题。本文从 NPU 驱动栈分层原理、核心组件、Makefile 编译依赖配置、常见编译报错、版本匹配五个维度,讲解昇腾 NPU 驱动原理以及 make 工程的依赖配置方法,帮助开发者快速完成 NPU 应用编译、调试与部署。

一、昇腾 NPU 驱动栈基础原理

昇腾 Davinci 架构 NPU 采用用户态‑内核态分离的驱动架构,完整驱动栈分为:硬件层、内核驱动层、Runtime 运行时层、AscendCL 应用接口层、上层业务应用层。

  1. 硬件层 AI Core、Vector Core、Tensor Block、多级片上缓存 L1/L2/L3、设备 DDR 内存,承担矩阵计算、向量运算、数据缓存,是算力载体。硬件本身不直接接受用户程序指令,全部请求经由驱动转发调度。

  2. 内核态驱动(kernel driver) 部署在 Linux 内核空间,主要模块:

  • 设备驱动模块:完成 NPU 硬件设备初始化、中断处理、寄存器读写、硬件异常上报;

  • 内存管理模块:设备物理内存申请、释放、主机与设备之间内存 DMA 搬运;

  • 任务调度模块:接收 Runtime 下发的任务,把算子任务分发到各个 AI Core 硬件单元执行;

内核驱动运行在内核空间,普通用户进程不能直接访问硬件寄存器,所有硬件操作必须通过驱动提供字符设备接口转发。

  1. Runtime 运行时层(aclrt,用户态) 属于 AscendCL 运行时库,运行在用户空间,向上给应用提供设备管理、内存管理、流、事件、任务提交接口;向下封装对内核驱动字符设备的 ioctl 调用。 核心能力:

  • 设备初始化、设置设备、复位设备;

  • Host/Device 内存申请释放,Host‑Device 数据拷贝;

  • 流(stream)管理,异步任务下发;

  • 同步事件、错误状态查询。

前文 GEMM 示例代码中aclInit、aclrtSetDevice、aclrtMallocHost全部属于 Runtime 接口。

  1. AscendCL 接口层 基于 Runtime 封装算子管理、模型加载、数据类型、算子内核调用接口,供应用程序直接调用,头文件为acl/acl.h。

  2. 上层业务应用层 开发者编写的业务代码,例如 GEMM 算子程序、推理程序,通过链接libacl.so库,调用 AscendCL 接口实现 NPU 计算。

数据调用流程 业务应用 → AscendCL API → aclrt Runtime 库 → ioctl 系统调用 → NPU 内核驱动 → NPU 硬件执行计算 → 结果 DMA 回传主机内存。

二、驱动相关核心文件分布

安装完昇腾 CANN 套件后,驱动、头文件、动态库分布在工具链目录:/usr/local/Ascend/ascend‑toolkit/latest/

目录

作用

include/

AscendCL 头文件,acl/acl.h等全部在这里,编译阶段需要‑I 指定该路径

lib64/

运行时动态库:libacl.so、libascend_runtime.so,链接阶段需要‑L 指定库路径

driver/

NPU 内核驱动 ko 模块,需要 root 权限加载到系统内核

注意:内核驱动是独立组件,CANN toolkit 提供编译好的用户态库,不包含内核驱动,内核驱动需要单独安装驱动包。toolkit 版本必须和 NPU 内核驱动版本严格匹配,版本不一致会出现初始化失败、设备不可用。

三、Makefile 编译依赖完整示例

gcc 单命令编译适合简单 demo;工程化项目一般使用 Makefile 管理编译。下面提供适配 NPU AscendCL 程序的完整 Makefile,以上文 GEMM 代码gemm_ascend.c为例。

# Makefile for Ascend NPU acl demo
CC ?= gcc
TARGET := gemm_ascend
SRC := gemm_ascend.c

# CANN工具链根路径,根据实际安装路径修改
ASCEND_TOOLKIT := /usr/local/Ascend/ascend-toolkit/latest

# 头文件搜索路径
INC := -I$(ASCEND_TOOLKIT)/include
# 库文件搜索路径
LIBPATH := -L$(ASCEND_TOOLKIT)/lib64
# 链接依赖库,acl封装runtime能力
LIBS := -lacl

# 编译优化选项,建议开启O3
CFLAGS := -O3 -Wall $(INC)
LDFLAGS := $(LIBPATH) $(LIBS)

all: $(TARGET)

$(TARGET): $(SRC)
	$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)

clean:
	rm -f $(TARGET)

执行编译命令

make

运行前环境准备(非常关键)

程序运行时系统需要找到动态链接库libacl.so,两种配置方式:

  1. 临时设置 LD_LIBRARY_PATH 环境变量

export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/lib64:$LD_LIBRARY_PATH
./gemm_ascend
  1. 写入系统 ld 配置(永久生效,root 权限)

echo "/usr/local/Ascend/ascend-toolkit/latest/lib64" >> /etc/ld.so.conf.d/ascend.conf
ldconfig

若没有配置 LD_LIBRARY_PATH,执行程序会报错:error while loading shared libraries: libacl.so cannot open shared object file。

四、关键编译依赖说明

  1. 头文件依赖(编译阶段) ‑I指向ascend‑toolkit/include,否则编译报错 fatal error: acl/acl.h: No such file or directory。

只安装 NPU 内核驱动,没有安装 CANN toolkit,会缺少 acl 头文件,代码无法编译。内核驱动只负责硬件调度,不提供用户态 API 头文件。

  1. 库链接依赖(链接阶段) ‑L指定 lib64 库目录,‑lacl链接 AscendCL 主库,内部会自动依赖 runtime 底层库。

链接阶段找不到库报错:cannot find ‑lacl,检查‑L路径是否正确。

  1. 运行时依赖(执行阶段) 运行时依赖两件事: ① 系统已经加载对应版本 NPU 内核驱动 ko,NPU 设备正常识别; ② 动态链接器可以找到libacl.so等 so 库(LD_LIBRARY_PATH /ldconfig); ③ 用户具备 NPU 设备访问权限,一般需要加入HwHiAiUser用户组。

  2. 版本匹配约束(高频踩坑)

  • NPU 内核驱动版本 ≡ CANN ascend‑toolkit 版本;

  • toolkit 版本高于驱动版本:aclInit 会返回错误码,设备初始化失败;

  • toolkit 版本低于驱动版本:部分新接口缺失,编译或运行异常。

查看版本命令:

#查看toolkit版本
cat /usr/local/Ascend/ascend-toolkit/latest/version.info
#查看npu驱动版本
npu-smi info

五、常见问题与排错建议

  1. 编译报错:acl/acl.h 找不到

  • 原因:Makefile 的 INC 路径配置错误,没有安装 CANN Toolkit。

  • 处理:确认 toolkit 完整安装,核对 Makefile 中 ASCEND_TOOLKIT 路径。

  1. 链接报错:cannot find -lacl

  • 原因:lib64 目录下 libacl.so 不存在,‑L 库路径写错。

  • 处理:检查路径,确认 toolkit 完整安装。

  1. 编译成功,运行时:libacl.so: cannot open shared object

  • 原因:动态链接器找不到 so 库。

  • 处理:配置 LD_LIBRARY_PATH 或者更新系统 ldconfig 缓存。

  1. 运行时 aclInit 返回失败,无法打开 NPU 设备

  • 原因:①内核驱动未加载;②驱动版本与 toolkit 版本不一致;③用户无 NPU 设备权限。

  • 处理:使用npu‑smi info确认 NPU 设备正常,核对版本,将用户加入 HwHiAiUser 用户组。

  1. make 编译时,交叉编译场景 如果是 ARM 平台交叉编译 NPU 程序,需要使用对应架构 toolkit 的 lib64‑aarch64 库,CC 替换为 aarch64‑linux‑gnu‑gcc。

六、总结

昇腾 NPU 整套体系分为内核驱动和CANN Toolkit 用户态 SDK两部分,二者职责分离:内核驱动负责硬件调度;CANN Toolkit 提供头文件、动态库,用于业务代码编译开发。

使用 Makefile 构建 NPU 应用时,编译阶段依赖 Toolkit 的 include 头文件目录;链接阶段依赖 lib64 动态库目录;程序运行阶段,既需要系统加载匹配版本 NPU 内核驱动,又要保证操作系统动态链接器可以找到 AscendCL 运行时库。开发过程中版本匹配、环境变量配置是最容易出错的环节,调试时优先确认npu‑smi info设备状态与版本信息,再定位编译与运行报错。

实际项目开发,建议基于 Makefile 管理编译参数,统一封装头文件路径、库路径,避免每次手动输入长 gcc 编译命令,提升工程可移植性。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐