适用场景
手里有昇腾 Atlas 800 训练/推理服务器或 Atlas 300I 推理卡,想把 DeepSeek V4.1 跑成自建推理服务。DeepSeek 开源的昇腾基础组件(设备适配层、算子库、推理调度等,具体包名与仓库地址以官方仓库 README 为准)把驱动、CANN、深度学习框架之间的适配工作做了封装,不需要从零写 ACL 代码。这套流程适合硬件已经到位、但卡在「环境对不上、算子缺失、吞吐上不去」这三类问题的团队。
环境与前置条件
- 操作系统:与目标 CANN 版本配套的 Linux 发行版,具体支持列表以 CANN 官方文档为准。
- 运行时:Python 3.x;PyTorch 与 torch_npu 必须是官方配套表里成对出现的组合,不要各装各的最新版。
- NPU 驱动与固件:版本需要和 CANN 配套。驱动偏旧或偏新,都会在设备初始化阶段直接报错。
- 显存与内存:模型权重按参数量估算,FP16 下每 10B 参数约 20GB 权重占用,还要额外留出 KV cache、激活和通信缓冲区。经验做法是单卡可用显存 ≥(权重总量 ÷ 卡数)× 1.5,主机内存不低于所有卡显存之和。
- 磁盘:权重文件、算子编译中间产物、日志三块都要留空间,建议预留数百 GB。
- 权限:当前用户对
/dev/davinci*等设备节点有读写权限;容器部署要挂载设备节点与驱动目录。
分步骤部署
步骤 1:确认硬件与驱动就绪
先看卡在不在、健康不健康:
```bash
npu-smi info
npu-smi info -t board -i 0
```
第一条会列出 NPU 数量、型号、显存占用和 Health Status;第二条给出固件与驱动版本。Health Status 显示 OK、显存占用接近 0,这一步才算通过。把驱动和固件版本号记下来,后面选 CANN 版本要用。
步骤 2:安装 CANN 工具链
CANN 通常提供 toolkit(开发工具链)和 kernels(算子包)两类安装包,下载地址与文件名以官网下载页面为准。
```bash
chmod +x Ascend-cann-toolkit_*_linux-*.run
./Ascend-cann-toolkit_*_linux-*.run --install
chmod +x Ascend-cann-kernels-*.run
./Ascend-cann-kernels-*.run --install
```
--install 会装到默认路径。装完把环境变量写进 shell 配置,避免每开一个新终端都要手动 source:
```bash
echo 'source /usr/local/Ascend/ascend-toolkit/set_env.sh' >> ~/.bashrc
source ~/.bashrc
```
验证:
```bash
which atc
python -c "import acl; print('acl ok')"
```
两条都不报错,说明工具链已就位。
步骤 3:配置 Python 环境与 torch_npu
建议用独立虚拟环境,昇腾侧包的依赖比较敏感,混装容易互相污染。
```bash
conda create -n v41 python=<3.x> -y
conda activate v41
torch 与 torch_npu 从昇腾官方源安装,版本组合以官方配套表为准
pip install torch==<与 torch_npu 配套的版本> --index-url <官方源地址>
pip install torch_npu==<配套版本> --index-url <官方源地址>
```
验证 NPU 张量能不能真的算:
```bash
python -c "
import torch, torch_npu
x = torch.randn(4, 4).npu()
y = (x @ x.T).cpu()
print(torch.npu.get_device_name(0), y.shape)
"
```
能打印出芯片型号和 [4, 4],说明框架到设备的通路是通的。
步骤 4:安装 DeepSeek 昇腾基础组件
从官方仓库拉代码,按 README 指定的方式安装。不同组件的安装方式有差异,常见是 pip 可编辑安装,或先编译再打包:
```bash
git clone <官方仓库地址>
cd <组件目录>
pip install -e . # 或按 README 执行 bash build.sh && pip install dist/*.whl
```
如果组件里带 C++ 扩展,编译前确认 cmake、gcc 版本满足 README 要求。编译过程可能持续十几分钟到几十分钟,中途只出现 warning、没有 error 属于正常。
装完确认能被导入:
```bash
python -c "import <组件包名>; print(<组件包名>.__file__)"
```
步骤 5:准备模型权重与推理配置
从官方发布渠道获取 V4.1 权重,下载后先校验哈希,避免半包损坏导致后面加载失败。目录结构一般长这样:
```text
weights/
config.json
tokenizer.json
*.safetensors
```
按卡数修改并行配置:单卡不需要张量并行;多卡要设置张量并行度与流水并行度,并且与启动脚本里的卡数、ASCEND_RT_VISIBLE_DEVICES 保持一致。精度字段按硬件能力选择,具体支持哪些精度以官方文档为准。
步骤 6:模型加载或图转换
有两条路线:
- 动态图路线:直接用 torch_npu 加载权重,调用组件的推理接口,不产生中间模型文件,调试方便。
- 静态图路线:先导出 ONNX,再用 ATC 转成 om,适合对时延稳定性要求高的生产场景。
ATC 示例:
```bash
atc --model=model.onnx \
--framework=5 \
--output=model_v41_bs1 \
--soc_version=<芯片型号> \
--input_format=ND \
--input_shape="input_ids:1,-1" \
--log=error
```
soc_version 要和 npu-smi info 里的芯片型号对应,映射关系查官方文档。执行成功会在输出目录生成 .om 文件和编译日志。
步骤 7:编译与安装自定义算子
遇到组件里没有的算子,或想用融合算子提性能,就要自己编。用算子工程生成工具搭骨架:
```bash
msopgen gen -i op_config.json -c ai_core-<soc_version> -out ./custom_op
cd custom_op
bash build.sh
./build_out/custom_opp_*.run --install
```
op_config.json 描述算子名、输入输出、支持的芯片型号。编译成功会生成算子包,安装后算子进入 opp 的 vendor 目录。如果装完仍然提示找不到算子,检查 ASCEND_OPP_PATH 是否包含了新装的 vendor 路径。
步骤 8:吞吐测试与调优
用一个固定输入长度、固定输出长度的脚本做基准,逐档加并发:
```python
import time, torch, torch_npu
prompt_len, out_len = 512, 128
for batch in (1, 2, 4, 8):
inputs = torch.randint(0, 1000, (batch, prompt_len)).npu()
torch.npu.synchronize()
t0 = time.time()
out = model.generate(inputs, max_new_tokens=out_len) # 接口名以组件文档为准
torch.npu.synchronize()
dt = time.time() - t0
print(f"bs={batch} {batch * out_len / dt:.1f} tokens/s, 单请求 {dt:.2f}s")
```
关注三个数字:整体 tokens/s、首 token 时延 TTFT、每 token 时延 TPOT。加并发后 tokens/s 上升但 TPOT 明显变差,说明显存带宽或 KV cache 到了瓶颈。
调优的几个常用抓手:
```bash
export HCCL_SOCKET_IFNAME=<业务网卡名>
export HCCL_IF_IP=<本机业务网卡 IP>
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3
```
- 用 msprof 采样一次推理,看耗时排前几的算子,把能替换成融合版本的替换掉:
```bash
msprof --application="python infer_bench.py" --output=./prof_out
```
验证部署是否成功
按顺序跑这几步,全过就说明链路完整:
1. npu-smi info 显示所有卡 Health Status 为 OK,没有异常进程占卡。
2. python -c "import torch, torch_npu; torch.randn(2,2).npu()" 无报错。
3. 组件仓库自带的 examples 或自检脚本能跑通,输出与 README 描述一致。
4. 用同一段 prompt 连续跑两次,贪心解码下输出内容一致、不抖动。
5. 吞吐脚本在 batch=1 时能得到正的 tokens/s,且随 batch 增大单调上升,直到出现拐点。
常见报错与解决
报错 1:ImportError: libascend_hal.so: cannot open shared object file 或 ModuleNotFoundError: No module named 'torch_npu'
→ 原因:当前 shell 没有 source CANN 的环境变量,或 LD_LIBRARY_PATH 里缺驱动库路径。
```bash
source /usr/local/Ascend/ascend-toolkit/set_env.sh
echo $LD_LIBRARY_PATH # 确认包含 ascend-toolkit 与 driver 的 lib64 目录
```
报错 2:RuntimeError: NPU out of memory 或 ACL_ERROR_RT_DEVICE_MEM_ERROR
→ 原因:batch 或序列长度超出显存,KV cache 没做分页/量化,或者上一个进程残留占卡未释放。
```bash
npu-smi info # 看是否还有残留进程
npu-smi info -t proc-mem -i 0
调小 batch / max_seq_len,或开启 KV cache 量化与分页
```
报错 3:多卡启动卡住并报 EI0006: Getting socket times out 或 HCCL execute failed
→ 原因:HCCL 走错网卡、端口被防火墙拦截,或各进程环境变量不一致。
```bash
export HCCL_SOCKET_IFNAME=<业务网卡名>
export HCCL_IF_IP=<本机业务网卡 IP>
export HCCL_CONNECT_TIMEOUT=1200
确认防火墙放通对应端口段
```
报错 4:The operator is not supported 或 EZ9999 类算子执行失败
→ 原因:自定义算子未安装,或安装后算子包路径没进环境变量。
```bash
./build_out/custom_opp_*.run --install
echo $ASCEND_OPP_PATH # 确认包含新 vendor 目录
临时回退方案:把该算子放到 CPU 执行,先跑通流程再补算子
```
报错 5:启动时提示驱动版本与 CANN 不匹配
→ 原因:驱动/固件与 CANN 版本不在官方配套表内。
```bash
npu-smi info -t board -i 0 # 记录当前驱动与固件版本
按官方配套表升级或降级驱动,固件与驱动一起更新
```
后续维护
- 备份:把权重目录、推理配置、算子包版本号、CANN 与 torch_npu 的版本组合记录成一份清单,和容器镜像 tag 一起归档。恢复环境时按清单装,不要凭记忆。
- 升级:驱动、固件、CANN、torch_npu、基础组件是联动的,任何一项单独升级都可能出问题。做法是先在一台测试机上按步骤 1 到 8 全量走一遍,跑通吞吐对比后再推生产。
- 日志:CANN 侧日志在
~/ascend/log或/var/log/npu下,按 plog 分组。出问题时把对应时间段的 plog 打包,比只看 Python 报错有用得多。 - 监控:用
npu-smi info或官方提供的 exporter 采集显存占用、利用率、温度,接入现有监控系统。重点看显存是否随请求数持续上涨,那通常是 KV cache 没有释放。 - 磁盘清理:算子编译中间产物和模型转换输出会越积越多,定期清理构建目录,只保留最终产物。
