刚接手昇腾AI服务器那会儿,我踩得最狠的一个坑,就是没把“版本查询”当回事。当时觉得驱动装上了、CANN也能import,就直接开跑模型,结果训练任务跑到一半算子编译报错,日志里全是“version mismatch”之类的红字,排查了一下午才发现是固件版本和CANN版本不在同一套配套关系里。从那以后我养成了一个习惯:不管新机器交付、旧机器升级,还是别人转交过来的环境,第一件事永远是先把固件、驱动、CANN这三层版本查清楚,记录成台账再动手。

这篇文章就把我这几年在昇腾服务器上常用的版本查询方法完整梳理一遍,包括npu-smi的基础用法、系统侧的交叉验证、CANN环境变量的检查技巧,以及版本不一致时的典型故障排查思路。适合刚接触昇腾环境的运维同学,也适合那些和我一样被版本配套问题折磨过的算法工程师。

1. 昇腾服务器软件栈拆解:固件、驱动、CANN到底各管什么

在动手敲命令之前,我觉得有必要先把昇腾环境里的三层软件关系说清楚。很多人查版本查不明白,本质上是不清楚自己在查哪一层,也不知道哪一层版本变化会影响到什么。

1.1 三层架构和它们的分工

昇腾AI服务器的软件栈从底层到上层,大致可以分为固件、驱动、CANN这几层。固件一般固化在硬件单板或者芯片外围的存储介质里,负责芯片上电初始化、电源管理、PCIe链路协商这些最底层的活。你可以理解成主板的BIOS,它不常动,但一旦出问题,整台机器直接起不来,或者NPU在系统里根本看不到。

驱动是运行在操作系统内核里的模块,负责把NPU的算力能力以设备节点的形式暴露给上层软件。昇腾的驱动安装后,你在/dev目录里会看到davinci相关的设备节点,davinci_manager、davinci0这些就是驱动工作起来之后创建的。驱动版本不对,最常见的结果就是npu-smi看不到NPU,或者AI Core上报异常。

CANN是华为昇腾的计算架构,也就是上层应用真正打交道的软件包。算子库、图编译引擎、运行时环境都在这层,你的训练框架比如PyTorch要通过torch_npu插件和CANN对接。CANN版本和驱动、固件版本之间是严格配套的,官方每个版本都会发布一张配套表,标明CANN的某个版本要求驱动和固件最低是多少、推荐是多少。

1.2 为什么要先学会查版本

你可能觉得,版本查询不过就是几条命令的事,哪里值得单独写一篇文章?但昇腾环境的版本问题,坑就坑在“不是装上就能用”。我见过很多同事在社区里发帖求助,症状五花八门,归根到底都是版本配套没对齐。

举几个真实场景:新买的Atlas 800T A2训练服务器,出厂固件和驱动版本可能已经刷好,但CANN还是套件包里的老版本,跑起来算子编译报错;又或者你为了修一个BUG单独升级了驱动,但固件没跟着升,结果NPU健康状态变成了Abnormal;还有更隐蔽的,驱动和CANN版本单独看都没问题,但你对着一块很老的Atlas 300I推理卡,装了一个很新的CANN版本,文档里明确写着不再支持,这种情况光看报错根本看不出来。

所以查版本不是走流程,而是建立整个排查体系的第一步。版本信息就像是环境的“锚点”,后面无论做性能分析、算子适配还是故障定位,都要拿版本号去对齐官方文档和已知问题清单。

1.3 版本匹配的本质:配套表

昇腾的版本配套关系,通常以“固件+驱动版本”与“CANN版本”组合的形式出现。比如官方会给出一个类似“CANN 7.0.0 配套 Driver 23.0.rc1、Firmware 23.0.rc1”的说明,具体数值要按你的产品型号去查对应版本的Release Notes,每个大版本下面还会有已知问题列表和升级路径说明。

这里有个非常重要的认知:固件和驱动经常是打包发布的,很多场景下它们的版本号会保持一致,但不代表它们天然就是配套的。你在服务器上手动单独升级驱动但不升固件,当下可能能用,但多次迭代后很容易出现“驱动版本比固件新很多,接口不兼容”的情况。所以我的建议是,查询版本的时候不要只看某一个命令的结果,而是要同时拿到固件、驱动、CANN三个信息,再去和配套表核对,这种习惯能帮你省掉大量排错时间。

2. 固件与驱动版本查询:实操命令全记录

昇腾服务器上查询固件和驱动版本,最核心的工具就是npu-smi,它是随驱动一起安装的命令行工具。下面我把常用命令和输出信息怎么解读都拆开讲。

2.1 首选工具npu-smi:一条命令看懂基本版本

npu-smi的完整路径一般在/usr/local/Ascend/driver/tools/npu-smi,如果安装驱动时已经把路径加入了环境变量,直接执行npu-smi info就行。我习惯在这个命令没反应时先确认一下路径,因为有些精简安装场景并不会自动把工具路径加入PATH。

执行npu-smi info后,输出信息通常分成几块。最上面会显示npu-smi工具自身的版本,中间会列出每颗NPU芯片的状态、健康情况、温度、功耗、HBM使用率,下面会有一段Driver Version和Firmware Version的汇总。在我们的一台Atlas 800T A2服务器上,输出大致是这样:

+------------------------------------------------------------------------------------+
| npu-smi 24.1.rc1                 Driver Version: 24.1.rc1     Firmware Version: 24.1.rc1 |
+-------------------+-----------------+--------------------------------------------------+
| NPU     Name      | Health          | Power                 | HBM                |
| Chip    Device    | Bus-Id          | AICore               | AIC                 |
+-------------------+-----------------+--------------------------------------------------+

这里的Driver Version和Firmware Version如果完全一致,通常说明固件和驱动是配套发布的版本,这是比较理想的状态。如果两者不一致,比如驱动是24.1.rc1但固件还是23.0.rc1,就要警惕了,后面我会在排查部分专门说这种场景。

还有一个细节要提醒:npu-smi info只展示当前能被驱动正常识别的NPU信息。如果你的固件版本老到驱动加载不了,npu-smi info可能直接报错,连版本都看不到。这种情况下反而不能依赖这个工具,得用系统侧的方式去验证,这部分放到2.3节讲。

2.2 深入单板信息与固件详情

npu-smi info给出的版本信息是汇总级别的,足够日常巡检用。但如果你想拿到更细的单板信息,比如PCB版本、器件型号、单板序列号,或者想确认固件里各组件的小版本号,就要用带参数的查询方式。

我比较常用的几条:

npu-smi info -t board -i 0
npu-smi info -t device -i 0

-t代表查询类型,-i指的是NPU ID。board信息会打印单板相关的硬件信息,device信息会打印设备侧状态。这些参数在不同版本的npu-smi里支持情况略有差异,查看帮助可以执行npu-smi info --help,不同版本的输出字段也会有差异,大版本升级后最好重新扫一眼帮助文档。

另外,upgrade-tool是专门负责固件和驱动升级的工具,它也提供了查询能力。在较新的版本里,可以执行:

npu-smi upgrade-tool -t info

这条命令会输出当前系统里固件和驱动的版本,以及一些升级路径相关信息的汇总,在准备升级之前跑一下非常有用。

2.3 系统侧交叉验证:不依赖npu-smi的查法

实战中总会遇到一些特殊情况,比如驱动加载失败、npu-smi工具损坏、或者你登录进的是一个容器环境,只有宿主机的命令还能用。这时候就需要系统侧的交叉验证手段。

驱动安装完成后,一般会在/usr/local/Ascend/driver目录下留下version.info或version.cfg文件。你可以直接查看:

cat /usr/local/Ascend/driver/version.info

这个文件一般会给出driver版本和固件版本,和npu-smi info看到的应该是一致的。不过要注意,文件里记录的是安装时的版本信息,如果后续有人手动改动过固件或者驱动文件,这里不一定能反映真实运行状态,只能作为参考。

更底层的验证方法是用dmesg查内核日志。驱动模块加载时会在dmesg里打印版本信息和初始化状态:

dmesg | grep -i npu
dmesg | grep -i davinci

如果能看到类似“driver version x.x.x”的日志,说明驱动模块至少加载到内核了。如果连日志都没有,那基本可以断定驱动模块没有正常insmod。

PCIe链路的状态可以通过lspci确认。昇腾的NPU在lspci输出里通常能看到Huawei相关的设备条目,执行:

lspci | grep -i huawei
lspci -nn | grep -i "Process"

这里有个经验:不要只依赖lspci判断设备是否存在,关键在于davinci设备节点是否创建。在系统里用ls /dev/davinci*看一下,如果节点没出现,多半是驱动加载失败。即使lspci能看到设备,上层软件也无法使用NPU。

3. CANN版本检查技巧与配套关系确认

固件和驱动查明白之后,下一步就是CANN。CANN版本检查的难点在于,它不是单一软件包,而是由toolkit、nnal、kernels等一堆组件组成,有些环境里还装了多个版本,一不小心就搞混用错。

3.1 先从安装目录和版本文件入手

默认情况下,CANN会安装到/usr/local/Ascend/ascend-toolkit目录。先看目录结构:

ls -l /usr/local/Ascend/ascend-toolkit/

通常会有latest软链接指向当前默认版本,版本目录名一般是带版本号的,比如7.0.0、7.0.RC1,不同产品配套的版本命名会有差异。多个版本并存时,是通过切换到不同目录来控制运行时版本的,并没有多版本自动选择机制。

确认当前默认版本的详细信息,可以查看版本文件:

cat /usr/local/Ascend/ascend-toolkit/latest/version.cfg

version.cfg是文本文件,直接可读,里面会列出CANN版本号、编译日期、配套信息等。有些版本里可能叫version.info,没有统一标准,所以打开目录看一眼最稳妥。

如果CANN是通过源码方式编译安装的,或者你家环境用的是虚拟环境,目录可能不在默认位置。这种情况下可以通过环境变量确认当前生效的CANN路径:

echo $ASCEND_TOOLKIT_HOME

正常配置的CANN环境里,这个变量会指向当前正在使用的ascend-toolkit路径。如果变量为空,说明环境变量没有正确加载,后面跑训练框架大概率会出各种找不到算子的诡异问题。

3.2 环境变量与工具链自检

CANN使用前必须正确source环境变量脚本。常见路径是:

source /usr/local/Ascend/ascend-toolkit/set_env.sh

这个脚本会把CANN的bin、lib、python包路径全部加进环境变量,同时设置ASCEND_TOOLKIT_HOME、ASCEND_HOME_PATH等变量。在跑任何需要NPU的Python脚本前,我都要先确认环境变量已生效,这是新手最容易漏的一步。

source之后,可以执行几个快速自检命令。比如查看CANN自带工具链的版本,不同版本工具名会有差异,但一般在bin目录下都能找到类似msmanage的工具:

msmanage --version

或者直接在Python里检查CANN运行时相关包:

python3 -c "import torch; print(torch.__version__)"
python3 -c "import torch_npu; print(torch_npu.__version__)"

如果你的训练框架是PyTorch,torch_npu的版本也必须和CANN版本对齐,否则调用NPU时会出现版本不匹配的告警。常见告警信息类似“torch_npu and CANN version mismatch, expected xxx, got yyy”,这种告警出现在导入torch_npu时,如果忽略它,后来跑算子大概率会直接崩,所以看到就必须处理。

3.3 配套表怎么看:先定位产品型号,再锁版本

拿到所有版本号之后,最关键的步骤是去核对官方配套表。昇腾的配套表一般发布在对应版本的Release Notes或者CANN兼容性说明文档里,文档标题类似“CANN xxx 版本配套表”或“产品兼容性说明”。

查看配套表有一个核心方法:先确认你的硬件产品型号,再确认你的芯片类型,然后才能看对应的软件版本要求。同样是昇腾服务器,Atlas 800T A2训练服务器和Atlas 800I A2推理服务器,可配套的CANN版本范围就不同;Atlas 300I Duo推理卡和Atlas 910B训练卡,驱动和固件的版本要求也不一样。

比如我自己维护的一台Atlas 800T A2服务器,芯片是昇腾910B,CANN用的是7.0.0配套的版本组合,驱动和固件都是24.1.rc1。后来我接手一台老的Atlas 300I推理卡服务器,官方配套表里明确建议用CANN 5.1.1或更早的版本,如果强行装CANN 7.0.0,驱动也能装上,但推理卡在运行时会被识别异常。

所以我的建议是:别只记版本号数值,要把“产品型号+CANN版本+驱动版本+固件版本”四元组记成一条台账,每次环境变更都更新这个台账。这样即使过了半年再回头看,也能立刻确认当前环境是不是处于官方支持的配套区间。

4. 版本相关问题排查实录

版本查询工具都熟悉了,接下来要聊聊真正逼疯人的部分:查出来版本之后还是很诡异,驱动、固件、CANN三个版本表面看都正常,但业务就是跑不对。这里我整理了这段时间在高频问题里的排查路径。

4.1 npu-smi看不到NPU或命令报错

如果你执行npu-smi info直接报错,比如提示无法连接设备,或者显示0颗NPU,大概率是驱动层就没起来。先不要急着重装系统,按这个顺序排查。

第一步,确认davinci设备节点是否存在:

ls -l /dev/davinci*

如果节点缺失,说明驱动模块可能没加载成功。用dmesg查驱动日志:

dmesg | grep -i "davinci"
dmesg | grep -i "npu"

常见的日志包括“driver version xxx”和“firmware version xxx”,如果看到firmware相关报错,比如固件校验失败,那就说明固件版本太旧、和当前驱动不兼容,需要升级固件或者回退驱动版本。

第二步,确认npu-smi工具的路径和权限。npu-smi需要root权限才能调用部分查询接口,如果你用普通用户跑,可能能看版本但看不到详细状态。建议用root执行,或者至少先确认用户是否在正确的用户组里。

第三步,检查NPU是否被系统识别到PCIe层面。上面说的lspci | grep -i huawei,如果这里都看不到设备,那问题可能在硬件、PCIe槽位或者固件里的PCIe配置,这时候就不能只从软件版本角度排查了,需要联系硬件工程师介入。

4.2 驱动与固件不一致导致的启动异常

我在一台Atlas服务器上遇到过这种状况:npu-smi能看到设备,驱动版本显示24.1.rc1,固件版本显示23.0.rc1,系统日志里反复出现“NPU is abnormal”的信息,但AI Core状态看起来还是正常的,模型也能跑,只是偶尔会报一些奇怪的段错误。

排查后发现,这台机器之前有人单独升级过驱动,但没有升级固件。官方配套表里明确要求驱动24.1.rc1必须配合固件24.1.rc1使用,跨大版本的固件接口变化导致驱动在特定路径下无法正确下发算子。

解决办法很简单:把固件升级到配套版本。昇腾固件和驱动的升级包在官方发布页面可以下载,升级固件的命令通常是:

./Ascend-cann-firmware_xxx.run --full --install

执行升级前强烈建议先备份当前固件版本信息,记录升级前后的版本号,升级完成后用npu-smi info确认固件和驱动版本是否已经对齐。这个过程大概率会涉及服务器重启,所以在生产环境上操作前一定申请变更窗口。

4.3 CANN算子编译时报版本不匹配

这类问题多发生在你单独升级了CANN,但驱动和固件没动的情况下。比如原本CANN 6.3和Driver 23.0.rc1配合得好好的,你为了用新特性把CANN升级到7.0,结果跑算子时提示找不到某个算子或者版本不匹配。

这背后原因是CANN新版本里的算子库可能依赖驱动新增的接口,驱动版本太老,这些接口不存在,CANN又不会自动回退到兼容模式。排查方法比较直接:先确认CANN版本和驱动版本是否在官方配套表里,如果不在,把驱动升级到对应版本。

另外要提醒一点:昇腾环境里如果同时存在多个CANN版本,或者你在容器里挂载了宿主机驱动但容器内装了新CANN,也容易出现版本错位。我遇到过容器内CANN是7.0.0、宿主机驱动还是23.0.rc1的情况,报错信息里会反复提到“libascendcl”和“libdriver”的版本不匹配。这种时候第一反应不应该是重装CANN,而是先确认宿主机驱动版本再做决定。

我在排查时一般用这个顺序:

npu-smi info | grep -E "Driver|Firmware"
cat /usr/local/Ascend/ascend-toolkit/latest/version.cfg
echo $ASCEND_TOOLKIT_HOME

三步走,能快速判断问题出在哪一层,能省下大量时间。

4.4 升级过程中的常见坑

版本升级看起来只是跑一下安装脚本,实际有很深的门道。固件升级失败最典型的症状是:安装脚本执行成功但重启后设备消失,或者固件半升级状态,导致驱动无法初始化。

我在升级过程中总结了几条经验。第一,升级驱动之前,必须卸载老版本驱动,或者使用脚本自带的覆盖安装参数,不要直接装新包上去叠加。驱动模块加载时有多个内核模块文件,新旧混在一起会导致模块间符号错位,这种问题极难排查。

第二,固件升级不像驱动升级,它可能涉及芯片内关键存储的初始化,升级过程中坚决不能断电。我见过同事在固件升级过程中因为SSH会话断开,直接重启服务器,结果整个NPU单板变砖,只能返厂刷写。所以生产环境固件升级,最好通过带外管理口操作,比如BMC或iBMC,确保网络断开或主机重启的情况下升级进程不会中断。

第三,升级前要做版本快照。昇腾环境没有像docker镜像回滚那么方便的工具,但你可以手工保留一份系统侧的快照信息,包括当前所有版本号、设备序列号和驱动的配置参数。至少要把npu-smi info的输出重定向到文件保存起来:

npu-smi info > npu_version_before_upgrade_$(date +%Y%m%d).txt

这样出了问题至少还能知道原来的版本组合是什么,方便快速回退。

5. 日常巡检脚本与版本管理建议

很多运维同学只在环境出问题时才去查版本,这会让问题发现滞后。昇腾AI服务器的版本状态应该纳入日常监控,我用一个小脚本加上定期巡检,把版本查询变成自动化动作。

5.1 一条命令汇总环境体检报告

我整理了一个简版巡检脚本,本质就是把本文提到的所有查询命令集合在一起输出。你可以根据自己环境调整路径。

#!/bin/bash
# 昇腾环境版本巡检脚本
# 建议以root身份执行
echo "===== 系统时间 ====="
date

echo "===== NPU状态与驱动/固件版本 ====="
npu-smi info

echo "===== 驱动版本文件 ====="
cat /usr/local/Ascend/driver/version.info 2>/dev/null || echo "未找到driver version.info"

echo "===== CANN当前版本 ====="
cat /usr/local/Ascend/ascend-toolkit/latest/version.cfg 2>/dev/null || echo "未找到CANN version.cfg"

echo "===== CANN环境变量 ====="
echo "ASCEND_TOOLKIT_HOME=$ASCEND_TOOLKIT_HOME"

echo "===== davinci设备节点 ====="
ls -l /dev/davinci* 2>/dev/null || echo "未找到davinci节点"

echo "===== Torch与torch_npu版本 ====="
python3 -c "import torch; print('torch:', torch.__version__)" 2>/dev/null || echo "未安装torch"
python3 -c "import torch_npu; print('torch_npu:', torch_npu.__version__)" 2>/dev/null || echo "未安装torch_npu"

这个脚本输出的信息足够日常巡检用。我每周跑一次,顺便把输出重定向到一个日志目录,方便追溯。如果哪天发现问题,可以直接拿最新一次日志做对比,知道环境什么时候发生过变化。

5.2 版本升级前的备份习惯

每次要升级驱动或CANN,我都会先做三件事:备份当前版本信息、备份关键配置文件、记录升级操作步骤和时间窗口。

关键配置主要是环境和用户配置,比如:

cp /usr/local/Ascend/driver/version.info /root/backup/
cp /usr/local/Ascend/ascend-toolkit/latest/version.cfg /root/backup/

严格来说这不算完整备份,因为驱动和CANN的安装目录占用空间很大,一般不需要整目录备份,但版本信息文件非常小,保留下来至少能在升级出问题时快速确认回退目标版本。如果条件允许,还可以把当前驱动和CANN的安装包文件单独放到一个备份目录,以备回滚时使用。

5.3 多服务器场景下的版本台账管理

如果你维护的不止一台昇腾服务器,建议建一个简单的版本台账,用表格记录每台机器的型号、芯片类型、驱动版本、固件版本、CANN版本、维护负责人、最近变更日期。形式不限,可以用Excel,也可以用Markdown表格放到Git仓库里。

为什么台账很重要?因为昇腾服务器的硬件产品线很杂,有些老服务器会搭配老款推理卡,软件版本长期不更新,却一直跑生产任务。如果哪天为了统一版本把一台老机器的驱动升到最新,结果发现新驱动不支持老卡,可能直接就影响线上推理服务。有了台账,你就能在一次升级前快速判断这台机器是否值得动,以及升级的影响范围有多大。

台账还有一个额外好处:当你需要向厂商售后反馈问题时,对方第一句话一定会问“你当前的环境版本是多少”,这时候你拿出台账,一分钟就能给出完整版本组合,沟通效率会高很多。

6. 三个最容易忽略的细节

版本查询相关的内容基本讲完了,最后再补充三个我实际操作中容易忽略的细节,它们虽然不是核心知识,但关键时刻能救命。

第一个细节是npu-smi工具自身版本可能和驱动版本不一致。npu-smi info输出最上面那行显示的版本,有时候是工具自身编译版本,有时候是驱动版本,不同大版本展示方式不同。应该以输出里Driver Version和Firmware Version字段为准,别被工具版本号误导。

第二个细节是环境变量和实际生效版本的匹配问题。有些同学在/etc/profile里写死了一套CANN路径,但后来安装新版本后,latest软链接已经指向新版本,shell环境却仍然加载旧路径,导致跑模型时看到的CANN版本和命令行里cat到的版本不一致。我建议每次登录后都执行一下echo $ASCEND_TOOLKIT_HOME,确认当前实际生效的路径。

第三个细节是固件小事:很多服务器在BIOS里开启了SR-IOV或PCIe ACS特性,这会影响NPU设备在系统里的呈现方式。如果你发现版本都正常但NPU在某些虚拟机环境里用不了,别急着怀疑驱动,先去BMC里看一下PCIe相关配置是否适合当前虚拟化场景。这类问题不属于常规版本查询的范畴,但确实会让人在排查版本问题时白费力气。

昇腾环境的版本管理,说到底就是耐心和习惯。版本查询命令就那么几条,但每条命令背后对应的软件层级、配套关系、故障场景,才是真正需要长期积累的经验。我现在的流程很简单:新接手机器先跑一遍巡检脚本,把台账记录下来;每个月再看一眼官方是否有新的Driver或CANN版本发布;升级前一定备份版本信息和配置;遇到问题先从版本组合入手排查。这套流程帮我躲过了很多原本可能要花几天才能定位的故障,也希望对你有点帮助。

更多推荐