ChrisKim
Do not go gentle into that good night.
颢天

基于 vLLM 在昇腾 910B 平台完成大模型分布式推理

最近由于项目原因,拿到了 95 万元的华为云代金券。项目需要进行大规模的大模型推理生成任务,为了利用好华为云的资源,于是我研究了下如何在华为云的昇腾 910B 平台部署大模型。尽管没有成熟的 CUDA 平台方便,但实际上整个流程也没有太过于困难,本篇文章便简单分享一下部署经验吧。

注意:国产平台还在高速发展期,本文的操作流程只对当前版本负责,后续版本如果出现变化可能本文就不适用了。

1 本文内容

在华为国产计算平台,完成大模型多机多卡的高性能分布式推理:张量并行(Tensor Parallel)+流水线并行(Pipeline Parallel)+专家并行(Expert Parallel)。文章以 910B4 32G 为例(理论上所有昇腾 NPU 都可用),以 Qwen3 模型为例(理论上所有 vLLM 支持的模型都可用)。

2025/10/22 UPD: 已验证 2*8 卡 910B2 总计 1024GB 显存配置同样可成功部署。

项目使用华为云的 ModelArts 轻量算力集群产品,购买了 2 台 8 卡昇腾 910B4 进行分布式推理,单台配置如下:

类型规格
CPU4*鲲鹏 920 48核=192核
内存24*64GB=1.5TB
NPU8*昇腾 910B4 32G
磁盘3*7.68TB NVMe
网络2*100GE标准网卡+8*200GE卡间互联
系统EulerOS 2.0 (SP10)
驱动7.5.0.5.220-24.1.0.3
https://assets.zouht.com/img/blog/4119-01.webp

如果你要参照本文进行部署,请确保你使用的 CPU 为鲲鹏 920 且 NPU 为昇腾系列,且昇腾 NPU 配置了 RoCE 的高速互联网络。

本文主要参考文档:https://vllm-ascend.readthedocs.io/en/latest/quick_start.html。这个文档写得真的很不错,属于国产平台文档里写得很详尽的一档了,跟着走基本没出现什么问题。

2 环境配置

如果你要进行分布式多机多卡推理,那么每台节点都需要完成下面的环境配置操作。

2.1 安装 Docker

本文使用 Docker 进行部署,原因是 vLLM Ascend 提供了官方的 Docker 镜像,免去了繁琐的依赖库配置步骤,因此首先需要安装 Docker。

我购买服务器时直接选择了 Docker 作为容器引擎(默认是 contained),因此服务器初始化好后直接自带了 Docker。如果你的服务器还没有 Docker,可以使用软件包管理器安装:yum install docker

安装后查看 Docker 版本:docker -v ,本文使用的版本为 Docker version 18.09.0, build ca986cf

2.2 拉取 vLLM-Ascend 镜像

vLLM 是一款高性能的大模型推理框架,而 vLLM-Ascend 是 vLLM 的插件,用于支持昇腾平台。本文撰写时,最新的镜像是 quay.io/ascend/vllm-ascend:v0.11.0rc0,大家拉取时可以在文档中查找最新的版本拉取。

使用指令 docker pull quay.io/ascend/vllm-ascend:v0.11.0rc0 进行镜像拉取,镜像大小有 15GB ,可能得自行配置一下镜像站来加速拉取。

2.3 准备模型

自行下载需要运行的模型到节点中,模型格式为标准 Transformers 库的格式即可。如果你需要使用量化模型,请注意你并不能使用网上为 CUDA 平台量化的版本,下文会有说明。(最方便的还是使用原始精度)

本文使用 2*8 卡昇腾 910B4 总计 512GB 显存,为了测试方便,选择了 Qwen3-VL-30B-A3B-Instruct 这个参数量很小的模型。实际上该配置可以运行 235B 的量化版本了。

3 运行模型

3.1 单机多卡

3.1.1 启动 vLLM-Ascend 容器

使用以下指令启动 vLLM-Ascend 容器:

docker run --rm \
    --name vllm-ascend-env \
    --net=host \
    --device /dev/davinci0 \
    --device /dev/davinci1 \
    --device /dev/davinci2 \
    --device /dev/davinci3 \
    --device /dev/davinci4 \
    --device /dev/davinci5 \
    --device /dev/davinci6 \
    --device /dev/davinci7 \
    --device /dev/davinci_manager \
    --device /dev/devmm_svm \
    --device /dev/hisi_hdc \
    -v /usr/local/dcmi:/usr/local/dcmi \
    -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
    -v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
    -v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
    -v /etc/ascend_install.info:/etc/ascend_install.info \
    -v /root/.cache:/root/.cache \
    -v /data:/data \
    -it quay.io/ascend/vllm-ascend:v0.11.0rc0 bash

如果要控制使用哪几个 NPU,可以修改 --device 参数,这里选择将 8 张 NPU 全部传入容器。另外注意将下好模型的目录挂载到容器中,我的模型储存在 /data 目录下,因此使用 -v /data:/data 将整个 /data 目录挂载到容器内,这样容器就可以读取下好的模型了。

容器启动需要一段时间,运行该指令后,稍作等待应该就能进入容器内的命令行了(可以发现用户变成容器里的 root 了)。

https://assets.zouht.com/img/blog/4119-02.webp

如果要退出容器,则使用 exit 退出命令行即可。需要注意的是,除了挂载到容器内的目录,对其他目录的修改在退出容器后均不会保存。

3.1.2 升级 transformers 库(可选)

如果你使用的模型架构很新,有可能容器里的 transformers 库还没有支持,这种情况就需要升级 transformers 库的版本了。模型所需的最低 transformers 库版本一般在官方的模型仓库中会注明,可以自行检查是否兼容。

本文的容器版本中包含的 transformers 库版本为 4.56.2,而 Qwen3-VL 的模型架构在 4.57.0 版本才引入,因此没法直接运行,得用以下指令升级库版本:

pip install transformers==4.57.0 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple

注意,上文提到了除了挂载到容器内的目录,对其他目录的修改在退出容器后均不会保存,因此本次升级也不会保存。再退出容器后,下次启动还需要重新升级

3.1.3 运行模型

完成了一切准备操作,终于可以开始运行模型了!使用以下指令启动 vllm:

vllm serve /data/Qwen3-VL-30B-A3B-Instruct \
  --served-model-name qwen3-vl \
  --disable-uvicorn-access-log \
  --disable-log-requests \
  --tensor-parallel-size 8 \
  --enable-expert-parallel \
  --max-model-len 32768  \
  --gpu-memory-utilization 0.9

第一行的模型路径需要修改为自己保存模型的路径,请确保该路径已经挂载到容器内,第二行设定了模型的名称。--tensor-parallel-size 参数指定了张量并行大小,服务器有 8 张 NPU 因此设定为 8。

另外,如果你使用的是混合专家模型(MoE),那么你还可以使用专家并行。向启动参数中添加 --enable-expert-parallel 即可开启该功能,例如:

出现以下消息时,就说明模型启动成功了。

https://assets.zouht.com/img/blog/4119-03.webp

如果你需要使用量化模型,请注意:你并不能直接使用网上为 CUDA 平台量化的版本,而是需要下载专为昇腾平台量化的 W8A8 版本,或是参考文档自行完成原始精度模型的量化,启动量化模型时,还需要在指令中添加 --quantization ascend 参数。

3.1.4 测试模型

启动后,vLLM 服务将在本地 8000 端口提供,http://localhost:8000/v1 便是 base_url,编写代码或者用大模型客户端即可进行连接了。这里提供一份我写的测试代码,用 Python 运行就可以快速测试模型效果了。

import argparse

from openai import OpenAI


def main():
    client = OpenAI(api_key=args.token, base_url=args.base_url)

    response = client.chat.completions.create(
        model=args.model,
        messages=[{"role": "user", "content": args.prompt}],
        max_completion_tokens=args.max_completion_tokens,
        temperature=args.temperature,
        stream=True
    )

    is_thinking = False

    for chunk in response:
        response_delta = chunk.choices[0].delta

        if hasattr(response_delta, 'content') and response_delta.content is not None:
            if is_thinking:
                is_thinking = False
                print("</think>")
            print(response_delta.content, end='', flush=True)

        if hasattr(response_delta, 'reasoning_content') and response_delta.reasoning_content is not None:
            if not is_thinking:
                is_thinking = True
                print("<think>")
            print(response_delta.reasoning_content, end='', flush=True)


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--base-url', type=str, default='http://localhost:8000/v1')
    parser.add_argument('--token', type=str, default='')
    parser.add_argument('--model', type=str, default='qwen3-vl')
    parser.add_argument('--max-completion-tokens', type=int, default=1024 * 8)
    parser.add_argument('--temperature', type=float, default=0.6)
    parser.add_argument('--prompt', type=str, default='介绍一下大语言模型是什么。')
    args = parser.parse_args()
    main()
https://assets.zouht.com/img/blog/4119-04.webp

3.2 多机多卡

3.2.1 测试互联网络

多级多卡分布式推理需要用到标准以太网络来进行进程交互,也需要用到 RoCE 网络完成高速卡间互联。

(1)测试标准以太网络

使用 ifconfig 指令查询节点的 IP 地址,本文两台节点的内网 IP 分别是 192.168.0.147192.168.0.35,互相 Ping 一下确认连通性就行了:

# 在 node 0 运行
ping 192.168.0.35
# 在 node 1 运行
ping 192.168.0.147

(2)测试 RoCE 网络

测试 RoCE 网络配置是否正常,使用以下指令测试,确保输出没有报错即可:

# Check the remote switch ports
for i in {0..7}; do hccn_tool -i $i -lldp -g | grep Ifname; done 
# Get the link status of the Ethernet ports (UP or DOWN)
for i in {0..7}; do hccn_tool -i $i -link -g ; done
# Check the network health status
for i in {0..7}; do hccn_tool -i $i -net_health -g ; done
# View the network detected IP configuration
for i in {0..7}; do hccn_tool -i $i -netdetect -g ; done
# View gateway configuration
for i in {0..7}; do hccn_tool -i $i -gateway -g ; done
# View NPU network configuration
cat /etc/hccn.conf

接下来查看节点的 RoCE 网卡 IP 地址,使用以下指令:

for i in {0..7}; do hccn_tool -i $i -ip -g | grep ipaddr; done

我的输出如下,每个节点的 8 个 IP 分别对应着 8 张 NPU:

# node 0 输出
ipaddr:29.74.153.181
ipaddr:29.74.161.19
ipaddr:29.74.191.70
ipaddr:29.74.135.46
ipaddr:29.74.13.110
ipaddr:29.74.159.60
ipaddr:29.74.11.174
ipaddr:29.74.138.7

# node 1 输出
ipaddr:29.74.42.211
ipaddr:29.74.80.82
ipaddr:29.74.66.31
ipaddr:29.74.137.124
ipaddr:29.74.123.170
ipaddr:29.74.159.58
ipaddr:29.74.62.133
ipaddr:29.74.28.3

接下来就可以测试一下连通性了,随便挑一个节点,向另一个节点的 IP 发送 Ping 就行了,用以下指令:

# node 0 -> node 1
hccn_tool -i 0 -ping -g address 29.74.42.211
# node 1 -> node 0
hccn_tool -i 0 -ping -g address 29.74.153.181

3.2.2 启动 vLLM-Ascend 容器

同 3.1.1 中的内容,注意每台节点均需要启动。

3.2.3 升级 transformers 库(可选)

同 3.1.2 中的内容,注意每台节点均需要操作。

3.2.4 启动 Ray

Ray 是一款机器学习分布式框架,vLLM 使用该框架完成分布式推理,在启动 vLLM 之前需要先在每个节点上启动 Ray。

Ray 节点分为两种:

  • Head Node:提供计算资源,负责完成分布式任务,同时负责整个分布式任务的调度。
  • Worker Node:仅提供计算资源,负责完成分布式任务。

本文一共两台节点,因此一台作为 Head,一台作为 Worker。如果你要部署更大规模的并行推理,那么只需要一台作为 Head,其他作为 Worker 即可。

(1)启动 Head 节点

vLLM-Ascend 容器已经配置好了 Ray 环境,在容器中运行以下命令启动 Ray:

# Head node
export HCCL_IF_IP=【本地IP地址】
export GLOO_SOCKET_IFNAME=【网卡名】
export TP_SOCKET_IFNAME=【网卡名】
export RAY_EXPERIMENTAL_NOSET_ASCEND_RT_VISIBLE_DEVICES=1
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
ray start --head

注意将本地 IP 地址和网卡名替换为该节点的真实值,可以使用 ifconfig 命令查看。

Ray 是后台进程,运行完后就会退出,没有报错就是成功运行:

https://assets.zouht.com/img/blog/4119-05.webp

(2)启动 Worker 节点

在另一个节点的 vLLM-Ascend 容器中运行以下命令启动 Ray:

# Worker node
export HCCL_IF_IP=【本地IP地址】
export GLOO_SOCKET_IFNAME=【网卡名】
export TP_SOCKET_IFNAME=【网卡名】
export RAY_EXPERIMENTAL_NOSET_ASCEND_RT_VISIBLE_DEVICES=1
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
ray start --address='【Head节点的IP地址】:6379' --node-ip-address=【本地IP地址】

注意将本地 IP 地址、网卡名、Head节点的 IP 地址替换为真实值。

Ray 是后台进程,运行完后就会退出,没有报错就是成功运行:

https://assets.zouht.com/img/blog/4119-06.webp

3.2.5 运行模型(TP张量并行)

如果你选择无论节点内和节点间,均使用张量并行策略,则使用以下指令启动 vllm:(该指令只需要Head 节点的容器内运行,Worker 节点会自动收到任务调度)

vllm serve /data/Qwen3-VL-30B-A3B-Instruct \
  --served-model-name qwen3-vl \
  --disable-uvicorn-access-log \
  --disable-log-requests \
  --distributed-executor-backend ray \
  --tensor-parallel-size 16 \
  --max-model-len 32768  \
  --gpu-memory-utilization 0.9

第一行的模型路径需要修改为自己保存模型的路径,请确保该路径已经挂载到容器内,第二行设定了模型的名称。--tensor-parallel-size 参数指定了张量并行大小,每个节点有 8 张 NPU,一共 2 个节点,因此设定为 16.

模型成功启动后,可以看到两台节点的 NPU 均有显存占用:

https://assets.zouht.com/img/blog/4119-07.webp

如果你需要使用量化模型,请注意:你并不能直接使用网上为 CUDA 平台量化的版本,而是需要下载专为昇腾平台量化的 W8A8 版本,或是参考文档自行完成原始精度模型的量化,启动量化模型时,还需要在指令中添加 --quantization ascend 参数。

3.2.6 运行模型(TP张量并行+PP流水线并行)

如果你选择在节点内使用张量并行策略,在节点间使用流水线并行策略,则使用以下指令启动 vllm:(该指令只需要Head 节点的容器内运行,Worker 节点会自动收到任务调度)

vllm serve /data/Qwen3-VL-30B-A3B-Instruct \
  --served-model-name qwen3-vl \
  --disable-uvicorn-access-log \
  --disable-log-requests \
  --distributed-executor-backend ray \
  --pipeline-parallel-size 2 \
  --tensor-parallel-size 8 \
  --max-model-len 32768  \
  --gpu-memory-utilization 0.9

第一行的模型路径需要修改为自己保存模型的路径,请确保该路径已经挂载到容器内,第二行设定了模型的名称。--pipeline-parallel-size 参数指定了流水线并行大小,一共 2 个节点,因此设定为 2,--tensor-parallel-size 参数指定了张量并行大小,每个节点有 8 张 NPU,因此设定为 8.

如果你需要使用量化模型,请注意:你并不能直接使用网上为 CUDA 平台量化的版本,而是需要下载专为昇腾平台量化的 W8A8 版本,或是参考文档自行完成原始精度模型的量化,启动量化模型时,还需要在指令中添加 --quantization ascend 参数。

3.2.7 运行模型(EP专家并行)

如果你使用的是混合专家模型(MoE),那么你还可以使用专家并行。向启动参数中添加 --enable-expert-parallel 即可开启该功能,例如:

vllm serve /data/Qwen3-VL-30B-A3B-Instruct \
  --served-model-name qwen3-vl \
  --disable-uvicorn-access-log \
  --disable-log-requests \
  --distributed-executor-backend ray \
  --tensor-parallel-size 16 \
  --enable-expert-parallel \
  --max-model-len 32768  \
  --gpu-memory-utilization 0.9

不过需要注意的是,目前的版本如果将流水线并行和专家并行一起使用,模型无法正常启动,这有可能是 bug。

3.2.8 测试模型

同 3.1.4 中的内容,注意模型服务是在 Head 节点提供的,因此需要在 Head 节点连接模型。

4 效率测试

接下来评估不同并行方式的模型推理效率差异,评估不算严谨,仅供参考。以下评估均使用代码 256 线程请求模型进行压力测试,查看 vLLM 界面的吞吐量日志,模型均为 Qwen3-VL-30B-A3B-Instruct。

(1)单机多卡 TP:输出速度大约为 2500 token/s.

https://assets.zouht.com/img/blog/4119-12.webp

(2)单机多卡 TP+EP:输出速度大约为 2500 token/s.

https://assets.zouht.com/img/blog/4119-08.webp

(3)多机多卡 TP:输出速度大约为 2200 token/s,较单机下降了大约 12%.

https://assets.zouht.com/img/blog/4119-09.webp

(4)多机多卡 TP+PP:输出速度大约为 1800 token/s,较单机下降了大约 28%.

https://assets.zouht.com/img/blog/4119-10.webp

(5)多多卡 TP+EP:输出速度大约为 2100 token/s,较单机下降了大约 16%.

https://assets.zouht.com/img/blog/4119-11.webp

综上,可以看到由于节点间的通信延迟,只要是使用了多机分布式推理,都会产生 10% 以上的性能下降,最高甚至下降了 28%。因此如果模型能够在单机容纳,则不要使用分布式推理(不过可以使用本文没提到的 DP 分布式,这种不存在多机损耗)。

本文链接:https://www.zouht.com/4119.html
本文使用:CC BY-NC-SA 4.0 许可
# # # # # # #
首页      教程      基于 vLLM 在昇腾 910B 平台完成大模型分布式推理

发表回复

textsms
account_circle
email

颢天

基于 vLLM 在昇腾 910B 平台完成大模型分布式推理
最近由于项目原因,拿到了 95 万元的华为云代金券。项目需要进行大规模的大模型推理生成任务,为了利用好华为云的资源,于是我研究了下如何在华为云的昇腾 910B 平台部署大模型。尽管没有…
扫描二维码继续阅读
2025-10-18