完整KTransformers昇腾NPU部署实战
【免费下载链接】ktransformersA Flexible Framework for Experiencing Heterogeneous LLM Inference/Fine-tune Optimizations项目地址: https://gitcode.com/GitHub_Trending/ktr/ktransformers
你手上有一张 Atlas 300I A2 昇腾NPU、一台 1TB 内存的 ARM 服务器,目标是把 671B 满血 DeepSeek-R1/V3 跑成本地可对话的推理服务。本文带你用 KTransformers 完成部署:注意力、共享专家下沉 NPU 计算,路由专家留在 CPU 内存,实测 Prefill 约 174 tokens/s、Decode 稳定在 16 tokens/s 左右。🎯
这种异构切分正是 KTransformers 的核心思路:把算得动的部分压进 NPU 图里,把放不下的 MoE 专家权重摊到 CPU 内存,两边通过共享内存交换中间结果。
开工前30秒自检:你的机器达标吗
逐行核对,任何一项不满足都会让后续步骤卡住:
| 检查项 | 硬性要求 | 说明 |
|---|---|---|
| NPU 型号 | Atlas 300I A2 | 目前仅此型号经过验证 |
| 参考整机 | Atlas 2UP,Kunpeng 920 7270Z | 官方基准测试机型 |
| 内存 | ≥400GB(满血版 R1/V3) | 路由专家权重全部驻留内存 |
| 操作系统 | Ubuntu 22.04 for aarch64,内核 5.15.0-25-generic | 需关闭自动更新 |
| HDK / CANN | 25.3.RC1 / 8.3.RC1.alpha003 | CANN 需装 ToolKit + Kernel + NNAL 三组件 |
| Python 栈 | Python 3.11,torch==2.5.1,transformers==4.57.1 | transformers 其他版本未验证 |
| torch_npu | v2.5.1 分支源码编译 | PyPI 上的包缺少新增算子,不可直接用 |
阶段一:锁定软件栈版本(HDK、CANN 与 torch_npu)
先在系统层装上构建依赖并固定 Python 环境。所有版本写死,不要图省事装"最新版":
# 构建依赖 + Python 3.11 虚拟环境 + 版本锁定的 PyTorch 栈 apt install cmake libhwloc-dev pkg-config conda create -n kt-npu python=3.11 conda activate kt-npu pip3 install numpy==1.26.4 # 适配 torch/torch_npu pip3 install torch==2.5.1 torchvision==0.20.1 torchaudio==2.5.1 pip3 install transformers==4.57.1 # 必须此版本torch_npu 必须从昇腾官方 PyTorch 仓库取 v2.5.1 分支源码编译。编译前加载 CANN 与 NNAL 环境,装完 wheel 后注意一点:wheel 版本号带 git 哈希后缀(如2.5.1.post4+git69550dfc),打开site-packages/torch_npu/version.py,把__version__改成2.5.1.post4并去掉哈希,否则依赖校验会失败。
source /usr/local/Ascend/ascend-toolkit/set_env.sh # 以实际CANN路径为准 source /usr/local/Ascend/nnal/atb/set_env.sh # 以实际NNAL路径为准 # 按仓库内文档编译 v2.5.1 分支,安装产出的 wheel 后再改 version.py验收点:执行python -c "import torch_npu; print(torch_npu.npu.is_available())",输出True且无报错,即软件栈打通。
阶段二:获取项目并完成构建
克隆仓库并初始化 third_party(llama.cpp、llamafile 等内核源码都在这一步拉取,耗时较长且容易受网络影响,建议首次成功后打包备用):
git clone https://gitcode.com/gh_mirrors/ktr/ktransformers cd ktransformers git submodule update --init --recursiveARM 平台必须做一处适配:打开third_party/llamafile/iqk_mul_mat_arm82.cpp,把文件内iqk_mul_mat与iqk_mul_mat_moe两行#define注释掉,否则 Q4 矩阵乘会走未适配内核。然后执行构建,USE_BALANCE_SERVE=1启用负载均衡推理后端,USE_NUMA=1按 NUMA 拓扑绑定线程:
source /usr/local/Ascend/ascend-toolkit/set_env.sh USE_BALANCE_SERVE=1 USE_NUMA=1 bash ./install.sh验收点:编译无报错退出,npu-smi info能列出你的 300I A2 卡。
阶段三:合并权重与关键配置
精度和精度要求下需要两份权重:Q4_K_M 量化权重复责体积,W8A8 权重复责 NPU 上的 W8A8 低精度矩阵乘,最终只使用合并后的产物。用仓库自带脚本合并(脚本位置见 archive/merge_tensors/merge_safetensor_gguf.py):
python merge_safetensor_gguf.py \ --safetensor_path /mnt/weights/DeepSeek-R1-Q4_K_M \ --gguf_path /mnt/weights/DeepSeek-R1-W8A8 \ --output_path /mnt/weights/DeepSeek-R1-q4km-w8a8 # 最终使用的合并权重接着改一处关键配置:ktransformers/configs/config.yaml中 attn 段的page_size改为128、chunk_size改为16384。原因是 NPU 融合注意力算子torch_npu.npu_fused_infer_attention_score只支持 page_size=16/128,改错会导致注意力直接报错。
验收点:合并输出目录里能看到完整的 safetensors 分片与索引文件,且总大小约等于两份源权重中 Q4 部分。
阶段四:首次运行启动服务
NPU 部署依赖"图下沉":把算子图整段下发到 NPU 执行,前提是算子下发顺序严格有序,所以TASK_QUEUE_ENABLE=0不能省。把下面脚本放在仓库根目录(optimize_config_path 用了相对路径),替换权重路径后执行。优化配置选用 300I A2 专用规则 optimize_rules/npu/ 下的 DeepSeek-V3-Chat-300IA2-npu-serve.yaml:
#!/bin/bash export USE_MERGE=0 # 已手动合并权重 export INF_NAN_MODE_FORCE_DISABLE=1 export TASK_QUEUE_ENABLE=0 # 保证算子下发顺序有序,图下沉前提 source /usr/local/Ascend/ascend-toolkit/set_env.sh source /usr/local/Ascend/nnal/atb/set_env.sh python ktransformers/server/main.py \ --port 10002 \ --model_path /mnt/weights/DeepSeek-R1-q4km-w8a8 \ --gguf_path /mnt/weights/DeepSeek-R1-q4km-w8a8 \ --model_name DeepSeekV3ForCausalLM \ --optimize_config_path ./ktransformers/optimize/optimize_rules/npu/DeepSeek-V3-Chat-300IA2-npu-serve.yaml \ --max_new_tokens 1024 \ --cache_lens 20480 \ --max_batch_size 4 \ --use_cuda_graph \ --tp 1 \ --backend_type balance_serve验收点:服务启动后请求http://127.0.0.1:10002/v1/chat/completions,能收到逐 token 流式返回的连贯中文,说明 NPU/CPU 两侧权重加载与调度都正常。
验收:基准数据与调优优先级
测试条件:Atlas 300I A2 单卡、batch size=4、输出 1024 tokens。你的实测值应落在这个量级:
| 指标 | 1K 输入 | 2K 输入 | 4K 输入 |
|---|---|---|---|
| Prefill 吞吐(tokens/s) | 174.68 | 169.52 | 167.15 |
| Decode 吞吐(tokens/s) | 16.07 | 16.12 | 16.48 |
若实测偏低,按优先级处理:
- 内存带宽是第一瓶颈:确认机器物理内存 ≥400GB 且专家权重完整驻留,Swap 一旦介入 Decode 会掉到个位数。
- 保住图下沉收益:
TASK_QUEUE_ENABLE=0与--use_cuda_graph成对出现,任一缺失都会让算子回落到逐条下发,Prefill 明显缩水。 - 定位慢在哪一段:给启动脚本加
PROF_DECODE=1或PROF_PREFILL=1重跑,看 NPU 图与 CPU 专家的耗时占比,再决定调--cache_lens还是扩--cpu_infer线程数。
跑通 DeepSeek 之后,Qwen3-235B 的适配流程与本文基本一致,差异部分见 doc/zh/Qwen3-MoE_tutorial_zh_for_Ascend_NPU.md;完整部署细节与参数释义可对照 doc/zh/DeepseekR1_V3_tutorial_zh_for_Ascend_NPU.md。
排错速查:4个高频错误与一行修复
| 现象 | 原因 | 一行修复 |
|---|---|---|
ImportError: libhccl.so | CANN Toolkit 环境未加载 | source /usr/local/Ascend/ascend-toolkit/set_env.sh |
ImportError: libascend_hal.so | 驱动库路径不在搜索列表 | export LD_LIBRARY_PATH=/usr/local/Ascend/driver/lib64/driver:$LD_LIBRARY_PATH |
| torch_npu 版本校验失败 | 自编译包版本号残留 git 哈希 | 改torch_npu/version.py中__version__为2.5.1.post4 |
| ARM 上 Q4 矩阵乘结果异常 | arm82 内核未禁用 | 注释iqk_mul_mat_arm82.cpp中两行#define后重装 |
从 HDK 到服务起来,全流程一次跑通,你就在纯昇腾生态上拥有了一个吞吐稳定、可对外提供 API 的 671B MoE 推理服务。🚀
【免费下载链接】ktransformersA Flexible Framework for Experiencing Heterogeneous LLM Inference/Fine-tune Optimizations项目地址: https://gitcode.com/GitHub_Trending/ktr/ktransformers
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考