德承DX-1300这个型号,跑Ubuntu做边缘AI的兄弟应该不陌生。我这边最近就有个项目要把视觉检测放到工控机上,一开始图省事直接用CPU推理,结果视频流一进来CPU直接飙到90%以上,运动控制线程偶尔被抢调度,整个设备的节拍都乱了。折腾了两天,最后决定把推理任务从CPU挪到NPU上,才把负载扛下来。
这过程里最花时间的其实不是应用层,反而是NPU驱动。说实话,工控机这种东西不像普通开发板,BIOS、内核、设备树、安全启动,哪个环节不对都能卡你半天,而且官方文档写得偏简略,很多细节得自己猜。今天就把我在德承DX-1300上,给Ubuntu系统安装NPU驱动的完整过程记录下来,包括原理、命令、踩坑和排查思路,给后面要搞边缘AI部署的兄弟省点时间。
这篇内容适合几类人:一是工控机厂商的现场工程师,要在交付设备上装AI推理环境;二是做算法部署的软件工程师,对Linux内核、驱动、设备权限这些不算特别熟,但需要让模型跑在NPU上;三是纯粹对Intel NPU在Linux下的生态环境好奇的玩家。无论你属于哪一类,照着这套流程走一遍,基本能把NPU弄起来。
1. 为什么放着CPU不用,非要折腾NPU驱动
先聊聊这次为什么非得上NPU。工控机在产线上跑视觉检测,表面上看用CPU做推理也“能跑”,但实际用起来问题一堆。CPU是通用计算单元,跑一个几百万参数的模型时,矩阵运算是它的弱项,功耗高,发热大,还占用主控资源。
特别是像DX-1300这种无风扇盒子,本身散热余量有限,CPU一旦长时间满载,降频几乎是必然的。温度一高,性能反而更差,这就是个恶性循环。而NPU是专门为神经网络推理设计的专用芯片,功耗低,算力强,最关键的是它不占CPU核心,推理任务和运动控制、逻辑控制、HMI界面刷新互不干扰。
Intel Core Ultra平台内置的NPU,也就是常说的AI Boost,在Meteor Lake架构之后的处理器上比较常见。Linux下要让它工作,需要完整的驱动栈,这个栈理论上包含三层:
- 内核态驱动:负责管理设备、分配显存、提交推理任务,对应的是ivpu驱动
- 固件:NPU芯片自己跑的程序,负责执行底层计算指令,对应的是intel-npu-firmware
- 用户态运行时:给OpenVINO这些推理框架调用的接口,对应的是Level Zero runtime
这三层缺一不可。底层固件不对,设备起不来;内核驱动没编进系统,/dev/accel/accel0这个设备节点就不存在;用户态运行时版本不匹配,OpenVINO识别不到NPU设备。
说白了,驱动安装不是把某个deb包装上就完事,而是要把这三层软件对齐。这也是为什么网上很多人装完驱动,OpenVINO里的可用设备列表依然只有CPU,没有NPU。
2. 动手前先摸清家底:确认硬件平台和系统环境
工控机和消费级主板不一样,型号批次不同,CPU平台可能都不一样。DX-1300这款标配的是Intel Core Ultra平台,所以能用NPU。但不同生产批次的配置可能有差异,最稳妥的做法是在装驱动之前,先在终端里确认识别到的设备信息。
2.1 用lspci确认NPU设备是否存在
安装PCIe设备查询工具,先看系统能不能识别到这张“卡”。虽然NPU不是传统意义上的独立PCIe卡,但它会挂在一个虚拟PCIe设备下面:
sudo apt update sudo apt install pciutils -y lspci -nn | grep -i npu lspci -nn | grep -i "processing"在DX-1300上通常能看到类似这样的输出:
00:0b.0 Processing accelerators [1200]: Intel Corporation Meteor Lake NPU [8086:7d1d]如果这一行都没有,说明几种可能:BIOS里NPU被禁用了,或者你这台机器的CPU平台根本没有NPU。此时先别继续往下装驱动,查了再说。
2.2 检查Ubuntu版本和内核版本
Intel官方对NPU驱动有内核版本要求,Ubuntu 22.04默认内核是5.15,这个版本对Meteor Lake平台的NPU支持不完整,强烈建议用Ubuntu 24.04,默认内核6.8,对Core Ultra平台友好很多。
lsb_release -a uname -r我实测下来,Ubuntu 22.04 LTS + 内核6.5以上也能跑,但需要自己编译DKMS模块,过程比较折腾。如果条件允许,直接上Ubuntu 24.04 LTS最省心,这也是官方推荐的做法。
2.3 BIOS里的安全启动和VT-d设置
这一条非常关键,很多人装完驱动发现固件加载报错,最后排查半天是安全启动的问题。
Intel NPU驱动里的内核模块默认没有微软签名,如果BIOS里开了Secure Boot,系统启动时会拒绝加载未签名的模块,表现就是设备节点一直不出来,dmesg里报Operation not permitted之类的错,非常隐蔽。
进DX-1300的BIOS之后,找到Security菜单,把Secure Boot关掉。如果设备要交付给最终客户,不方便关闭安全启动,那得用机器自己的MOK(Machine Owner Key)对模块进行签名,这个流程比较繁琐,后面章节单独说。
另外建议把VT-d打开,这对后面做设备直通、更高性能的推理场景有帮助。设置完之后用F10保存重启。
2.4 把基础编译环境装好
装驱动一定会编译内核模块,编译就得有内核头文件、gcc、make、dkms。提前装好能省不少事:
sudo apt update sudo apt upgrade -y sudo apt install build-essential dkms git wget -y sudo apt install linux-headers-$(uname -r) -ylinux-headers-$(uname -r)这个包名,里面的变量会替换成当前内核版本。装完之后可以用dpkg -l | grep linux-headers确认。
3. Intel NPU驱动安装实操:官方脚本和手动兜底
安装NPU驱动,最推荐的方式是直接用Intel官方维护的linux-npu-driver仓库,里面有完整的安装脚本。GitHub仓库也可以访问,但在工控机现场如果网络不好,建议提前下载好整个仓库打包带过去。
3.1 获取官方驱动源码
cd ~ git clone https://github.com/intel/linux-npu-driver.git cd linux-npu-driver git checkout release/latest -b local/install分支这里可以看一下release列表,选最新的稳定版本。Intel对NPU驱动的迭代速度不慢,新版本往往修复不少固件加载问题,建议用最新。
3.2 分析一下官方安装脚本做了什么
先别急着执行,打开脚本看看,知道它在干什么,后面排查问题才有方向:
cat install.sh | head -n 100这个脚本的逻辑大概是:检测内核版本、安装依赖包、拉取固件、编译内核模块、注册DKMS、安装Level Zero运行时。它会把整个驱动栈一次性装好。
整个脚本大概分成几块,每一块做的事大概是这样:
- 调用
apt安装一些依赖库 - 从Intel的固件下载地址拉取
intel-npu-firmware包并安装 - 用DKMS编译ivpu内核驱动
- 安装libze相关的用户态运行时库
了解这些之后,直接跑安装。
3.3 运行一键安装脚本
最好用普通用户执行,需要root权限的地方脚本内部会调sudo,避免整个脚本都在root下跑,出问题不好定位:
cd ~/linux-npu-driver sudo ./install.sh这个过程耗时取决于网络速度,核心是在编译内核模块,几分钟到十几分钟不等。脚本执行完,输出会提示需要重启系统。
等这一步结束,先别急着验证,重启:
sudo reboot3.4 脚本执行失败时的兜底方案
一键脚本如果中途报错,别慌。最常见的错误是某个依赖包装不上,或者是网络问题导致固件包下载失败。
这时候有两种选择:一是重新执行脚本,Intel的脚本写得还算健壮,支持重复执行,已经完成的部分会自动跳过;二是手动分步装:
sudo apt install intel-npu-firmware -y这一步如果报Unable to locate package intel-npu-firmware,说明源没加好,需要在/etc/apt/sources.list.d/下确认Intel的源已经存在。没有的话手动添加Intel的repository之后再update。
内核模块编译,手动跑DKMS命令:
sudo dkms add -m intel-npu-driver -v <版本号> sudo dkms build -m intel-npu-driver -v <版本号> sudo dkms install -m intel-npu-driver -v <版本号>其中<版本号>换成实际的源码版本号,在~/linux-npu-driver/dkms.conf里能看到。
4. 驱动验证和应用对接:让模型真正跑在NPU上
重启完之后,第一步就是看系统有没有识别到NPU设备,以及能不能正常加载固件。这一步没通过,后面OpenVINO装了也白装。
4.1 检查设备节点和内核日志
在终端里执行:
ls -l /dev/accel/accel0 ls /dev/accel/正常情况能看到/dev/accel/accel0这个设备节点。如果看不到,就查内核日志:
dmesg | grep -i ivpu dmesg | grep -i npu dmesg | grep -i accel正常的启动日志里能看到ivpu驱动加载的完整过程,包括固件版本、芯片版本这些。如果这里一堆红色错误,比如failed to init、timeout,不用多想,就是固件加载失败了。
另外用clinfo看一下OpenCL层面的设备识别情况:
sudo apt install clinfo -y clinfo -l能看到类似Platform #0: Intel(R) OpenCL Graphics的输出说明用户态运行时已经装好了。如果前面Intel的Level Zero runtime没装对,这里会少一个平台。
4.2 安装OpenVINO工具套件
NPU驱动装好只是基础,应用要调用NPU还得靠推理框架。最原生支持Intel NPU的就是OpenVINO,安装方法很多,最简单的是用pip直接装:
pip install openvino如果你希望用OpenVINO工具套件做模型优化、量化这些工作,可以装完整的runtime包。在Ubuntu 24.04下还可以直接装发行版软件包,我个人习惯用pip,方便版本控制。
装完后用Python测试一下设备列表,这是最简单的验证方式:
python3在Python交互环境里输入:
from openvino import Core core = Core() print(core.available_devices)正常的输出结果是['CPU', 'NPU'],有这个NPU,就说明驱动和推理框架已经完整对接上了。如果只有['CPU'],说明驱动栈还有问题,回到第四步排查。
4.3 跑一个真实推理示例验证性能
设备列表里有NPU不代表推理就能顺利跑起来,最保险的做法是真正跑一个模型试一试。用OpenVINO自带的demo或者随便下载一个小模型:
pip install openvino-dev然后下载一个图像分类模型,编译并指定设备为NPU:
source /opt/intel/openvino_2024/setupvars.sh 2>/dev/null || true python3 -c " from openvino import Core import numpy as np core = Core() model = core.read_model('path/to/model.xml') compiled_model = core.compile_model(model, 'NPU') print('NPU推理成功') "如果路径下没有模型,也可以用OpenVINO自带的示例模型,或者直接用OpenVINO内置的一个测试模型跑一下,主要目的是确认推理请求能正常下发到NPU。
4.4 C++工程里怎么对接NPU
很多工控机应用不是Python写的,是C++写的,特别是和运动控制、视觉检测集成的老系统。C++对接NPU的思路和Python一样,也是走OpenVINO的API。
在CMakeLists.txt里加OpenVINO依赖,核心代码大同小异:
#include <openvino/openvino.hpp> ov::Core core; auto model = core.read_model("model.xml"); auto compiled = core.compile_model(model, "NPU"); auto infer_request = compiled.create_infer_request();编译的时候记得把/opt/intel/openvino/runtime/lib加到库搜索路径,否则程序起来会提示找不到libopenvino.so。这个坑很常见,Linux下运行时库路径没配好,QT程序里也是经常遇到。
5. 工控环境下常见坑与排查方法
最后的这部分,我整理了几个真实的故障场景,全部是自己在装驱动过程中或者帮朋友调试时踩过的。工控机环境和开发板不太一样,出了问题往往没有图形界面可以参考,只能靠命令行一点点排查,掌握方法比记死命令更重要。
5.1 一键脚本频繁报依赖错
很多工控机交付时系统是精简过的,Ubuntu装完后会有很多软件包缺失。install.sh跑起来之后经常报Unable to locate package xxx或者Package xxx has no installation candidate。
这种问题多半是软件源没更新,或者源里没有这个包。先执行:
sudo apt update sudo apt full-upgrade -y如果还是报错,就要看是不是Ubuntu版本太老,某些新版驱动的依赖包只有高版本仓库才有。比如OpenVINO的某些依赖在Ubuntu 24.04上是正常包,在22.04上可能就要加PPA源。
5.2 Secure Boot导致的固件加载失败
这个坑最隐蔽,症状也最像驱动没装好。现象是/dev/accel/accel0一直不出来,dmesg里报Platform now in secured mode这种错。
这种纯粹就是内核模块没通过安全启动校验。解法有三条路:
- 最简单:BIOS里关掉Secure Boot,大部分内部项目都是这么干的
- 正规点:导入MOK密钥,签内核模块
- 稳妥方案:用系统自带的
dkms配合签名工具,在安装模块时自动完成签名
第三条路适合要交付给外部客户的场景,配置一次MOK,后续内核升级也能持续生效,用户不需要碰BIOS。具体流程是在Ubuntu下安装shim-signed,然后用mokutil --import导入,重启后按提示输入密码确认信任。
5.3 固件版本和内核驱动不匹配
Intel NPU的固件迭代很快,如果手动更新过固件包,而内核驱动版本还停在老版本上,会导致设备初始化失败。dmesg里的错误信息可能是firmware image is incompatible。
这个没有捷径,只能把驱动和固件升级到同一版本。最省事的做法是把linux-npu-driver仓库重新拉最新版,再跑一次sudo ./install.sh,它会顺便把固件也更新掉。教训就是不要在工控机上用apt upgrade盲目更新系统,特别是涉及内核和固件的包,很容易把驱动环境搞崩。
5.4 系统更新后驱动失效
工控机在客户现场跑着跑着,某次重启之后NPU突然没了,查了半天大概率是系统自动更新把内核换了,而DKMS模块没在新内核上重编。
Linux内核更新之后,原来编译的内核模块不会自动带到新内核,除非配置了DKMS。这也是为什么前面安装流程里要特别强调DKMS的原因。
出现这个问题,先看当前内核版本和头文件版本:
uname -r sudo dkms status如果DKMS状态正常但模块没加载,重新执行一下:
sudo dkms autoinstall如果dkms status显示模块状态是broken,干脆删了重新加:
sudo dkms remove -m intel-npu-driver -v <版本号> --all sudo dkms autoinstall为避免现场再出状况,我习惯在交付前锁定内核版本,只做安全更新,不做内核大版本升级。工控机最重要的是稳定,新功能之类不是现场要考虑的事。
5.5 无人值守环境下的一点建议
工控机上跑模型,很多时候是无人值守的。设备开机就要自动拉起推理程序,程序崩了要自己重启。这种情况下,驱动层面的状态就很重要。我现在的习惯是在服务启动脚本里加一段自检,先检查/dev/accel/accel0是否存在,不存在就尝试重新加载模块,再不存在就发报警。
if [ ! -e /dev/accel/accel0 ]; then sudo modprobe intel_vpu sleep 2 fi这个脚本虽然简单,但现场排查问题的效率能提高不少。工控机的价值在稳定运行,与其出了问题再跑现场,不如把自检逻辑提前写好。
另外一个实际体会是,NPU驱动装完之后,尽量别动系统的内核和BIOS版本。工控机场景里,软件环境变了导致设备起不来,责任往往很难扯清楚,锁定环境版本才是最高效的交付方式。一套能跑通的驱动组合,在生产环境里用三五年不动,才是最稳妥的选择。