双机 Atlas 800T A2 部署大模型

从环境初始化到 Ray 分布式多节点部署 DeepSeek V4 Flash 的完整记录
华为 Ascend 910B2 · vLLM + Ray · 2026-08

前言:硬件配置

公司提供了两台华为 Atlas 800T A2 训练服务器作为生产环境,本文完整记录了从裸机环境检查、CANN 驱动安装、vLLM 部署到 Ray 分布式多节点推理的整个过程。目标模型为 DeepSeek V4 Flash(W8A8 量化版),采用张量并行(TP)+ 流水线并行(PP)+ 数据并行(DP)的多维并行策略,最终在双机 16 卡 NPU 上实现稳定推理服务。

两台服务器的硬件配置完全一致,规格如下:

配置项规格
实例类型physical.lcas910b.2xlarge11
CPU4 路 × 48 核 × 48 线程(共 192 核,192 线程)
内存1536 GB
GPU8 × Huawei Ascend 910B2
本地系统盘2 × 480 GB(SSD)
本地数据盘2 × 3200 GB(NVMe SSD)

硬件要点

  • Ascend 910B2 是华为面向 AI 训练和推理的高性能 NPU,单卡算力约 310 TFLOS(FP16)。双机共 16 张卡,每台机器 8 张卡通过 HCCL(Huawei Collective Communication Library)进行卡间高速集合通信,机器间通过 RoCE 网络互联。

  • NVMe 数据盘 提供大容量本地存储(6.4TB/台),用于存放模型权重文件,避免网络存储的 I/O 瓶颈。


单机环境检查

在开始任何安装之前,首先确认操作系统的版本、内核架构以及 NPU 驱动是否已正确识别。所有操作均在 root 用户下执行(hostname 为 ctyun-gpu-atlas-01)。

操作系统与内核

[root@ctyun-gpu-atlas-01 ~]# cat /etc/os-release
NAME="CTyunOS"
VERSION="22.06"
ID="ctyunos"
VERSION_ID="22.06"
PRETTY_NAME="CTyunOS 22.06"
ANSI_COLOR="0;31"

[root@ctyun-gpu-atlas-01 ~]#
[root@ctyun-gpu-atlas-01 ~]# uname -a
Linux ctyun-gpu-atlas-01 4.19.90-2102.2.0.0068.3.ctl2.aarch64 #1 SMP Thu Jun 13 00:10:29 UTC 2024 aarch64 aarch64 aarch64 GNU/Linux
[root@ctyun-gpu-atlas-01 ~]#
[root@ctyun-gpu-atlas-01 ~]# npu-smi -v
npu-smi version: 25.2.0
[root@ctyun-gpu-atlas-01 ~]#
[root@ctyun-gpu-atlas-01 ~]# lspci -n -D | grep -o '19e5:d[0-9a-f]\{3\}' | head -n1 | cut -d: -f2
d802

命令参数说明:

命令说明
cat /etc/os-release查看操作系统发行版信息。CTyunOS 是天翼云基于 openEuler 定制的服务器操作系统
uname -a显示内核版本和 CPU 架构。aarch64 表明是 ARM64 架构(鲲鹏处理器)
npu-smi -v查看 NPU 系统管理接口版本,类似 NVIDIA 的 nvidia-smi。版本 25.2.0 表示驱动已预装
lspci -n -D | grep -o '19e5:d...'通过 PCI 设备 ID 识别 NPU 型号。19e5 是华为的 PCI Vendor ID,d802 对应 Ascend 910B 系列

从输出可以看到:

  • 操作系统:CTyunOS 22.06(基于 openEuler,aarch64 架构)

  • 内核:4.19.90,编译于 2024-06-13

  • NPU 驱动:npu-smi 25.2.0 已预装

  • 设备 IDd802 对应 Ascend 910B2

图 1:CANN 安装下载页面(选择 A2 系列、AArch64、CTyunOS、离线安装)


初始化环境:CANN 下载与 Python 准备

安装基础工具

首先安装必要的系统工具和编译环境:

sudo yum install -y tmux git patch
sudo yum install -y gcc python3 python3-pip

安装 pyenv 管理 Python 版本

CTyunOS 自带的 Python 版本过低,而 vLLM 要求 Python ≥ 3.10 且 < 3.13。因此使用 pyenv 安装独立版本的 Python。

首先配置 pip 清华镜像源以加速下载:

pip3 config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
curl -fsSL https://pyenv.run | bash

安装好 pyenv 后,将以下内容添加到 ~/.bashrcsource ~/.bashrc 重载环境变量:

export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"
eval "$(pyenv virtualenv-init -)"

参数说明:

说明
PYENV_ROOT指定 pyenv 的安装根目录,默认为 ~/.pyenv
PATH=...pyenv/bin:$PATH将 pyenv 的可执行文件加入 PATH,使其可以在任意位置调用
pyenv init - bash初始化 pyenv 的 shims 机制,使 python 命令自动指向 pyenv 管理的版本
pyenv virtualenv-init -启用 pyenv-virtualenv 插件,进入项目目录时自动激活虚拟环境

安装 Python 3.10.4

根据 vLLM 官方文档建议(Python >= 3.10, < 3.13),选择安装 Python 3.10.4。同时配置清华镜像加速源码下载:

export PYTHON_BUILD_MIRROR_URL="https://mirrors.tuna.tsinghua.edu.cn/python/"
export PYTHON_BUILD_MIRROR_URL_SKIP_CHECKSUM=1
pyenv install 3.10.4
pyenv global 3.10.4

参数说明:

环境变量 / 命令说明
PYTHON_BUILD_MIRROR_URL指定 pyenv 编译安装 Python 时下载源码的镜像地址,替代默认的 python.org
PYTHON_BUILD_MIRROR_URL_SKIP_CHECKSUM=1跳过校验和验证(镜像源文件可能与官方校验值不一致)
pyenv install 3.10.4下载并编译安装 Python 3.10.4(包含解释器、标准库等)
pyenv global 3.10.4将 3.10.4 设为全局默认 Python 版本

下载安装驱动:CANN Toolkit 与 910B 算子包

CANN(Compute Architecture for Neural Networks)是华为昇腾 AI 处理器的计算架构,相当于 NVIDIA 的 CUDA 生态。部署 vLLM-Ascend 需要安装两个组件:CANN Toolkit(包含驱动 + 通用工具包)和 910B 专用算子包(包含 910B 芯片特有的高性能算子实现)。

下载并安装 CANN Toolkit

从华为 OBS 对象存储下载 CANN 9.0.1 离线安装包(约 1.8GB):

[root@ctyun-gpu-atlas-01 ~]# wget "https://ascend-cann-open.obs.cn-north-4.myhuaweicloud.com/CANN/CANN%209.0.1/Ascend-cann_9.0.1_linux-aarch64.run"
--2026-08-29 22:39:45--  https://ascend-cann-open.obs.cn-north-4.myhuaweicloud.com/CANN/CANN%209.0.1/Ascend-cann_9.0.1_linux-aarch64.run
Resolving ascend-cann-open.obs.cn-north-4.myhuaweicloud.com (ascend-cann-open.obs.cn-north-4.myhuaweicloud.com)... 122.9.24.7, 122.9.24.4
Connecting to ascend-cann-open.obs.cn-north-4.myhuaweicloud.com (ascend-cann-open.obs.cn-north-4.myhuaweicloud.com)|122.9.24.7|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1911207575 (1.8G) [binary/octet-stream]
Saving to: 'Ascend-cann_9.0.1_linux-aarch64.run'

Ascend-cann_9.0.1_linux-aarch 100%[=================================================>]   1.78G  6.33MB/s    in 4m 46s

2026-08-29 22:44:31 (6.38 MB/s) - 'Ascend-cann_9.0.1_linux-aarch64.run' saved [1911207575/1911207575]

[root@ctyun-gpu-atlas-01 ~]#

bash ./Ascend-cann_9.0.1_linux-aarch64.run --install
===========
= Summary =
===========

Driver:  Installed in /usr/local/Ascend/driver.
CANN:    Ascend-cann_9.0.1_linux-aarch64 install success, installed in /usr/local/Ascend.

Please make sure that the environment variables have been configured.
-  To take effect for all users, you can add "source /usr/local/Ascend/cann/set_env.sh" to /etc/profile.
-  To take effect for current user, you can exec command below: source /usr/local/Ascend/cann/set_env.sh or add "source /usr/local/Ascend/cann/set_env.sh" to ~/.bashrc.

[root@ctyun-gpu-atlas-01 ~]#

Toolkit 安装成功后,输出提示已安装到 /usr/local/Ascend,并建议配置环境变量 set_env.sh

下载并安装 910B 专用算子包

接下来下载 910B 专用算子包(约 2.1GB),它包含针对 Ascend 910B 芯片优化的高性能算子:

[root@ctyun-gpu-atlas-01 ~]# wget "https://ascend-repo.obs.cn-east-2.myhuaweicloud.com/CANN/CANN%209.0.1/Ascend-cann-910b-ops_9.0.1_linux-aarch64.run"
--2026-08-29 23:03:59--  https://ascend-repo.obs.cn-east-2.myhuaweicloud.com/CANN/CANN%209.0.1/Ascend-cann-910b-ops_9.0.1_linux-aarch64.run
Resolving ascend-repo.obs.cn-east-2.myhuaweicloud.com (ascend-repo.obs.cn-east-2.myhuaweicloud.com)... 122.9.88.11, 122.9.88.13, 122.9.88.10, ...
Connecting to ascend-repo.obs.cn-east-2.myhuaweicloud.com (ascend-repo.obs.cn-east-2.myhuaweicloud.com)|122.9.88.11|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2296115500 (2.1G) [application/octet-stream]
Saving to: 'Ascend-cann-910b-ops_9.0.1_linux-aarch64.run'

Ascend-cann-910b-ops_9.0.1_li 100%[=================================================>]   2.14G  6.35MB/s    in 5m 44s

2026-08-29 23:09:43 (6.37 MB/s) - 'Ascend-cann-910b-ops_9.0.1_linux-aarch64.run' saved [2296115500/2296115500]

[root@ctyun-gpu-atlas-01 ~]# bash ./Ascend-cann-910b-ops_9.0.1_linux-aarch64.run --install

===========
= Summary =
===========

Driver:    Installed in /usr/local/Ascend/driver.
ops_910b:  Ascend-cann-910b-ops_9.0.1_linux-aarch64 install success, installed in /usr/local/Ascend.

Please make sure that the environment variables have been configured.
-  To take effect for all users, you can add "source /usr/local/Ascend/cann/set_env.sh" to /etc/profile.
-  To take effect for current user, you can exec command below: source /usr/local/Ascend/cann/set_env.sh or add "source /usr/local/Ascend/cann/set_env.sh" to ~/.bashrc.

[root@ctyun-gpu-atlas-01 ~]#

验证安装

加载 CANN 环境变量后,通过 Python 调用 ACL(Ascend Computing Language)接口验证芯片型号是否正确识别:

[root@ctyun-gpu-atlas-01 ~]# source /usr/local/Ascend/cann/set_env.sh
[root@ctyun-gpu-atlas-01 ~]# python3 -c "import acl;print(acl.get_soc_name())"
Ascend910B2
[root@ctyun-gpu-atlas-01 ~]#

验证结果acl.get_soc_name() 返回 Ascend910B2,说明 CANN Toolkit 和 910B 算子包均已正确安装,ACL 运行时能正确识别芯片型号。这是后续所有推理部署的前提条件。


系统参数调优

大模型推理对网络和系统参数有较高要求。在正式部署前,需要对内核网络缓冲区、文件描述符限制、HCCL 端口等进行调优。

网络缓冲区调优

# 设置系统参数
sudo bash -c 'cat >> /etc/sysctl.conf << EOF
net.core.rmem_max=26214400
net.core.wmem_max=26214400
net.ipv4.tcp_rmem=4096 87380 26214400
net.ipv4.tcp_wmem=4096 65536 26214400
EOF'

sudo sysctl -p

# 设置用户限制
sudo bash -c 'cat >> /etc/security/limits.conf << EOF
* soft  nofile  1048576
* hard  nofile  1048576
* soft  memlock unlimited
* hard  memlock unlimited
EOF'

参数说明:

参数说明
net.core.rmem_max26214400 (25MB)内核接收缓冲区最大值,默认通常只有 212992(208KB),调大以支持大规模数据传输
net.core.wmem_max26214400 (25MB)内核发送缓冲区最大值,同理调大
net.ipv4.tcp_rmem4096 87380 26214400TCP 接收缓冲区三个值:最小/默认/最大,确保大流量场景下缓冲区足够
net.ipv4.tcp_wmem4096 65536 26214400TCP 发送缓冲区三个值:最小/默认/最大
nofile1048576 (1M)每个进程可打开的最大文件描述符数。大模型推理涉及大量模型文件和连接,需要放宽
memlockunlimited允许进程锁定内存不限制,防止关键内存被 swap 换出导致性能下降

HCCL 通信端口预留

HCCL 默认使用操作系统的 60000-60015 端口进行卡间通信。需要将这些端口预留,避免被其他应用占用:

# HCCL默认使用服务器OS的60000-60015端口,请执行如下命令预留此范围的操作系统端口:
echo "net.ipv4.ip_local_reserved_ports=60000-60015" >> /etc/sysctl.conf
sysctl -p
# 若需要使用其它端口,例如使用50000-50015端口,请执行如下命令预留此范围的操作系统端口:export HCCL_IF_BASE_PORT=50000
echo "net.ipv4.ip_local_reserved_ports=50000-50015" >> /etc/sysctl.conf
sysctl -p

端口冲突说明ip_local_reserved_ports 让内核在自动分配临时端口时跳过这些范围,确保 HCCL 通信不被干扰。如需使用非默认端口范围,可通过环境变量 HCCL_IF_BASE_PORT 指定起始端口。


Docker 环境与 vllm-ascend 镜像

vLLM-Ascend 官方提供了预构建的 Docker 镜像,集成了 vLLM、PyTorch-NPU 和 CANN 运行时。通过 Docker 可以避免宿主机环境冲突,同时方便版本管理。

# Update DEVICE according to your device (/dev/davinci[0-7])
export DEVICE=/dev/davinci0
# Update the vllm-ascend image
# Atlas A2:
# export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-openeuler
# Atlas A3:
# export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-a3-openeuler
# Atlas 950DT:
# export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-950dt-openeuler
export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-openeuler
docker run --rm \
--name vllm-ascend \
--shm-size=1g \
--device $DEVICE \
--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 \
-p 8000:8000 \
-it $IMAGE bash
# Install curl
yum update -y && yum install -y curl

Docker run 参数说明:

参数说明
--shm-size=1g设置共享内存大小为 1GB。PyTorch DataLoader 和多进程通信需要共享内存
--device $DEVICE将 NPU 设备 /dev/davinci0 映射到容器内。此处仅映射单卡用于测试
--device /dev/davinci_managerNPU 管理设备,容器内通过它与 NPU 驱动交互
--device /dev/devmm_svm设备内存共享虚拟化管理设备
--device /dev/hisi_hdc华为 HDC(Hardware Debug Channel)设备,用于调试和通信
-v /usr/local/dcmi:...映射 DCMI(Device Control Management Interface)库
-v /usr/local/bin/npu-smi:...映射 npu-smi 工具,容器内可查看 NPU 状态
-v .../driver/lib64/:...映射 NPU 驱动库文件,容器内运行时依赖
-v /etc/ascend_install.info:...映射安装信息文件,记录 CANN 安装路径和组件
-v /root/.cache:...映射缓存目录,模型下载和编译缓存可跨容器复用
-p 8000:8000映射 vLLM API 服务端口
-it ... bash以交互模式启动并进入 bash shell

镜像选择:根据硬件型号选择对应的镜像:Atlas A2 用 v0.23.0-openeuler,A3 用 v0.23.0-a3-openeuler,950DT 用 v0.23.0-950dt-openeuler。本文使用的是 A2 系列镜像。


小模型验证:Qwen3-0.6B 冒烟测试

在正式部署大模型之前,先用一个小模型验证整个推理链路是否畅通。这里选择 Qwen3-0.6B——参数量小、下载快,适合快速验证环境。

下载模型并启动服务

[root@ctyun-gpu-atlas-01 workspace]# modelscope download --model Qwen/Qwen3-0.6B --local_dir /mnt/models/Qwen/Qwen3-0.6B
[root@ctyun-gpu-atlas-01 workspace]# vllm serve /mnt/models/Qwen/Qwen3-0.6B --served-model-name qwen3
...
(APIServer pid=232) INFO:     Started server process [232]
(APIServer pid=232) INFO:     Waiting for application startup.
(APIServer pid=232) INFO:     Application startup complete.

服务启动成功,输出 Application startup complete 表示 vLLM API Server 已就绪。

查看可用模型

[root@ctyun-gpu-atlas-01 workspace]# curl http://localhost:8000/v1/models | python3 -m json.tool
{
    "object": "list",
    "data": [
        {
            "id": "qwen3",
            "object": "model",
            "created": 1788066640,
            "owned_by": "vllm",
            "root": "/mnt/models/Qwen/Qwen3-0.6B",
            "parent": null,
            "max_model_len": 40960,
            "permission": [
                {
                    "id": "modelperm-ab74ad47294f4e4f",
                    "object": "model_permission",
                    "created": 1788066640,
                    "allow_create_engine": false,
                    "allow_sampling": true,
                    "allow_logprobs": true,
                    "allow_search_indices": false,
                    "allow_view": true,
                    "allow_fine_tuning": false,
                    "organization": "*",
                    "group": null,
                    "is_blocking": false
                }
            ]
        }
    ]
}
[root@ctyun-gpu-atlas-01 workspace]#

API 返回了已加载的模型信息,idqwen3,最大上下文长度 max_model_len 为 40960 tokens。

发送推理请求

[root@ctyun-gpu-atlas-01 workspace]# curl http://localhost:8000/v1/completions     -H "Content-Type: application/json"     -d '{
        "model": "qwen3",
        "prompt": "Beijing is a",
        "max_completion_tokens": 5,
        "temperature": 0
    }' | python3 -m json.tool
{
    "id": "cmpl-86ccbe0c8c82384a",
    "object": "text_completion",
    "created": 1788066874,
    "model": "qwen3",
    "choices": [
        {
            "index": 0,
            "text": " city that has been experiencing a lot of changes. The city has been experiencing a",
            "logprobs": null,
            "finish_reason": "length",
            "stop_reason": null,
            "token_ids": null,
            "prompt_logprobs": null,
            "prompt_token_ids": null,
            "routed_experts": null
        }
    ],
    "service_tier": null,
    "system_fingerprint": "vllm-0.23.0-5658b290",
    "usage": {
        "prompt_tokens": 4,
        "total_tokens": 20,
        "completion_tokens": 16,
        "prompt_tokens_details": null
    },
    "kv_transfer_params": null
}
[root@ctyun-gpu-atlas-01 workspace]#

冒烟测试通过:模型成功生成了续写文本 “ city that has been experiencing a lot of changes…“finish_reason: length 表示因达到 max_completion_tokens 上限而停止。至此,单卡推理链路验证完毕,环境没有问题。


DeepSeek V4 Flash 单机 TP8 部署

验证完基础环境后,开始正式部署目标模型 DeepSeek V4 Flash(W8A8 量化版)。单机阶段使用 8 卡张量并行(TP=8),将模型权重切分到 8 张 NPU 上并行计算。

启动 Docker 容器(8 卡全量映射)

与之前的测试容器不同,这里需要映射全部 8 张 NPU 卡,并使用专门的 DeepSeek V4 Flash 镜像:

export IMAGE=quay.io/ascend/vllm-ascend:DeepSeekV4-flash-0731
docker run --rm \
    --privileged=true \
    --name vllm-ascend \
    --shm-size=512g \
    --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/Ascend/driver/tools/hccn_tool:/usr/local/Ascend/driver/tools/hccn_tool \
    -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
    -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
    -v /usr/local/Ascend/firmware:/usr/local/Ascend/firmware \
    -v /usr/local/Ascend/add-ons/:/usr/local/Ascend/add-ons/ \
    -v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
    -v /usr/local/Ascend/ascend-toolkit:/usr/local/Ascend/ascend-toolkit \
    -v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
    -v /etc/ascend_install.info:/etc/ascend_install.info \
    -v /etc/hccn.conf:/etc/hccn.conf \
    -v /usr/local/sbin/:/usr/local/sbin/ \
    -v /mnt/models:/mnt/models \
    --ulimit nofile=65535:65535 \
    -it $IMAGE bash

关键参数说明:

参数说明
--privileged=true特权模式,容器拥有完整权限,可访问 NPU 驱动的所有接口
--shm-size=512g共享内存设为 512GB,大模型多卡推理需要大量共享内存用于进程间数据交换
--net=host使用宿主机网络栈,容器直接使用物理网络。TP8 多卡通信需要低延迟网络,NAT 会增加开销
--device /dev/davinci0-7映射全部 8 张 NPU 卡到容器内
-v .../hccn_tool:...映射 HCCN(Huawei Cache Coherent Network)工具,用于卡间通信配置
-v .../firmware:...映射 NPU 固件
-v .../ascend-toolkit:...映射 Ascend Toolkit(CANN 工具链),容器内编译算子需要
-v /etc/hccn.conf:...映射 HCCN 配置文件,包含卡间网络拓扑信息
-v /mnt/models:...映射模型存储目录
--ulimit nofile=65535:65535设置容器内文件描述符上限

启动 vLLM 服务(TP8)

进入容器后,设置环境变量并启动 vLLM 服务:

source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
export OMP_NUM_THREADS=32
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export TASK_QUEUE_ENABLE=1
export HCCL_BUFFSIZE=1024
export HCCL_OP_EXPANSION_MODE=AIV

vllm serve /mnt/models/Eco-Tech/DeepSeek-V4-Flash-0731-w8a8 \
    --host 0.0.0.0 \
    --port 8000 \
    --api-key your-api-key \
    --served-model-name dsv4 \
    --tensor-parallel-size 8 \
    --enable-expert-parallel \
    --quantization ascend \
    --max-model-len 1048576 \
    --max-num-seqs 32 \
    --max-num-batched-tokens 8192 \
    --gpu-memory-utilization 0.9 \
    --block-size 128 \
    --trust-remote-code \
    --tokenizer-mode deepseek_v4 \
    --tool-call-parser deepseek_v4 \
    --enable-auto-tool-choice \
    --reasoning-parser deepseek_v4 \
    --enable-prefix-caching \
    --no-disable-hybrid-kv-cache-manager \
    --model-loader-extra-config '{"enable_multithread_load": true, "num_threads": 128}' \
    --additional-config '{   "ascend_compilation_config": {     "enable_npugraph_ex": true,     "enable_static_kernel": false   },   "enable_cpu_binding": true,   "enable_dsa_cp": false,   "multistream_overlap_shared_expert": true }' \
    --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
    --async-scheduling

环境变量说明:

环境变量说明
OMP_NUM_THREADS32OpenMP 线程数,控制 CPU 端并行度。设为 32 平衡 CPU 计算和上下文切换开销
PYTORCH_NPU_ALLOC_CONFexpandable_segments:True启用可扩展内存段分配,减少 NPU 内存碎片,大模型推理必备
TASK_QUEUE_ENABLE1启用任务队列,优化 NPU 算子调度顺序
HCCL_BUFFSIZE1024HCCL 通信缓冲区大小(MB),增大可提升集合通信吞吐
HCCL_OP_EXPANSION_MODEAIVHCCL 算子展开模式,AIV 模式使用 AI Vector 进行通信优化

vLLM serve 参数说明:

参数说明
--tensor-parallel-size8张量并行度,将模型权重切分到 8 张卡上。单机 8 卡全用
--enable-expert-parallel-启用专家并行(EP)。DeepSeek V4 是 MoE 模型,EP 让不同专家分布在不同卡上
--quantizationascend使用昇腾专用量化方案,对应 W8A8 权重+激活量化
--max-model-len1048576最大上下文长度 1M tokens(1048576)。DeepSeek V4 支持超长上下文
--max-num-seqs32最大并发序列数,控制同时处理的请求数
--max-num-batched-tokens8192单次批量处理的最大 token 数
--gpu-memory-utilization0.9NPU 显存利用率上限 90%,预留 10% 给框架开销
--block-size128KV Cache 块大小,128 是 DeepSeek V4 推荐值
--tokenizer-modedeepseek_v4使用 DeepSeek V4 专用 tokenizer 模式
--tool-call-parserdeepseek_v4使用 DeepSeek V4 工具调用解析器
--enable-auto-tool-choice-启用自动工具选择,模型可自主决定是否调用工具
--reasoning-parserdeepseek_v4使用 DeepSeek V4 推理内容解析器,提取思维链
--enable-prefix-caching-启用前缀缓存,相同前缀的请求复用 KV Cache,减少重复计算
--no-disable-hybrid-kv-cache-manager-启用混合 KV Cache 管理器,优化 MoE 模型的显存使用
--model-loader-extra-configmultithread_load多线程加载模型权重,128 线程并行读取 safetensors 文件,加速加载
--additional-configJSONAscend 编译配置:启用 NPU Graph 扩展、CPU 绑定、多流重叠共享专家等高级优化
--compilation-configFULL_DECODE_ONLYcudagraph 模式设为仅解码阶段全图编译,平衡编译时间和执行效率
--async-scheduling-启用异步调度,让 CPU 调度与 NPU 计算重叠,减少 bubble 时间

运行状态监控

服务运行后,vLLM 会定期输出引擎状态日志,展示实时吞吐和资源使用情况:

http)

(APIServer pid=273) INFO 08-30 08:20:18 [loggers.py:273] Engine 000: Avg prompt throughput: 409.5 tokens/s, Avg generation throughput: 336.9 tokens/s, Running: 126 reqs, Waiting: 0 reqs, GPU KV cache usage: 70.7%, Prefix cache hit rate: 0.0%
(APIServer pid=273) INFO 08-30 08:20:18 [metrics.py:120] SpecDecoding metrics: Mean acceptance length: 1.56, Accepted throughput: 121.68 tokens/s, Drafted throughput: 1511.08 tokens/s, Accepted: 1217 tokens, Drafted: 15113 tokens, Per-position acceptance rate: 0.227, 0.117, 0.073, 0.056, 0.042, 0.029, 0.019, Avg Draft acceptance rate: 8.1%

运行状态解读

  • 引擎吞吐:Prompt 处理 409.5 tokens/s,生成 336.9 tokens/s;当前 126 个请求并发运行、0 个排队等待;KV Cache 使用率 70.7%。

  • 投机解码(SpecDecoding):平均接受长度 1.56,即每个草稿 token 平均有 1.56 个被接受;草稿吞吐 1511.08 tokens/s,接受吞吐 121.68 tokens/s;平均草稿接受率 8.1%。投机解码通过小模型快速生成候选 token 再由大模型验证,可加速推理。


单机性能压测

服务稳定运行后,使用 vLLM 内置的 vllm bench serve 工具进行性能压测,评估单机 TP8 配置下的吞吐和延迟指标。

[root@ctyun-gpu-atlas-01 ~]# docker exec -it vllm-ascend bash
root@ctyun-gpu-atlas-01:/workspace#
root@ctyun-gpu-atlas-01:/workspace# vllm bench serve   --backend openai   --base-url http://127.0.0.1:8000   --served-model-name dsv4   --model /mnt/models/Eco-Tech/DeepSeek-V4-Flash-0731-w8a8   --dataset-name random   --num-prompts 1024   --num-warmups 10   --request-rate inf   --max-concurrency 128   --random-input-len 1024   --random-output-len 512   --save-result   --result-dir ./bench_results
INFO 08-30 09:19:39 [__init__.py:44] Available plugins for group vllm.platform_plugins:
INFO 08-30 09:19:39 [__init__.py:46] - ascend -> vllm_ascend:register
INFO 08-30 09:19:39 [__init__.py:49] All plugins in this group will be loaded. Set `VLLM_PLUGINS` to control which plugins to load.
INFO 08-30 09:19:39 [__init__.py:237] Platform plugin ascend is activated
INFO 08-30 09:19:50 [platform.py:61] Breakable cudagraph is force disabled on Ascend because DeepSeek V4 PIECEWISE cudagraph is not supported yet.
2026-08-30 09:19:50,069 - 14584 - ServiceProfiler - INFO - VLLM_USE_V1 not set, auto-detected via vLLM 0.25.1+empty: default 1
INFO 08-30 09:19:50 [__init__.py:112] Registered model loader `<class 'vllm_ascend.model_loader.netloader.netloader.ModelNetLoaderElastic'>` with load format `netloader`
INFO 08-30 09:19:50 [__init__.py:112] Registered model loader `<class 'vllm_ascend.model_loader.rfork.rfork_loader.RForkModelLoader'>` with load format `rfork`
Namespace(subparser='bench', bench_type='serve', dispatch_function=<function BenchmarkServingSubcommand.cmd at 0xfffc1f16eac0>, trust_remote_code=False, seed=0, num_prompts=1024, dataset_name='random', no_stream=False, dataset_path=None, no_oversample=False, skip_chat_template=False, enable_multimodal_chat=False, disable_shuffle=False, custom_output_len=256, custom_ensure_client_side_data=False, spec_bench_output_len=256, spec_bench_category=None, sonnet_input_len=550, sonnet_output_len=150, sonnet_prefix_len=200, sharegpt_output_len=None, timed_trace_chunk_hash_size=16, timed_trace_sec_multiplier=1, timed_trace_label_timestamp='timestamp', timed_trace_label_input_length='input_length', timed_trace_label_output_length='output_length', timed_trace_label_hash_ids='hash_ids', blazedit_min_distance=0.0, blazedit_max_distance=1.0, asr_max_audio_len_sec=inf, asr_min_audio_len_sec=0.0, random_input_len=1024, random_output_len=512, random_range_ratio='0.0', random_prefix_len=0, random_batch_size=1, no_reranker=False, random_mm_base_items_per_request=1, random_mm_num_mm_items_range_ratio=0.0, random_mm_limit_mm_per_prompt={'image': 255, 'video': 1}, random_mm_bucket_config={(256, 256, 1): 0.5, (720, 1280, 1): 0.5, (720, 1280, 16): 0.0}, hf_subset=None, hf_split=None, hf_name=None, hf_output_len=None, bfcl_categories=None, prefix_repetition_prefix_len=256, prefix_repetition_suffix_len=256, prefix_repetition_num_prefixes=10, prefix_repetition_output_len=128, speed_bench_dataset_subset='qualitative', speed_bench_output_len=4096, speed_bench_category=None, label=None, backend='openai', base_url='http://127.0.0.1:8000', host='127.0.0.1', port=8000, endpoint='/v1/completions', header=None, max_concurrency=128, model='/mnt/models/Eco-Tech/DeepSeek-V4-Flash-0731-w8a8', input_len=None, output_len=None, tokenizer=None, tokenizer_mode='auto', use_beam_search=False, logprobs=None, request_rate=inf, burstiness=1.0, disable_tqdm=False, num_warmups=10, profile=False, save_result=True, save_detailed=False, append_result=False, metadata=None, result_dir='./bench_results', result_filename=None, ignore_eos=False, self_timed=None, percentile_metrics=None, metric_percentiles='99', goodput=None, request_id_prefix='bench-dc506760-', top_p=None, top_k=None, min_p=None, temperature=None, frequency_penalty=None, presence_penalty=None, repetition_penalty=None, served_model_name='dsv4', lora_modules=None, lora_assignment='random', ramp_up_strategy=None, ramp_up_start_rps=None, ramp_up_end_rps=None, ready_check_timeout_sec=0, chat_template_kwargs=None, extra_body=None, skip_tokenizer_init=False, insecure=False, plot_timeline=False, timeline_itl_thresholds='25,50', plot_dataset_stats=False)
INFO 08-30 09:19:52 [utils.py:90] Sampling input_len from [1024, 1024] and output_len from [512, 512]
WARNING: /tokenize unavailable, skipping alignment.
WARNING: vllm bench serve no longer sets temperature==0 (greedy) in requests by default. The default will be determined on the server side and can be model/API specific. For the old behavior, include --temperature=0.
Starting initial single prompt test run...
Skipping endpoint ready check.
Warming up with 10 requests...
100%|██████████████████████████████████████████████████████████████████████████████████| 10/10 [00:36<00:00,  3.65s/it]
Warmup run completed.
Starting main benchmark run...
Traffic request rate: inf
Burstiness factor: 1.0 (Poisson process)
Maximum request concurrency: 128
100%|██████████████████████████████████████████████████████████████████████████████| 1024/1024 [07:00<00:00,  2.44it/s]
tip: install termplotlib and gnuplot to plot the metrics
============ Serving Benchmark Result ============
Successful requests:                     1024
Failed requests:                         0
Maximum request concurrency:             128
Benchmark duration (s):                  420.15
Total input tokens:                      1048576
Total generated tokens:                  524288
Request throughput (req/s):              2.44
Output token throughput (tok/s):         1247.86
Peak output token throughput (tok/s):    1747.00
Peak concurrent requests:                152.00
Total token throughput (tok/s):          3743.58
---------------Time to First Token----------------
Mean TTFT (ms):                          2638.07
Median TTFT (ms):                        2154.07
P99 TTFT (ms):                           11093.08
-----Time per Output Token (excl. 1st token)------
Mean TPOT (ms):                          97.49
Median TPOT (ms):                        98.33
P99 TPOT (ms):                           100.58
---------------Inter-token Latency----------------
Mean ITL (ms):                           97.49
Median ITL (ms):                         81.38
P99 ITL (ms):                            720.66
==================================================
root@ctyun-gpu-atlas-01:/workspace#

bench

压测参数说明:

参数说明
--backendopenai使用 OpenAI 兼容 API 后端
--base-urlhttp://127.0.0.1:8000vLLM 服务地址
--dataset-namerandom使用随机生成数据集(非真实对话数据),用于纯性能压测
--num-prompts1024发送 1024 个请求
--num-warmups10预热请求数,不计入统计结果
--request-rateinf请求发送速率为无穷大,即尽可能快地发送所有请求
--max-concurrency128最大并发请求数 128,超过则排队
--random-input-len1024每个请求的输入长度 1024 tokens
--random-output-len512每个请求的输出长度 512 tokens
--save-result-保存结果到指定目录

压测结果分析

指标含义
成功请求1024 / 1024全部成功,0 失败
请求吞吐2.44 req/s每秒完成 2.44 个请求
输出 token 吞吐1247.86 tok/s每秒生成约 1248 个 token
峰值输出吞吐1747.00 tok/s峰值瞬间每秒生成 1747 个 token
总 token 吞吐3743.58 tok/s含输入+输出的总吞吐
平均 TTFT2638.07 ms首 token 延迟,平均约 2.6 秒
P99 TTFT11093.08 ms99 分位首 token 延迟约 11 秒
平均 TPOT97.49 ms首 token 后每个输出 token 平均耗时约 97.5ms
平均 ITL97.49 mstoken 间平均延迟约 97.5ms
P99 ITL720.66 ms99 分位 token 间延迟约 721ms

性能总结:单机 TP8 配置下,输出吞吐约 1248 tok/s,峰值达 1747 tok/s。TPOT 约 97.5ms/token,P99 控制在 100.58ms 以内,生成速率稳定。TTFT 平均 2.6 秒(P99 约 11 秒),在高并发 128 请求下首 token 延迟可接受。整体表现良好,为后续双机部署提供了性能基线。


Ray 分布式多节点部署

单机 8 卡已经能运行 DeepSeek V4 Flash,但双机 16 卡可以通过更大的并行度提升吞吐。这里使用 Ray 作为分布式执行框架,将两台机器组成一个集群,实现跨节点的流水线并行(PP2)+ 张量并行(TP8)。

NPU 网络连通性检查

在搭建 Ray 集群之前,首先验证 8 张 NPU 卡的 RoCE 网络是否正常。使用 hccn_tool 工具逐卡检查链路状态、网络健康度、对端地址和网关配置。

1. 查看每张卡的物理网口

[root@ctyun-gpu-atlas-01 ~]#  for i in {0..7}; do hccn_tool -i $i -lldp -g | grep Ifname; done
	Ifname: 400GE1/4/1:1
	Ifname: 400GE1/4/1:2
	Ifname: 400GE1/4/2:1
	Ifname: 400GE1/4/2:2
	Ifname: 400GE1/4/3:1
	Ifname: 400GE1/4/3:2
	Ifname: 400GE1/4/4:1
	Ifname: 400GE1/4/4:2

每张卡有 8 个 400GE(400 Gigabit Ethernet)端口,通过 LLDP 协议发现对端设备。400GE 高速网络为卡间通信提供了充足带宽。

2. 检查链路状态

[root@ctyun-gpu-atlas-01 ~]#  for i in {0..7}; do hccn_tool -i $i -link -g ; done
link status: UP
link status: UP
link status: UP
link status: UP
link status: UP
link status: UP
link status: UP
link status: UP

全部 8 张卡链路状态均为 UP,物理连接正常。

3. 检查网络健康度

[root@ctyun-gpu-atlas-01 ~]#  for i in {0..7}; do hccn_tool -i $i -net_health -g ; done
net health status: Success
net health status: Success
net health status: Success
net health status: Success
net health status: Success
net health status: Success
net health status: Success
net health status: Success

全部 Success,RoCE 网络健康。

4. 查看对端检测地址

[root@ctyun-gpu-atlas-01 ~]#  for i in {0..7}; do hccn_tool -i $i -netdetect -g ; done
netdetect address: 6.0.2.0
netdetect address: 6.0.2.2
netdetect address: 6.0.2.4
netdetect address: 6.0.2.6
netdetect address: 6.0.2.8
netdetect address: 6.0.2.10
netdetect address: 6.0.2.12
netdetect address: 6.0.2.14

每张卡检测到的对端地址分布在 6.0.2.x 网段,偶数地址递增。

5. 查看网关和接口

[root@ctyun-gpu-atlas-01 ~]#  for i in {0..7}; do hccn_tool -i $i -gateway -g ; done
default gateway:6.0.2.0, Iface:eth0
default gateway:6.0.2.2, Iface:eth1
default gateway:6.0.2.4, Iface:eth2
default gateway:6.0.2.6, Iface:eth3
default gateway:6.0.2.8, Iface:eth4
default gateway:6.0.2.10, Iface:eth5
default gateway:6.0.2.12, Iface:eth6
default gateway:6.0.2.14, Iface:eth7

每张卡对应一个独立的虚拟网口(eth0~eth7),网关地址依次递增。NPU 卡间网络通过内部交换芯片互联,无需外部交换机。

6. 查看 IP 地址并测试连通性

[root@ctyun-gpu-atlas-01 ~]# for i in {0..7}; do hccn_tool -i $i -ip -g | grep ipaddr; done
ipaddr:6.0.2.1
ipaddr:6.0.2.3
ipaddr:6.0.2.5
ipaddr:6.0.2.7
ipaddr:6.0.2.9
ipaddr:6.0.2.11
ipaddr:6.0.2.13
ipaddr:6.0.2.15
[root@ctyun-gpu-atlas-01 ~]# hccn_tool -i 0 -ping -g address 6.0.2.1
device 0 PING 6.0.2.1
recv seq=0,time=0.042000ms
recv seq=1,time=0.012000ms
recv seq=2,time=0.009000ms
3 packets transmitted, 3 received, 0.00% packet loss
[root@ctyun-gpu-atlas-01 ~]#

NPU 0 ping 自身地址(6.0.2.1),3 个包全部收到,延迟约 0.01~0.04ms,0% 丢包。卡间网络连通性完全正常。

Ray Head 节点启动

在第一台机器(atlas-01,IP: 10.0.0.6)上启动 Ray Head 节点:

export HCCL_IF_IP=10.0.0.6
export HCCL_SOCKET_IFNAME=eno0
export RAY_EXPERIMENTAL_NOSET_ASCEND_RT_VISIBLE_DEVICES=1
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
export HCCL_P2P_DISABLE=0
export HCCL_IF_BASE_PORT=50000
root@ctyun-gpu-atlas-01:/workspace# ray start --head --node-ip-address=10.0.0.6 --port=6379 --num-gpus=8                                                                               [394/462]
Enable usage stats collection? This prompt will auto-proceed in 10 seconds to avoid blocking cluster startup. Confirm [Y/n]: y
Usage stats collection is enabled. To disable this, add `--disable-usage-stats` to the command that starts the cluster, or run the following command: `ray disable-usage-stats` before starting
the cluster. See https://docs.ray.io/en/master/cluster/usage-stats.html for more details.

Local node IP: 10.0.0.6
2026-08-31 01:22:14,499 - INFO - Failed to auto-detect TPU type.
2026-08-31 01:22:14,505 - INFO - Failed to configure TPU pod. Got: tpu_name: None, worker_id: None, accelerator_type: None

--------------------
Ray runtime started.
--------------------

Next steps
  To add another node to this Ray cluster, run
    ray start --address='10.0.0.6:6379'

  To connect to this Ray cluster:
    import ray
    ray.init(_node_ip_address='10.0.0.6')

  To terminate the Ray runtime, run
    ray stop

  To view the status of the cluster, use
    ray status
root@ctyun-gpu-atlas-01:/workspace# ray status
======== Autoscaler status: 2026-08-31 01:22:29.001024 ========
Node status
---------------------------------------------------------------
Active:
 1 node_b9434c9fa32f41a47c6f450a08b76d1f358b0002cbe7babee773f5e8
 1 node_0c2a8d8fb57354c14c2917f5752bb2993c1c2811a3c9a3d2b39e511f
Pending:
 (no pending nodes)
Recent failures:
 (no failures)

Resources
---------------------------------------------------------------
Total Usage:
 0.0/384.0 CPU
 0.0/16.0 GPU
 0.0/16.0 NPU
 0.0/2.0 TPU
 0B/2.63TiB memory
 0B/372.53GiB object_store_memory

Total Constraints:
 (no request_resources() constraints)
Total Demands:
 (no resource demands)
root@ctyun-gpu-atlas-01:/workspace#

图 2:Ray Head 节点启动后的集群状态(tmux 会话截图)

环境变量说明:

环境变量说明
HCCL_IF_IP10.0.0.6HCCL 通信使用的本机 IP 地址。Head 节点为 10.0.0.6
HCCL_SOCKET_IFNAMEeno0HCCL 通信使用的网卡接口名
RAY_EXPERIMENTAL_NOSET_ASCEND_RT_VISIBLE_DEVICES1实验性参数,阻止 Ray 自动设置 ASCEND_RT_VISIBLE_DEVICES,由用户手动控制
ASCEND_RT_VISIBLE_DEVICES0,1,2,3,4,5,6,7可见 NPU 设备列表,暴露全部 8 张卡
HCCL_P2P_DISABLE0不禁用 P2P(点对点)通信,启用 NPU 间直接数据传输
HCCL_IF_BASE_PORT50000HCCL 通信起始端口

Ray 集群资源:Head 节点启动后显示集群有 384 CPU、16 GPU、16 NPU、2.63TiB 内存。注意 GPU 和 NPU 都显示 16(双机合计),TPU 的 2.0 是 Ray 对未知加速器的默认检测(可忽略)。此时 Head 节点已就绪,等待 Worker 节点加入。

Ray Worker 节点加入

在第二台机器(atlas-02,IP: 10.0.0.5)上配置环境变量并加入集群:

export HCCL_IF_IP=10.0.0.5
export HCCL_SOCKET_IFNAME=eno0
export RAY_EXPERIMENTAL_NOSET_ASCEND_RT_VISIBLE_DEVICES=1
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
export HCCL_P2P_DISABLE=0 
root@ctyun-gpu-atlas-02:/workspace# ray start --address='10.0.0.6:6379' --node-ip-address=10.0.0.5 --num-gpus=8
Local node IP: 10.0.0.5
2026-08-31 01:22:22,139 - INFO - Failed to auto-detect TPU type.
2026-08-31 01:22:22,143 - INFO - Failed to configure TPU pod. Got: tpu_name: None, worker_id: None, accelerator_type: None
[2026-08-31 01:22:22,164 W 169 169] global_state_accessor.cc:435: Retrying to get node with node ID b9434c9fa32f41a47c6f450a08b76d1f358b0002cbe7babee773f5e8

--------------------
Ray runtime started.
--------------------

To terminate the Ray runtime, run
  ray stop

Worker 节点成功加入集群。回到 Head 节点查看集群状态:

root@ctyun-gpu-atlas-01:/workspace# ray status
======== Autoscaler status: 2026-08-31 01:22:29.001024 ========
Node status
---------------------------------------------------------------
Active:
 1 node_b9434c9fa32f41a47c6f450a08b76d1f358b0002cbe7babee773f5e8
 1 node_0c2a8d8fb57354c14c2917f5752bb2993c1c2811a3c9a3d2b39e511f
Pending:
 (no pending nodes)
Recent failures:
 (no failures)

Resources
---------------------------------------------------------------
Total Usage:
 0.0/384.0 CPU
 0.0/16.0 GPU
 0.0/16.0 NPU
 0.0/2.0 TPU
 0B/2.63TiB memory
 0B/372.53GiB object_store_memory

Total Constraints:
 (no request_resources() constraints)
Total Demands:
 (no resource demands)
root@ctyun-gpu-atlas-01:/workspace#

集群显示 2 个 Active 节点,16 NPU 资源全部可用。双机 Ray 集群搭建完毕。

启动 PP2 + TP8 多节点推理

Ray 集群就绪后,在 Head 节点启动 vLLM 服务,配置 流水线并行 PP=2(模型按层切分到两台机器)+ 张量并行 TP=8(每台机器内部 8 卡张量并行):

source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export TASK_QUEUE_ENABLE=1
export HCCL_BUFFSIZE=1024
export HCCL_OP_EXPANSION_MODE=AIV
export HCCL_SOCKET_IFNAME=bond0
export HCCL_IF_IP=100.97.170.13
export HCCL_P2P_DISABLE=0

vllm serve /mnt/models/Eco-Tech/DeepSeek-V4-Flash-0731-w8a8 \
    --host 0.0.0.0 \
    --port 8000 \
    --distributed-executor-backend ray \
    --pipeline-parallel-size 2 \
    --served-model-name dsv4 \
    --tensor-parallel-size 8 \
    --quantization ascend \
    --max-model-len 1048576 \
    --max-num-seqs 128 \
    --max-num-batched-tokens 8192 \
    --gpu-memory-utilization 0.9 \
    --block-size 128 \
    --trust-remote-code \
    --tokenizer-mode deepseek_v4 \
    --tool-call-parser deepseek_v4 \
    --enable-auto-tool-choice \
    --reasoning-parser deepseek_v4 \
    --enable-prefix-caching \
    --no-disable-hybrid-kv-cache-manager \
    --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
    --async-scheduling

关键新增参数说明:

参数说明
--distributed-executor-backendray使用 Ray 作为分布式执行后端,替代默认的 MP(多进程)方式。Ray 提供更灵活的跨节点调度能力
--pipeline-parallel-size2流水线并行度 2,将模型按 Transformer 层切分到 2 个 stage(对应两台机器)。Stage 0 在 atlas-01,Stage 1 在 atlas-02
--max-num-seqs128相比单机的 32 提升到 128,双机有更多显存可容纳更多并发
HCCL_SOCKET_IFNAME=bond0bond0多节点场景下使用 bond0(链路聚合接口)进行 HCCL 通信,提供更高带宽和冗余
OMP_NUM_THREADS=1010降低 OMP 线程数,因为双机总 CPU 核数更多,每进程分配较少线程避免过度竞争

启动成功日志

(EngineCore pid=1165) (RayWorkerProc pid=732, ip=10.0.0.5) (Worker_PP1_TP7 pid=732) INFO 08-31 01:29:36 [cpu_binding.py:641] NPU7: main=[98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141]  acl=[142]  release=[[143]] [repeated 10x across cluster]
(EngineCore pid=1165) (RayWorkerProc pid=428, ip=10.0.0.5) (Worker_PP1_TP1 pid=428) INFO 08-31 01:29:36 [cpu_binding.py:667] [migrate] NPU:1 -> NUMA [0] [repeated 13x across cluster]
(EngineCore pid=1165) (RayWorkerProc pid=428, ip=10.0.0.5) (Worker_PP1_TP1 pid=428) WARNING 08-31 01:29:39 [worker.py:763] Bind cpus failed in rank1: [Errno 2] No such file or directory: '/proc/irq/971/smp_affinity' Skip binding cpu.
(EngineCore pid=1165) INFO 08-31 01:29:40 [core.py:337] init engine (profile, create kv cache, warmup model) took 121.36 s (compilation: 19.69 s)
(EngineCore pid=1165) INFO 08-31 01:29:41 [ascend_config.py:824] Dynamic EPLB is False
(EngineCore pid=1165) INFO 08-31 01:29:41 [ascend_config.py:825] The number of redundant experts is 0
(EngineCore pid=1165) INFO 08-31 01:29:43 [vllm.py:1042] Asynchronous scheduling is enabled.
(EngineCore pid=1165) INFO 08-31 01:29:43 [kernel.py:292] Final IR op priority after setting platform defaults: IrOpPriorityConfig(rms_norm=['native'], fused_add_rms_norm=['native'])
(EngineCore pid=1165) WARNING 08-31 01:29:43 [utils.py:1246] For deepseek_v4 model, block size should be 32, 64 or 128. Setting block size to 32 for better performance.
(EngineCore pid=1165) INFO 08-31 01:29:43 [platform.py:771] Set PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
(EngineCore pid=1165) INFO 08-31 01:29:43 [compilation.py:312] Enabled custom fusions: norm_quant, act_quant
(APIServer pid=863) INFO 08-31 01:29:43 [api_server.py:612] Supported tasks: ['generate']
(APIServer pid=863) INFO 08-31 01:29:44 [parser_manager.py:37] "auto" tool choice has been enabled.
(APIServer pid=863) WARNING 08-31 01:29:44 [model.py:1528] Default vLLM sampling parameters have been overridden by the model's `generation_config.json`: `{'temperature': 1.0, 'top_p': 1.0}`. If this is not intended, please relaunch vLLM instance with `--generation-config vllm`.
(APIServer pid=863) INFO 08-31 01:29:44 [api_server.py:616] Starting vLLM server on http://0.0.0.0:8000
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:37] Available routes are:
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /openapi.json, Methods: GET, HEAD
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /docs, Methods: GET, HEAD
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /docs/oauth2-redirect, Methods: GET, HEAD
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /redoc, Methods: GET, HEAD
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /load, Methods: GET
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /version, Methods: GET
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /health, Methods: GET
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /metrics, Methods: GET
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /tokenize, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /detokenize, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/models, Methods: GET
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /ping, Methods: GET
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /ping, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /invocations, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/chat/completions, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/chat/completions/batch, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/responses, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/responses/{response_id}, Methods: GET
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/responses/{response_id}/cancel, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/completions, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/messages, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/messages/count_tokens, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /generative_scoring, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /scale_elastic_ep, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /is_scaling_elastic_ep, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/chat/completions/render, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/completions/render, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/chat/completions/derender, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /v1/completions/derender, Methods: POST
(APIServer pid=863) INFO 08-31 01:29:44 [launcher.py:46] Route: /inference/v1/generate, Methods: POST
(APIServer pid=863) INFO:     Started server process [863]
(APIServer pid=863) INFO:     Waiting for application startup.
(APIServer pid=863) INFO:     Application startup complete.

图 3:PP2+TP8 多节点 vLLM 服务启动成功(tmux 会话截图)

启动过程解读

  • CPU 绑定:vLLM 自动将每张 NPU 的计算线程绑定到特定 CPU 核心以减少跨 NUMA 访问延迟。日志显示 NPU7 绑定到 CPU 核 98-141,ACL 线程在核 142。部分 rank 因 /proc/irq 文件不存在而跳过绑定(WARNING 级别,不影响运行)。

  • 引擎初始化:耗时 121.36 秒(其中编译 19.69 秒),包括 KV Cache 创建和模型预热。

  • Block Size 调整:vLLM 自动将 block size 从 128 调整为 32 以获得更好性能(DeepSeek V4 模型的推荐值)。

  • 服务就绪Application startup complete 表示多节点推理服务已成功启动,注册了包括 /v1/chat/completions/v1/completions/v1/messages 等 OpenAI 兼容路由。


数据并行(DP)部署

PP2+TP8 虽然能跨双机运行模型,但流水线并行的 bubble 开销较大。另一种方案是数据并行(DP)——每台机器独立运行一份完整的 TP8 推理实例,通过数据并行在两台机器间分配请求,实现吞吐翻倍。

以下配置使用 eno0 网卡接口,在两台机器上分别启动 vLLM 进程,通过 DP RPC 端口协调。

节点 1(atlas-01)配置

source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
nic_name="eno0"
local_ip="10.0.0.6"
node0_ip="10.0.0.6"
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export HCCL_TRANSFER_TIMEOUT=600
export HCCL_EXEC_TIMEOUT=3600
export HCCL_CONNECT_TIMEOUT=3600
export OMP_PROC_BIND=false
export ASCEND_RT_VISIBLE_DEVICES="0,1,2,3,4,5,6,7"
export OMP_NUM_THREADS=4
export HCCL_BUFFSIZE=1024
export PYTORCH_NPU_ALLOC_CONF="expandable_segments:True"
export VLLM_RPC_TIMEOUT=1200
export HCCL_P2P_DISABLE=1
export ATB_OPERATION_EXECUTE_ASYNC=1
export NPU_MEMORY_FRACTION=0.95
export HCCL_DETERMINISTIC=false
export INF_NAN_MODE_ENABLE=1

sysctl -w vm.swappiness=0
sysctl -w kernel.numa_balancing=0
sysctl kernel.sched_migration_cost_ns=50000

vllm serve /mnt/models/Eco-Tech/DeepSeek-V4-Flash-0731-w8a8 \
    --host 0.0.0.0 \
    --port 8077 \
    --safetensors-load-strategy prefetch \
    --api-server-count 1 \
    --tensor-parallel-size 8 \
    --data-parallel-size 2 \
    --data-parallel-size-local 1 \
    --data-parallel-start-rank 0 \
    --data-parallel-address $node0_ip \
    --data-parallel-rpc-port 12980 \
    --enable-expert-parallel \
    --enforce-eager \
    --enable-prefix-caching \
    --disable-custom-all-reduce \
    --quantization ascend \
    --max-model-len 32768 \
    --max-num-seqs 16 \
    --max-num-batched-tokens 8192 \
    --gpu-memory-utilization 0.90 \
    --trust-remote-code \
    --api-server-count 1 \
    --served-model-name dsv4 \
    --tokenizer-mode deepseek_v4 \
    --tool-call-parser deepseek_v4 \
    --enable-auto-tool-choice \
    --block-size 128 \
    --reasoning-parser deepseek_v4 \
    --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
    --async-scheduling 

节点 2(atlas-02)配置

source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
nic_name="eno0"
local_ip="10.0.0.5"
node0_ip="10.0.0.6"
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export HCCL_TRANSFER_TIMEOUT=600
export HCCL_EXEC_TIMEOUT=3600
export HCCL_CONNECT_TIMEOUT=3600
export OMP_PROC_BIND=false
export ASCEND_RT_VISIBLE_DEVICES="0,1,2,3,4,5,6,7"
export OMP_NUM_THREADS=4
export HCCL_BUFFSIZE=1024
export PYTORCH_NPU_ALLOC_CONF="expandable_segments:True"
export VLLM_RPC_TIMEOUT=1200
export HCCL_P2P_DISABLE=1
sysctl -w vm.swappiness=0
sysctl -w kernel.numa_balancing=0
sysctl kernel.sched_migration_cost_ns=50000

vllm serve /mnt/models/Eco-Tech/DeepSeek-V4-Flash-0731-w8a8 \
    --host 0.0.0.0 \
    --port 8078 \
    --headless \
    --tensor-parallel-size 8 \
    --data-parallel-size 2 \
    --data-parallel-size-local 1 \
    --data-parallel-start-rank 1 \
    --data-parallel-address $node0_ip \
    --data-parallel-rpc-port 12980 \
    --enable-expert-parallel \
    --enforce-eager \
    --enable-prefix-caching \
    --disable-custom-all-reduce \
    --quantization ascend \
    --block-size 128 \
    --max-model-len 32768 \
    --max-num-seqs 16 \
    --max-num-batched-tokens 8192 \
    --gpu-memory-utilization 0.90 \
    --trust-remote-code \
    --api-server-count 0 \
    --served-model-name dsv4 \
    --tokenizer-mode deepseek_v4 \
    --tool-call-parser deepseek_v4 \
    --enable-auto-tool-choice \
    --reasoning-parser deepseek_v4 \
    --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
    --async-scheduling 

DP 关键参数说明:

参数节点1节点2说明
--port80778078各节点独立端口
--data-parallel-size22数据并行总数 2(两台机器各 1 个 DP rank)
--data-parallel-size-local11每台机器本地 DP 副本数 1
--data-parallel-start-rank01本节点的 DP rank 起始编号。节点1 为 rank 0,节点2 为 rank 1
--data-parallel-address10.0.0.610.0.0.6DP 协调地址(指向 Head 节点 IP)
--data-parallel-rpc-port1298012980DP RPC 通信端口,两节点必须一致
--headless节点2 设为 headless 模式,不启动 API Server,仅作为推理 Worker
--api-server-count10节点1 启动 1 个 API Server;节点2 不启动 API Server
--enforce-eager--强制 eager 模式,禁用 cudagraph,DP 场景下更稳定
--disable-custom-all-reduce--禁用自定义 all-reduce,DP 不需要跨节点梯度同步
--max-model-len3276832768DP 模式下降低上下文长度到 32K 以节省显存

DP 环境变量说明:

环境变量说明
GLOO_SOCKET_IFNAMEeno0Gloo 通信后端使用的网卡(PyTorch 分布式通信库)
TP_SOCKET_IFNAMEeno0张量并行通信使用的网卡
HCCL_P2P_DISABLE=11DP 模式禁用 P2P(与 PP 模式不同),因跨节点无 P2P 硬件支持
ATB_OPERATION_EXECUTE_ASYNC=11Ascend Transformer Boost 异步执行,提升算子并行度
NPU_MEMORY_FRACTION=0.950.95NPU 内存使用上限 95%,比 vLLM 的 gpu-memory-utilization 更底层
HCCL_TRANSFER_TIMEOUT600HCCL 传输超时 600 秒
HCCL_EXEC_TIMEOUT3600HCCL 执行超时 1 小时
VLLM_RPC_TIMEOUT1200vLLM RPC 超时 20 分钟
vm.swappiness=00禁用 swap,避免内存交换导致性能下降
kernel.numa_balancing=00禁用 NUMA 自动平衡,手动控制 CPU 绑定
sched_migration_cost_ns=5000050000任务迁移成本 50us,减少不必要的 CPU 间任务迁移

DP vs PP 对比

  • 数据并行(DP):每台机器独立运行完整模型,请求在两个实例间均衡分配,吞吐接近翻倍。无需跨节点传输中间激活值,延迟更低。但每台机器需完整加载模型权重,显存需求与单机相同。

  • 流水线并行(PP):模型按层切分到两台机器,每台只需一半权重,显存减半。但存在流水线 bubble,且 Stage 间需传输中间激活,增加延迟。适合显存不足时使用。


直连通信 BUG 修复

在 DP 部署过程中遇到了一个 MoE(Mixture of Experts)通信方式的 BUG。DeepSeek V4 是 MoE 模型,多个专家之间的通信方式选择不当会导致通信异常。需要手动修改 vllm-ascend 源码强制使用 ALLGATHER 通信方式。

root@atlas-01:/workspace# vim /vllm-workspace/vllm-ascend/vllm_ascend/ascend_forward_context.py
    找到select_moe_comm_method方法在return前设置
    moe_comm_type=MoECommType.ALLGATHER
    return moe_comm_type

BUG 修复说明

ascend_forward_context.py 文件的 select_moe_comm_method 方法中,在 return 前强制设置 moe_comm_type=MoECommType.ALLGATHER。这覆盖了原有的自动选择逻辑,确保 MoE 专家间通信用 ALLGATHER 模式,避免在多节点 DP 场景下出现直连通信不可用的问题。

MoECommType.ALLGATHER:所有专家的输出通过 AllGather 操作汇总,相比 P2P 直连方式更稳定,但通信量稍大。在跨节点场景下,P2P 直连可能因网络拓扑限制而失败,ALLGATHER 是更安全的选择。


ais_bench 基准测试

除了 vLLM 内置的压测工具,还使用华为官方的 ais_bench 基准测试框架进行评测。ais_bench 提供标准化的数据集和评测流程,可以对比不同模型的性能表现。

安装 ais_bench

pip3 install ais_bench_benchmark

配置模型接口

修改 ais_bench 的 vLLM API 流式对话配置文件,指定模型路径、API 地址和生成参数:

vim /usr/local/python3.12.13/lib/python3.12/site-packages/ais_bench/benchmark/configs/models/vllm_api/vllm_api_stream_chat.py
from ais_bench.benchmark.models import VLLMCustomAPIChat
from ais_bench.benchmark.utils.postprocess.model_postprocessors import extract_non_reasoning_content

models = [
    dict(
        attr="service",
        type=VLLMCustomAPIChat,
        abbr="vllm-api-stream-chat",
        path="/mnt/models/Eco-Tech/DeepSeek-V4-Flash-0731-w8a8",
        model="dsv4",
        stream=False,
        request_rate=0,
        use_timestamp=False,
        retry=2,
        api_key="your-api-key",
        host_ip="127.0.0.1",
        host_port=8000,
        url="",
        max_out_len=512,
        batch_size=1,
        trust_remote_code=False,
        generation_kwargs=dict(
            temperature=0.01,
            ignore_eos=False,
        ),
        pred_postprocessor=dict(type=extract_non_reasoning_content),
    )
]

配置参数说明:

参数说明
type=VLLMCustomAPIChat-使用 ais_bench 内置的 vLLM 自定义 API 客户端
path模型路径本地模型权重路径,用于 tokenizer 初始化
modeldsv4API 请求中的模型名(对应 vLLM 的 served-model-name)
stream=FalseFalse关闭流式响应,等待完整输出再返回
request_rate=00请求发送速率为 0,表示不限制(尽快发送)
retry=22失败重试次数
max_out_len=512512最大输出长度 512 tokens
temperature=0.010.01极低温度,接近贪婪解码,确保结果确定性
pred_postprocessorextract_non_reasoning_content后处理器:提取非推理内容,过滤掉思维链部分

下载 GSM8K 数据集

# 进入 ais_bench 的数据集目录
cd /usr/local/python3.12.13/lib/python3.12/site-packages/ais_bench/datasets/

# 下载 GSM8K 数据集(如果 wget 不可用,可以改用 curl -O)
wget http://opencompass.oss-cn-shanghai.aliyuncs.com/datasets/data/gsm8k.zip
apt update && apt install -y unzip && unzip gsm8k.zip
# 解压
# 验证文件是否解压成功(应该能看到 test.jsonl 等文件)
ls gsm8k/

GSM8K 是一个包含 8500 道小学数学应用题的数据集,广泛用于评估大语言模型的数学推理能力。

运行基准测试

ais_bench --models vllm_api_stream_chat   --datasets gsm8k_gen_0_shot_cot_str_perf   --debug --summarizer default_perf --mode perf

ais_bench 参数说明:

参数说明
--modelsvllm_api_stream_chat使用刚才配置的 vLLM API 模型
--datasetsgsm8k_gen_0_shot_cot_str_perfGSM8K 数据集,0-shot CoT(思维链)性能模式
--debug-调试模式,输出详细日志
--summarizerdefault_perf使用默认性能摘要器,输出吞吐和延迟统计
--modeperf性能评测模式(非准确率模式)

参考资料

  1. vLLM Ascend GLM5.2 部署教程 - Docker 镜像安装
  2. ModelScope Eco-Tech 模型集合 - DeepSeek V4 Flash
  3. vLLM Ascend GLM5.2 部署教程 - 上下文配置
  4. vllm-ascend 安装文档 (GitHub)
  5. vLLM Ascend 官方安装指南
  6. DeepSeek V4 Flash W8A8 量化模型 (GitCode)
  7. vLLM 专家并行部署文档
  8. vLLM 并行扩展与分布式部署问题排查
  9. vLLM 分布式故障排查 - Ray 可观测性