1. 装驱动前,先把这三件事做对
1.1 确认硬件型号和服务器环境
华为Atlas 300I推理卡的驱动安装,看着只是“跑一个安装包”的事,实际动手时坑比想象中多。我前后在昇腾环境上装过几十次驱动,从最开始照着文档一步步敲命令,到后来闭着眼睛也能判断问题出在系统环境还是包本身,中间踩过的坑包括内核头文件缺失、DKMS没装、固件版本和驱动不配套、重启后设备节点消失……如果你正准备给服务器装Atlas 300I,我建议花十分钟把这篇看完,能少走很多弯路。这篇文章面向的是实际要部署推理环境的人——不管你是第一次接触昇腾生态、还是要在一个全新系统上从零搭建,它都能帮你理清驱动安装的几种方式,以及怎么根据场景选最合适的安装方法。
先说第一步:搞清楚你手里到底是一张什么型号的卡。Atlas 300I目前常见的有Atlas 300I 3010、Atlas 300I Pro等几个型号,它们在算力规格、功耗、接口上略有差异,但驱动安装思路基本一致。我见过有人拿Atlas 300I Duo的固件包去给300I 3010刷,结果固件校验直接失败,虽然没变砖,但也折腾了大半天。建议装驱动前先用眼睛看一下卡上的标签,或者用lspci确认设备信息:
lspci | grep -i "accelerat"如果能看到类似“Huawei Technologies Co., Ltd. Device”的设备信息,说明系统已经识别到PCIe设备。如果这里完全没输出,先别急着装驱动,大概率是卡没插到位、PCIe插槽供电不足,或者服务器没有给GPU/NPU插槽供足够的通道,这种情况装驱动是白费力气。
然后是服务器形态。Atlas 300I是一张标准PCIe x16的半高半长卡,常见部署在2U/4U机架服务器里,也有一部分人会插在塔式工作站上。不管哪种,先确认服务器的BIOS里已经开启“Above 4G Decoding”,并关闭CSM兼容模式,否则后续内核分配MMIO空间时可能出问题。我踩过一次:一台老工作站没开Above 4G,驱动装完倒是没报错,但npu-smi里死活看不到卡,查了半天才发现是BIOS地址映射导致设备没有被系统完整枚举。
1.2 系统、内核和编译环境要提前备齐
Atlas 300I的驱动安装严格依赖操作系统内核和编译工具链,这是新手最容易忽略的环节。官方文档会给出一个支持列表,常见的是Ubuntu 18.04/20.04/22.04、CentOS 7.6/7.9、openEuler 20.03/22.03,以及麒麟V10这类国产系统。不要只看系统版本,内核小版本也要留意,比如Ubuntu 20.04.5自带的内核是5.4.0-110,后来升级到5.4.0-135也没问题,但如果你手动换成了HWE内核5.15,就可能遇到驱动包自带的DKMS重新编译时找不到内核源码的问题。
因此在装驱动之前,我强烈建议先执行一次系统更新:
# Debian/Ubuntu apt update && apt upgrade -y # CentOS/openEuler yum update -y然后确认这几个编译依赖是否到位:
# Ubuntu apt install -y gcc make linux-headers-$(uname -r) dkms # CentOS/openEuler yum install -y gcc make kernel-devel-$(uname -r) dkms这里特别强调kernel-devel或linux-headers。驱动安装过程中需要为当前内核编译一个内核模块,没有对应的头文件,安装脚本会直接中断,而且报错信息有时候是英文的一大段,很多人看到“Kernel header files not found”就懵了,实际上就是缺了这个包。还有一个容易被忽略的点:如果你的系统已更新内核,但还没重启,当前用着的还是旧内核,那么你装驱动时要确保头文件版本和uname -r输出一致。
注意:不要在跑着生产业务的生产服务器上直接apt upgrade,除非你能接受重启。装驱动前先确认当前内核和头文件版本,避免升级后内核变了、驱动模块和新内核不匹配。
1.3 备份与卸载旧驱动
很多人拿到一台已有的服务器,上面可能装了旧版CANN或驱动,然后直接跑新安装包,结果各种冲突。Atlas 300I的驱动和CANN版本是强相关的,旧驱动不卸,新驱动装不上或者装上后推理时报Unknown Device。
在安装新驱动前,先看看当前机器上有没有遗留的昇腾软件栈:
npu-smi info能正常执行就说明已经有驱动,记录一下版本号。然后检查/usr/local/Ascend目录,确认是否已经装了CANN、driver、firmware等组件。如果有,建议先按官方卸载脚本清理干净。旧版本卸载命令具体看安装包里的uninstall.sh,但最通用的做法是:
# 卸载CANN /usr/local/Ascend/ascend-toolkit/latest/uninstall.sh # 卸载驱动 /usr/local/Ascend/driver/uninstall.sh卸载后重启一次,再确认设备节点已经消失:
ls /dev/davinci*如果还看到davinci_manager、davinci0这类设备,说明卸载不彻底,需要手动清理驱动模块(后面第7章再说)。
2. 驱动安装方式怎么选:run、deb、rpm
2.1 从哪下载驱动包
昇腾的软件包不像普通软件那样集中在一个仓库里,它是分模块发布的。你得先搞清楚三个概念:驱动(Driver)、固件(Firmware)和CANN(Compute Architecture for Neural Networks)。驱动负责让操作系统和NPU建立通信,固件是烧到卡上的底层芯片程序,CANN则是跑推理时真正调用的算子库和运行框架。三者不是同一个包,下载地址也分开放。
去昇腾社区官网,找到“Atlas 300I 推理卡”对应的产品页,里面有“软件包”或“驱动/固件”栏目。通常一个版本周期会提供如下几类文件:
- Ascend HDK 驱动包:例如 Ascend-hdk-...-driver_...run
- Ascend HDK 固件包:例如 Ascend-hdk-...-firmware_...run
- CANN工具包:例如 Ascend-cann-toolkit_...run
- 以及部分deb/rpm格式的驱动包
我个人的建议是:不要图方便直接下载“最新版”,而是先确认你的CANN计划用哪个版本,再按官方配套表去选驱动和固件版本。驱动版本比CANN新很多或者老很多,安装时都不报错,但一跑模型就各种算子报错,那种问题排查起来最花时间。
2.2 三种安装包的差异对比
run包是昇腾官方最推荐的安装格式,本质上是一个自解压脚本,内部封装了驱动、固件或工具包的安装逻辑。deb和rpm则是给Debian系和RedHat系系统用户准备的“类原生”安装包,方便用系统包管理器统一管理。三者用起来体验差异不小,我整理了一个对比表:
| 安装包格式 | 适用系统 | 安装命令 | 优点 | 缺点 |
|---|---|---|---|---|
| run包 | 全支持 | ./xxx.run --full | 官方文档示例最多,安装逻辑统一,可自定义参数 | 不自带依赖管理,缺依赖得先手动装 |
| deb包 | Ubuntu/Debian | dpkg -i xxx.deb | 能用dpkg查询状态,卸载相对规范 | 版本冲突时不提示,容易覆盖旧包 |
| rpm包 | CentOS/openEuler | rpm -ivh xxx.rpm | 能配合yum解决部分依赖 | 需要手动处理内核模块编译 |
如果只是装一台测试机,怎么方便怎么来;但如果你管着一批服务器,我会更建议统一固定一种格式,能少记很多命令。
2.3 驱动与固件的安装顺序问题
关于“先装驱动还是先装固件”,网上的说法有些乱。根据我实测,官方文档的推荐流程是:先装固件,再装驱动。原因是固件属于底层系统,驱动在上层调用,反过来装也不是不能启动,但某些版本组合下会出现驱动报“Firmware version mismatch”的警告,虽然不影响基本推理,但看着闹心,强迫症最好按官方顺序来。
固件升级和驱动安装还有一点不一样:固件升级往往需要重启之后才会真正生效,而且升级过程中不能断电。我在一次固件升级中途因为机房维护电源掉电,结果卡的状态灯一直闪烁,设备节点完全不出现,最后排查发现固件没刷完整,只能重新走一遍升级流程才救回来。所以固件升级尽量安排在维护窗口内,并接上UPS或确保机房供电稳定。
3. run包安装实操记录
3.1 安装前校验与权限准备
用run包安装,我一般会先做两件事:校验文件完整性、确认磁盘空间。虽然昇腾社区下载的文件基本不会出错,但传输过程中被截断的情况也不是没有。校验方法就是对比官方页面上给出的SHA256值:
sha256sum Ascend-hdk-...run把输出值和网页上的值对比,一致再继续。这一步虽然简单,但能避免装到一半解压失败的尴尬。
磁盘空间也要看一眼。驱动包本身只有几百MB,解压和安装过程中会占用/usr/local/Ascend和/var/log,建议至少留出5GB以上空间。之前有台机器根分区只有20GB,装CANN的时候直接爆盘,安装过程中报错,系统差点起不来。
run包安装还需要注意执行权限。下载完先chmod赋权:
chmod +x Ascend-hdk-*_driver_*.run chmod +x Ascend-hdk-*_firmware_*.run然后确认你的用户对/usr/local有写权限,如果之前用sudo安装过其他软件,直接把安装命令放进sudo里执行即可。
3.2 执行安装命令与关键参数
固件和驱动的安装命令长得差不多,区别在run包名和参数上。以驱动为例,最通用的安装命令是:
sudo ./Ascend-hdk-*_driver_*.run --full --install-for-all--full表示完整安装,--install-for-all表示让所有用户都能使用,而不是只给当前用户安装。这里我吃过亏:有一次没加--install-for-all,安装完成后root用户可以正常用npu-smi,但切到普通用户后一直提示找不到设备或权限不足,排查了半天发现是安装时只给当前用户配置了权限。后面我统一都用--install-for-all,一劳永逸。
固件的安装命令稍微有点区别,需要指定--upgrade:
sudo ./Ascend-hdk-*_firmware_*.run --upgrade固件安装过程中会弹出一个提示“Do you want to continue? [y/n]”,我记得有些版本还要输入y确认,建议执行时盯着一点,不要挂着nohup就跑了。
3.3 安装完成后如何验证
无论驱动还是固件,安装完成后第一步永远是看日志。昇腾安装日志通常写在:
/var/log/ascend_seclog/ascend_install.log出现“install success”字样基本就是装完了。驱动装好后立即验证设备节点:
ls /dev/davinci*正常情况下会出现davinci_manager和davinci0(如果你是两张卡,就是davinci0和davinci1),同时还有hisi_hdc等管理设备节点。然后运行:
npu-smi info能看到卡名、驱动版本、固件版本、温度、算力利用率等基础信息,说明安装成功。
如果npu-smi提示找不到命令,别慌,先检查环境变量或直接进到驱动工具目录执行:
/usr/local/Ascend/driver/tools/npu-smi info这个工具是随驱动一起装的,默认路径不加入全局PATH,很多教程没写清楚,导致有人装完驱动后以为命令不存在。
4. deb和rpm包安装的适用场景
4.1 Ubuntu下dpkg安装步骤
Atlas 300I的deb包适合Ubuntu/Debian系统,尤其适合喜欢用dpkg管理软件的人。下载对应驱动deb包后,安装命令很直接:
sudo dpkg -i Ascend-hdk-*_driver_*.debdeb包的好处是用dpkg可以随时查询安装状态:
dpkg -l | grep Ascend卸载时也算规范:
sudo dpkg -r ascend-driver需要注意,dpkg不会自动拉依赖。如果系统缺dkms、make等软件,dpkg一样会报错,所以安装前还是要把编译依赖补齐。另外,deb包安装后也要重启或重新加载内核模块才生效,别指望立刻就能看到设备。
4.2 CentOS/openEuler下rpm安装流程
rpm包的使用习惯和deb差不多,安装:
sudo rpm -ivh Ascend-hdk-*_driver_*.rpm查询:
rpm -qa | grep Ascend卸载:
sudo rpm -e ascend-driver我在openEuler 22.03上装rpm包时遇到过一个细节:直接rpm -ivh可能因为系统缺少某个基础依赖(比如kmod)而安装失败,但系统明明是完整的服务器版。后来我查了才知道,某些最小化安装的系统默认不带完整内核模块相关组件,把kernel-devel、kmod装上后就好了。
4.3 批量部署时推荐哪种方式
如果你要同时给几十台服务器装驱动,run包一个个执行肯定不现实。这时候我比较推荐在基础镜像里把rpm/deb包预先打好,配合PXE或自动化运维工具批量执行。
但有一点必须提醒:Atlas 300I驱动在安装过程中会为当前运行内核编译模块,也就是说批量推送的时候,所有机器的内核版本最好一致。否则同一批安装包,在这台机器上编译成功,在另一台机器上因为内核头文件版本对不上而失败。遇到这种情况,先把所有机器的内核升级到同一个版本再统一部署。
容器镜像场景则是另一种思路。容器里一般不装完整驱动,而是复用宿主机的内核模块和设备节点,所以批量部署时不需要把驱动打进容器镜像,只需要保证宿主机的驱动版本和容器内的CANN版本配套即可。
5. 版本匹配和固件升级是隐形的坑
5.1 驱动、固件、CANN的配套关系
Atlas 300I的版本体系经常让新手晕头转向。同一个版本的驱动包,可能对应某一个CANN版本,而上一个驱动版本又不支持最新的CANN,这里面的对应关系必须依赖官方版本配套表。
我在实际项目中的做法是:先去昇腾社区下载“版本配套表”或产品文档里的“支持矩阵”,确定我要用的CANN版本,然后反向找它对应的驱动和固件版本。不要拍脑袋选“最新版”,宁可一个版本稳定用半年,也不要为了追新频繁升级,搞得模型推理结果出现波动。
举个例子,如果你准备用CANN 7.0系列的推理环境,驱动和固件通常也要匹配到对应的7.0系列,而不是拿一个6.x的驱动硬顶。装好驱动后,npu-smi info里会同时显示驱动版本和固件版本,拿这两个值去和配套表核对,差太远就重装。
5.2 固件升级的操作流程
固件升级流程比驱动安装稍微复杂,我已经按经验总结出一套相对稳的步骤:
先卸载当前驱动,但不要卸载固件:
/usr/local/Ascend/driver/uninstall.sh执行固件升级:
sudo ./Ascend-hdk-*_firmware_*.run --upgrade升级完成后重启服务器。
重启后重新安装驱动:
sudo ./Ascend-hdk-*_driver_*.run --full --install-for-all再次确认版本:
npu-smi info
之所以先卸驱动再升固件,是为了避免驱动在固件升级过程中访问设备造成冲突。虽然有些版本不卸载直接升也能成功,但稳妥总没错。
5.3 升级后的检查清单
升级完固件之后,别急着跑推理,先做一遍体检。我一般按以下顺序检查:
npu-smi info能正常输出,且驱动、固件版本与配套表一致。/dev/davinci*设备节点权限正常,不是只有root能访问。- 加载内核模块没有报错:
lsmod | grep drv_pcie_dev。 - 用CANN自带的样例做一次简单推理验证,比如跑resnet50分类,确认算子和设备都正常。
- 检查
/var/log/ascend_seclog下有没有新的错误日志。
只要这几项过了,基本就可以大胆跑业务。如果其中任何一项异常,建议先别继续,回到第3章和第5.2节的步骤重新排查。
6. 安装完成后的优化配置,别急着跑推理
6.1 环境变量和基础路径
驱动装好后,CANN工具包也需要配置环境变量。安装完成后CANN目录一般在/usr/local/Ascend/ascend-toolkit,里面会提供一个环境变量脚本:
source /usr/local/Ascend/ascend-toolkit/set_env.sh我习惯把这个source写进/etc/profile.d/ascend.sh里,这样所有用户登录后都能直接用。需要注意,set_env.sh里会设置LD_LIBRARY_PATH、PATH、PYTHONPATH等,如果和别的软件(比如CUDA)同时存在,要注意库的加载顺序,必要时用echo $LD_LIBRARY_PATH确认一下。
6.2 NUMA亲和性配置
Atlas 300I插在PCIe插槽上,对应的PCIe控制器会挂在某一颗CPU的NUMA节点上。如果服务器是多路CPU,推理进程如果跑在另一颗CPU上,跨NUMA访问NPU的PCIe资源会显著增加延迟,推理性能会打折扣。
建议先用npu-smi info看卡在哪个槽位,再用lspci查设备的NUMA node:
lspci -v | grep -A20 -i "Huawei" cat /sys/bus/pci/devices/0000:*:*/numa_node确认NPU挂在node0还是node1后,启动应用时用numactl绑定:
numactl --cpubind=0 --membind=0 python3 your_inference_server.py这个优化表面看不明显,但在高并发推理场景下,吞吐能提升不少。之前帮客户调优时,就靠这一步把端到端时延降低了差不多10%。
6.3 容器内使用推理卡的挂载方式
Atlas 300I在容器里跑推理很常见,不是把驱动装进容器,而是把宿主机的设备节点映射进容器。基础挂载方式如下:
docker run -it \ --device /dev/davinci_manager \ --device /dev/davinci0 \ --device /dev/hisi_hdc \ -v /usr/local/Ascend/driver/lib64:/usr/local/Ascend/driver/lib64 \ your-image容器内还需要配套的CANN运行环境。昇腾官方提供了Ascend Docker Runtime,装上之后可以自动感知设备并注入环境变量,比我上面手写--device方便很多。如果只是内部测试,手写挂载完全够用;如果是生产环境多卡部署,建议直接用官方容器运行时,减少人为遗漏。
7. 常见错误与排查实录
7.1 依赖缺失类报错
这类报错在run包和rpm包里都很常见,典型特征是安装脚本跑到一半退出,终端里出现“Kernel header files not found”或者“gcc: command not found”。处理方法在1.2节已经提到,先把gcc、make、kernel-devel/linux-headers、dkms装齐,再重新跑安装包。
还有一个很容易被骗的场景:明明装了kernel-devel,但还是报找不到头文件。这时候检查一下安装的kernel-devel版本到底对不对:
rpm -q kernel-devel uname -r两者必须完全一致。如果不一致,就装对应版本:
yum install -y kernel-devel-$(uname -r)或者在Ubuntu下:
apt install -y linux-headers-$(uname -r)7.2 设备节点不出现/重启失效
设备节点不出现,先看驱动模块有没有加载:
lsmod | grep drv_pcie_dev如果没有输出,尝试手动加载:
sudo modprobe drv_pcie_dev加载后再看/dev/davinci*。如果模块加载失败,去查内核日志:
dmesg | grep -i "davinci\|drv_pcie\|atlas"很多情况下能直接看到错误原因。比如内存不足、PCIe地址分配失败、或者设备被BIOS隐藏。
重启后设备失效也是一个高频问题。大部分原因是驱动不使用DKMS注册内核模块,或者DKMS没有正确注册。解决办法是重新执行一次驱动安装命令,确保安装脚本把DKMS编译好的模块放到/lib/modules/$(uname -r)/updates/dkms/下。装完之后可以验证:
dkms status看到类似“ascend/xx.x, x.x.x-x, x86_64: installed”的状态,说明模块注册成功。
7.3 多卡识别顺序和插槽对应问题
服务器插了两张Atlas 300I,装完驱动后发现/dev/davinci0是哪张卡、/dev/davinci1是哪张卡,没法直观确定。这在多卡推理场景下会引发资源分配混乱。我建议用npu-smi info查看卡号与槽位:
npu-smi info它会列出“Chip Card HwBoardId”之类的信息,同时可以结合lspci确认PCIe地址。如果你想让某张卡固定对应某个设备节点,可以通过调整PCIe插槽顺序来实现,但这个改动比较敏感,个人不建议在生产环境里折腾。一般情况下只需要在应用层通过ASCEND_VISIBLE_DEVICES环境变量控制使用哪张卡即可。
7.4 卸载重装后的残留处理
这个坑我踩过不下三次。卸载驱动后,npu-smi info看着已经不可用了,但重新安装时提示“driver already exists”,或者安装完成后设备节点起不来。原因是卸载脚本没有把公钥、配置文件和部分内核模块清理干净。
手动清理步骤:
# 停掉可能还在引用的服务 sudo systemctl stop ascend-docker 2>/dev/null # 移除驱动模块 sudo rmmod drv_pcie_dev 2>/dev/null # 清理残留目录 sudo rm -rf /usr/local/Ascend/driver sudo rm -rf /etc/ascend sudo rm -rf /var/log/ascend_seclog清理完再重新安装。注意最后留个心眼,确认一下/usr/local/Ascend下是否还有其他组件(CANN等),如果找不到哪些可以删,宁可先备份再删。
7.5 装了驱动但推理性能异常
最后补一个不是驱动安装本身的坑,但很多人装完驱动后发现推理很慢,第一反应是驱动有问题。其实大概率是CANN的算子库或PyTorch适配层版本和驱动不匹配,导致有些算子回退到CPU执行,速度自然慢。用npu-smi info看NPU利用率,如果推理时利用率一直很低,而CPU跑满,基本就是算子没有真正跑在NPU上。这时候去查CANN的版本配套说明,把CANN和驱动一起对齐到推荐组合,问题基本都能解决。
安装和优化Atlas 300I的过程,本质就是把系统环境、版本配套、设备映射这些细节都捋顺。很多问题看起来是驱动不行,实际都是前面某一小步没做到位。我个人的习惯是每次装完都固定写一条笔记,记录系统版本、内核版本、驱动版本、固件版本、CANN版本,以及安装命令和注意事项。下次再遇到类似环境,照着笔记走一遍,十分钟就能搞定,完全不慌。