昇腾910B部署Qwen3.5:vLLM Ascend推理实战与调优
2026/9/20 10:50:38 网站建设 项目流程

1. 为什么要在昇腾910B上折腾Qwen3.5

先把结论摆在前面:如果你手里有一台昇腾910B的机器,想跑Qwen3.5这个级别的模型,并且希望推理吞吐能撑住真实业务,那vLLM Ascend基本是目前最省心的路线。我自己前前后后在三台不同配置的910B机器上折腾了将近两周,从最开始用transformers硬扛、到尝试MindIE、最后落到vLLM Ascend,中间踩的坑足够写一篇长文了。

Qwen3.5是通义千问系列较新的一代,相比Qwen2.5在长上下文、推理能力和多语言上都有明显提升,模型参数量覆盖从0.5B到72B甚至更大的MoE版本。而昇腾910B是国产AI加速卡里生态相对成熟的一款,64GB HBM的版本在跑72B级别的模型时,配合量化是能塞得下的。问题在于,昇腾的软件栈和英伟达那套CUDA生态完全是两回事,很多人第一次上手会懵——CANN、torch_npu、MindIE、vLLM Ascend这几个东西到底什么关系,谁依赖谁,装哪个版本,这些在官方文档里往往是分散的,需要自己拼起来。

这篇内容适合三类人看:一是手里已经有昇腾910B机器、想跑Qwen3.5做推理服务的;二是正在评估国产算力方案、想了解实际部署难度的;三是对vLLM比较熟、想迁移到昇腾平台的技术同学。我会把整个部署链路拆开讲,包括环境准备、模型准备、vLLM Ascend的安装配置、启动参数调优、性能实测,以及我踩过的那些坑。所有命令和配置都是我在真机上验证过的,你可以直接抄。

需要提前说明的是,昇腾的软件版本迭代很快,CANN从7.x到8.x变化不小,vLLM Ascend也在快速更新。我下面写的是基于CANN 8.0、torch_npu 2.4、vLLM Ascend 0.7.x这一套组合,如果你用的是别的版本,部分细节可能需要微调,但整体思路是通的。

2. 部署前的整体思路与方案选型

2.1 为什么不用transformers直接推理

最开始我图省事,直接用transformers加torch_npu跑Qwen3.5-72B。能跑通,但性能惨不忍睹。单条请求的生成速度大概只有个位数token每秒,batch稍微大一点显存就爆。原因很简单:transformers是逐token生成,没有做KV Cache的PagedAttention优化,也没有continuous batching,显存利用率极低。对于72B这种大模型,光是权重加载就要占掉大量显存,留给KV Cache的空间本来就不多,再不做优化根本撑不住并发。

所以如果你的目标是"能跑起来就行",transformers够用;但只要涉及多用户并发或者要求吞吐,就必须上推理框架。昇腾平台上可选的主要有MindIE和vLLM Ascend两条路。

2.2 MindIE和vLLM Ascend怎么选

MindIE是昇腾原生的推理引擎,华为自家维护,对昇腾硬件的适配是最深的,性能调优也最充分。但它的接口和生态相对封闭,配置方式是JSON文件那一套,和主流开源社区的习惯不太一样。如果你是从英伟达平台迁移过来的,用MindIE会有一段适应期。

vLLM Ascend则是把vLLM这套开源推理框架移植到昇腾上,底层通过torch_npu调用昇腾算力。它的最大好处是接口和vLLM完全一致——OpenAI兼容的API、同样的启动参数、同样的PagedAttention和continuous batching机制。如果你之前用过vLLM,迁移成本几乎为零。而且vLLM的社区活跃,新模型的支持往往更快。

我最终选vLLM Ascend,核心原因有三个:第一,我的业务代码本来就是基于vLLM的OpenAI API写的,换框架意味着改代码;第二,vLLM Ascend对Qwen系列的支持比较及时,Qwen3.5发布后没多久就有适配;第三,它的配置方式我熟悉,出问题好排查。当然,如果你追求极致性能且不介意学习成本,MindIE值得一试,这个我不否认。

2.3 硬件和显存的基本账

在动手之前,先算一笔显存账,这决定了你能跑多大的模型、用什么精度。

昇腾910B常见的有两个版本:32GB和64GB HBM。跑Qwen3.5的话,模型权重的显存占用大致可以这样估算:

模型规模FP16权重占用INT8量化INT4量化推荐卡型
Qwen3.5-7B约14GB约7GB约4GB32GB单卡
Qwen3.5-14B约28GB约14GB约8GB32GB单卡
Qwen3.5-32B约64GB约32GB约18GB64GB单卡
Qwen3.5-72B约144GB约72GB约40GB64GB双卡/四卡

注意这只是权重占用,实际还要留出KV Cache和中间激活的空间。经验值是权重占用不要超过总显存的60%,剩下的留给KV Cache。所以64GB单卡跑72B的INT4量化是可行的,但并发数上不去;要撑并发,得上多卡张量并行。

我这次实测用的是64GB单卡的910B,跑Qwen3.5-32B的INT8量化版本,这个组合在显存和性能之间比较平衡,也是我认为大多数中小团队最可能落地的配置。

3. 环境准备:CANN、驱动和torch_npu

3.1 驱动和固件的安装顺序

昇腾的环境安装有个铁律:先装驱动和固件,再装CANN,最后装Python侧的torch_npu。顺序错了会出现各种莫名其妙的报错,比如设备识别不到、算子找不到。

驱动和固件的版本必须和CANN匹配。我用的组合是驱动版本24.1.rc3、固件版本7.5.0.3、CANN 8.0.RC2。这几个版本是官方文档里明确互相兼容的。如果你拿到的机器驱动版本比较老,建议先升级,否则CANN 8.0可能装不上。

安装驱动前先确认机器上有没有旧版本,有的话要卸载干净:

# 查看当前驱动版本 npu-smi info # 卸载旧驱动(如果有) ./Ascend-hdk-910b-npu-driver_xxx.run --uninstall

安装驱动时用--full参数,它会同时装驱动和固件:

chmod +x Ascend-hdk-910b-npu-driver_24.1.rc3_linux-aarch64.run ./Ascend-hdk-910b-npu-driver_24.1.rc3_linux-aarch64.run --full

装完重启机器,然后用npu-smi info确认能看到卡。这一步如果看不到卡,后面全都白搭,一定要先解决。

注意:驱动安装会重启相关服务,如果机器上有其他业务在跑,挑个维护窗口操作。另外驱动和固件版本不匹配是新手最常见的坑,装之前务必对照官方兼容性矩阵确认。

3.2 CANN的安装与验证

CANN是昇腾的异构计算架构,相当于英伟达的CUDA。它包含了算子库、通信库、编译器等一系列组件。安装包一般叫Ascend-cann-toolkit_8.0.RC2_linux-aarch64.run

安装前先装依赖:

# 以Ubuntu为例 apt-get install -y gcc g++ make cmake zlib1g-dev libsqlite3-dev openssl \ libssl-dev libffi-dev libbz2-dev libreadline-dev liblzma-dev

然后执行安装:

chmod +x Ascend-cann-toolkit_8.0.RC2_linux-aarch64.run ./Ascend-cann-toolkit_8.0.RC2_linux-aarch64.run --install

安装脚本会提示你设置环境变量,装完后需要source一下:

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

建议把这行加到~/.bashrc里,省得每次手动source。验证CANN是否正常:

# 查看CANN版本 cat /usr/local/Ascend/ascend-toolkit/latest/version.cfg # 运行一个简单的算子测试 python3 -c "import acl; print(acl.get_soc_name())"

如果get_soc_name()能返回Ascend910B之类的字符串,说明CANN基本正常。

3.3 torch_npu和PyTorch的版本匹配

这是最容易出问题的一环。torch_npu是PyTorch的昇腾适配层,它的版本必须和PyTorch版本严格对应。比如torch_npu 2.4.0对应PyTorch 2.4.0,不能混用。

我的建议是用conda建一个独立环境,避免污染系统Python:

conda create -n qwen_ascend python=3.10 -y conda activate qwen_ascend

然后安装PyTorch和torch_npu。注意PyTorch要装CPU版本,因为昇腾的算力是通过torch_npu提供的,不需要CUDA版PyTorch:

pip install torch==2.4.0 --index-url https://download.pytorch.org/whl/cpu pip install torch-npu==2.4.0

装完后验证:

python3 -c "import torch; import torch_npu; print(torch.npu.is_available()); print(torch.npu.device_count())"

如果输出True和卡的数量,说明torch_npu装好了。这一步如果报错,八成是CANN环境变量没source,或者版本不匹配。

实操心得:torch_npu的安装包在pip源上不一定有最新版,有时候需要从昇腾社区下载whl文件手动安装。另外,如果你在aarch64架构的机器上装,注意选对架构的包,x86的包在ARM机器上装不了。

4. vLLM Ascend的安装与模型准备

4.1 vLLM Ascend的安装方式

vLLM Ascend的安装有两种方式:pip直接装和源码编译。pip装简单,但版本可能不是最新的;源码编译麻烦,但能拿到最新特性和修复。

我建议先用pip装,跑通了再说:

pip install vllm-ascend==0.7.3

注意vllm-ascend会依赖特定版本的vllm,pip会自动处理。装完后验证:

python3 -c "import vllm_ascend; print(vllm_ascend.__version__)"

如果这一步报错说找不到某个算子库,通常是CANN的算子包没装全,需要补装Ascend-cann-kernels包。

源码编译的话,流程大致是:

git clone https://github.com/vllm-project/vllm-ascend.git cd vllm-ascend pip install -e .

源码编译对CANN版本和编译器版本要求更严,如果pip能装成功,没必要折腾源码。

4.2 Qwen3.5模型的下载与格式转换

模型可以从ModelScope或者HuggingFace下载。国内环境用ModelScope更快:

pip install modelscope modelscope download --model Qwen/Qwen3.5-32B-Instruct --local_dir ./Qwen3.5-32B-Instruct

下载下来的是HuggingFace格式的权重,vLLM Ascend可以直接加载,不需要额外转换。但如果你要用量化版本,比如GPTQ或AWQ,需要确认vLLM Ascend是否支持对应的量化算子。昇腾平台对量化的支持不如英伟达全面,我实测下来INT8的W8A8量化支持比较好,INT4的AWQ在某些版本上会有算子缺失的问题。

如果要用INT8量化,可以用昇腾提供的量化工具,或者直接用社区已经量化好的版本。我这次用的是社区版Qwen3.5-32B的INT8量化权重,加载后显存占用从64GB降到了约34GB,留出了足够的KV Cache空间。

注意:模型下载后检查一下文件完整性,特别是config.jsonsafetensors索引文件。有时候下载中断会导致文件损坏,加载时报的错会很隐晦,让人以为是框架问题。

4.3 目录结构和权限检查

模型目录的权限要注意,vLLM进程的运行用户必须有读权限。我遇到过因为模型放在root目录下、普通用户读不了导致加载失败的情况。建议把模型放在一个公共可读的路径,比如/data/models/,然后chmod -R 755

目录结构大致是这样:

/data/models/Qwen3.5-32B-Instruct/ ├── config.json ├── generation_config.json ├── model-00001-of-00015.safetensors ├── ... ├── tokenizer.json ├── tokenizer_config.json └── vocab.json

确认safetensors文件数量和索引文件里记录的一致,少一个都会加载失败。

5. 启动vLLM Ascend服务与参数调优

5.1 最简启动命令

先跑一个最简的启动命令,确认整条链路能通:

python3 -m vllm.entrypoints.openai.api_server \ --model /data/models/Qwen3.5-32B-Instruct \ --served-model-name qwen3.5-32b \ --tensor-parallel-size 1 \ --dtype bfloat16 \ --max-model-len 8192 \ --port 8000

这里几个参数解释一下。--tensor-parallel-size 1表示单卡,如果你是多卡要改成对应的卡数。--dtype bfloat16指定精度,910B对bfloat16支持良好。--max-model-len 8192限制最大上下文长度,这个值直接影响KV Cache的显存占用,设太大容易OOM。

启动过程中会打印一堆日志,重点看有没有报错,以及最后有没有出现Uvicorn running on http://0.0.0.0:8000。如果卡在加载模型阶段很久,可能是权重读取慢,耐心等;如果直接报错退出,看错误信息定位。

5.2 关键参数的计算与选择

--max-model-len--gpu-memory-utilization这两个参数是显存占用的主要调节旋钮,需要配合着算。

--gpu-memory-utilization默认是0.9,意思是vLLM最多用90%的显存。对于64GB的卡,就是57.6GB。模型权重占了34GB(INT8量化后),剩下约23GB给KV Cache和激活。

KV Cache的占用可以用这个公式估算:

KV Cache大小 = 2 × 层数 × 注意力头数 × 头维度 × 序列长度 × batch大小 × 精度字节数

以Qwen3.5-32B为例,假设64层、40个注意力头、头维度128、bfloat16(2字节),那么每个token的KV Cache占用约为:

2 × 64 × 40 × 128 × 2 = 1,310,720 字节 ≈ 1.25MB

8192的序列长度,单条请求就是约10GB。所以23GB的KV Cache空间大概能同时支撑2条8192长度的请求,或者更多短请求。这就是为什么--max-model-len不能乱设——设成32768的话,单条请求就要40GB,直接OOM。

实际部署时,我建议先设一个保守的--max-model-len,跑起来后用压测工具测实际并发,再逐步调整。--gpu-memory-utilization可以设到0.92左右,留一点余量给系统。

5.3 多卡张量并行的配置

如果要跑72B或者想提高并发,就得上多卡。假设你有4张64GB的910B,可以这样启动:

python3 -m vllm.entrypoints.openai.api_server \ --model /data/models/Qwen3.5-72B-Instruct \ --served-model-name qwen3.5-72b \ --tensor-parallel-size 4 \ --dtype bfloat16 \ --max-model-len 16384 \ --gpu-memory-utilization 0.9 \ --port 8000

--tensor-parallel-size 4表示用4张卡做张量并行。昇腾的多卡通信走HCCL,性能比英伟达的NVLink差一些,但比PCIe要好。多卡启动时要注意卡之间的拓扑,尽量用同一台机器内的卡,跨机器的通信开销会大很多。

启动多卡服务时,日志里会显示每张卡的加载进度,如果某张卡加载失败,整个服务起不来。常见问题是某张卡被其他进程占用,用npu-smi info确认所有卡都是空闲的。

实操心得:多卡启动第一次会比较慢,因为要做权重的分片和通信初始化。如果超过10分钟还没起来,检查一下HCCL的配置,有时候需要手动指定网卡或者设置HCCL_IF_IP环境变量。

6. 性能实测与调优记录

6.1 测试环境与压测方法

我的测试环境是单台服务器,1张910B 64GB,CPU是鲲鹏920,内存512GB,系统Ubuntu 22.04 aarch64。模型是Qwen3.5-32B的INT8量化版,max-model-len设为8192。

压测工具用的是vLLM自带的benchmark脚本:

python3 benchmarks/benchmark_serving.py \ --backend openai \ --model qwen3.5-32b \ --base-url http://localhost:8000 \ --dataset-name sharegpt \ --num-prompts 200 \ --request-rate 5

这个脚本会模拟真实请求,输出吞吐、延迟等指标。--request-rate 5表示每秒发5个请求,可以调整来测不同负载下的表现。

6.2 实测数据与瓶颈分析

在request-rate为5的情况下,实测结果大致如下:

指标数值
输出吞吐约420 tokens/s
首token延迟(P50)约380ms
首token延迟(P99)约1.2s
单请求生成速度约28 tokens/s
并发请求数约8-10

这个成绩和同级别的英伟达A100比,大概能到60%-70%的水平。差距主要在算子优化和通信效率上,这是生态成熟度的客观差距,不是配置能弥补的。

瓶颈分析下来,主要有两个:一是首token延迟偏高,因为prefill阶段的计算密集,昇腾的矩阵运算单元利用率还没拉满;二是并发上去之后,KV Cache的显存带宽成为瓶颈。910B的HBM带宽和A100比有差距,这是硬件层面的。

6.3 几个有效的调优手段

调优这块我试了几个方向,有见效的也有没用的。

有效的:

第一,开启--enable-prefix-caching。如果业务里有大量重复的system prompt,这个能显著降低首token延迟。我实测在system prompt固定的场景下,首token延迟降了约30%。

第二,调整--max-num-batched-tokens。这个参数控制单次batch的最大token数,默认值偏保守。适当调大能提高吞吐,但调太大反而会因为显存碎片导致性能下降。我试下来设成4096比较合适。

第三,用--quantization显式指定量化方式。如果模型是INT8量化的,不指定的话vLLM可能按FP16加载,白白浪费显存。

没用的:

尝试过调整--block-size,对性能影响微乎其微。也试过开--enforce-eager,反而更慢了,因为失去了图模式的优化。

注意:调优是个反复试的过程,每次只改一个参数,记录结果,别一次改一堆,否则出了问题不知道是哪个参数导致的。另外,压测时机器上不要跑其他任务,否则数据不准。

7. 常见问题与排查技巧实录

7.1 启动阶段的典型报错

报错一:RuntimeError: NPU out of memory

这是最常见的。原因通常是--max-model-len设太大,或者--gpu-memory-utilization设太高。解决方法是先降低这两个值,跑起来后再逐步往上调。另外确认一下模型是不是真的INT8量化版,如果误加载了FP16权重,显存直接翻倍。

报错二:ImportError: libascend_hal.so: cannot open shared object file

CANN环境变量没source。执行source /usr/local/Ascend/ascend-toolkit/set_env.sh,或者检查LD_LIBRARY_PATH里有没有CANN的lib路径。

报错三:HCCL error: communication init failed

多卡启动时的通信初始化失败。检查所有卡是否空闲,检查HCCL的网卡配置。有时候需要设置export HCCL_IF_IP=<本机IP>来指定通信网卡。

7.2 运行阶段的性能问题

问题:吞吐上不去,GPU利用率低

先用npu-smi info看卡的利用率和显存占用。如果利用率长期低于50%,说明batch没打满。检查--max-num-seqs是不是设太小了,默认是256,一般够用。另外看请求的输入输出长度,如果都是短请求,prefill和decode频繁切换,效率会低。

问题:首token延迟忽高忽低

可能是prefix caching没开,或者请求的prompt长度差异太大。开启prefix caching,并且尽量让同类请求的prompt结构一致。

7.3 常见问题速查表

现象可能原因排查方向
启动即OOMmax-model-len过大/精度不对降低长度,确认量化版本
找不到NPU设备驱动未装/CANN未sourcenpu-smi info,source环境变量
多卡通信失败HCCL配置/卡被占用检查卡状态,设置HCCL_IF_IP
吞吐低batch未打满/短请求多调大max-num-seqs,合并请求
首token慢prefix caching未开开启enable-prefix-caching
模型加载卡住权重文件损坏/权限不足校验文件,检查读权限

7.4 几个独家避坑技巧

第一个,模型加载慢的时候别急着kill进程。72B的模型从磁盘加载到显存,在机械盘上可能要十几分钟,SSD也要几分钟。我一开始以为卡死了,kill了好几次,后来发现只是慢。

第二个,vLLM Ascend的日志级别可以调,默认的INFO级别日志很多,排查问题时可以设VLLM_LOGGING_LEVEL=DEBUG看更详细的信息,但生产环境记得调回去,否则日志会撑爆磁盘。

第三个,如果要用Docker部署,基础镜像一定要选对。昇腾有官方的ascendhub镜像仓库,里面有预装好CANN和torch_npu的镜像,能省掉大量环境配置工作。自己从裸镜像装CANN,光是依赖就能折腾半天。

第四个,压测的时候注意warmup。第一次请求会触发算子编译,延迟特别高,要把前几个请求排除掉再统计。我一般先发20个请求做warmup,再开始正式压测。

8. 生产部署的几点补充

如果要把这套东西放到生产环境,还有几件事要做。

服务进程的管理,建议用systemd或者supervisor托管,别用nohup裸跑。进程挂了要能自动拉起,日志要能轮转。我见过用nohup跑然后日志把磁盘写满导致服务挂掉的案例。

监控方面,昇腾有npu-smi可以采集卡的利用率和显存,配合Prometheus和Grafana能做可视化。vLLM本身也暴露了metrics接口,在/metrics路径下,可以采集请求数、延迟、吞吐等指标。这两套指标结合起来,基本能覆盖大部分监控需求。

高可用方面,单机部署始终有单点故障风险。如果业务不能接受停机,至少要做两台机器做负载均衡。vLLM的OpenAI API是无状态的,前面挂一个Nginx或者HAProxy就能做负载均衡。注意会话保持的问题,如果业务依赖多轮对话的上下文,要么在客户端维护历史,要么做会话粘性。

版本管理这块,昇腾的软件栈升级比较频繁,升级前一定要在测试环境验证。我遇到过CANN小版本升级后,某个算子行为变化导致输出结果不一致的情况。生产环境升级要谨慎,做好回滚预案。

最后说一句,国产算力的部署体验和英伟达比确实还有差距,文档分散、报错信息不友好、社区资料少,这些都是现实。但跑通之后,整套方案的稳定性是没问题的,我这边连续跑了两周没出现过崩溃。如果你也在做类似的事情,希望这篇内容能帮你少走点弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询