跳转至

Qwen3-VL-235B-A22B-Instruct

1 简介

Qwen3-VL-235B-A22B-Instruct 是 Qwen3-VL 系列中的大规模稀疏 MoE 视觉语言模型。它面向多模态聊天、图像理解、多图推理、类似 OCR 的视觉问答以及长上下文生成等场景而设计。

本文档介绍该模型的主要验证步骤,包括支持的功能、前提条件、安装、单节点在线部署、多节点部署、Prefill-Decode(PD)分离、功能验证、精度与性能评估、性能调优以及常见问题。

Qwen3-VL-235B-A22B-Instruct 教程在 v0.12.0 左右的 vLLM-Ascend 验证周期中引入。以下示例请使用当前 vllm-ascend 文档镜像占位符或后续版本。

2 支持的功能

请参考 支持的功能列表 以获取该模型支持的功能矩阵。

请参考 功能指南 以获取功能配置。

3 前提条件

3.1 模型权重

权重版本 硬件要求 下载链接
Qwen3-VL-235B-A22B-Instruct (BF16 版本) 1 个 Atlas 800 A3 (64G x 16) 节点或 2 个 Atlas 800 A2 (64GB x 8) 节点 ModelScope
Qwen3-VL-235B-A22B-Instruct-w8a8-QuaRot (单节点验证使用的量化版本) 1 个 Atlas 800 A3 (64GB x 16) 节点 ModelScope
Qwen3-VL-235B-A22B-Instruct-w8a8-mxfp8 (量化版本) 1 个 950DT Products (96GB x 8) 节点 ModelScope

建议将模型权重下载到多个节点共享的目录中。

路径说明:请将模型权重下载到您选择的目录并记录该路径。确保后续部署命令中的模型路径与该目录一致。

3.2 验证多节点通信(可选)

如果您希望在多节点环境中部署该模型,请根据 验证多节点通信环境 验证通信环境。

4 安装

4.1 Docker 镜像安装

请根据机器类型选择镜像,并在节点上启动 Docker 镜像,参考 使用 Docker。

在每个节点上启动 Docker 镜像。

export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-a5
export NAME=vllm-ascend

docker run --rm \
  --name $NAME \
  --net=host \
  --shm-size=1g \
  --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/hisi_hdc \
  --device /dev/ummu \
  --device /dev/uburma \
  -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
  -v /etc/ascend_install.info:/etc/ascend_install.info \
  -v /etc/hccl_rootinfo.json:/etc/hccl_rootinfo.json \
  -v /etc/hixlep/:/etc/hixlep/ \
  -v /root/.cache:/root/.cache \
  -v /usr/local/sbin:/usr/local/sbin \
  -v /usr/local/dcmi:/usr/local/dcmi \
  -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
  -v /usr/local/sbin/npu-smi:/usr/local/sbin/npu-smi \
  -v /usr/lib64:/usr/lib64 \
  -itd $IMAGE bash

在每个节点上启动 Docker 镜像。

export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-a3
docker run --rm \
    --name vllm-ascend \
    --shm-size=512g \
    --net=host \
    --privileged=true \
    --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/davinci8 \
    --device /dev/davinci9 \
    --device /dev/davinci10 \
    --device /dev/davinci11 \
    --device /dev/davinci12 \
    --device /dev/davinci13 \
    --device /dev/davinci14 \
    --device /dev/davinci15 \
    --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/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 /etc/hccn.conf:/etc/hccn.conf \
    -v /root/.cache:/root/.cache \
    -it $IMAGE bash

在每个节点上启动 Docker 镜像。

export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0
docker run --rm \
    --name vllm-ascend \
    --shm-size=512g \
    --net=host \
    --privileged=true \
    --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/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 /etc/hccn.conf:/etc/hccn.conf \
    -v /root/.cache:/root/.cache \
    -it $IMAGE bash

启动容器后,运行以下命令以验证安装:

docker ps | grep vllm-ascend

预期结果:容器以 Up 状态列出。您还可以在容器内验证 vllm-ascend 版本:

pip show vllm-ascend

预期结果:显示版本信息,与拉取的镜像版本一致。

4.2 源代码安装

如果您不想使用 Docker 镜像,可以从源代码构建。首先从源代码安装 vLLM:

  1. 克隆并安装 vLLM:
git clone https://github.com/vllm-project/vllm.git
cd vllm
pip install -e .
  1. 克隆并安装 vLLM-Ascend 仓库:
git clone https://github.com/vllm-project/vllm-ascend.git
cd vllm-ascend
pip install -e .

安装验证:

pip show vllm vllm-ascend

预期结果:显示两个包的版本信息,确认安装成功。

Note

如果部署多节点环境,请在每个节点上配置环境。

有关更多详细信息,请参阅安装指南。

5 在线服务部署

5.1 单节点在线部署

单节点部署在同一节点上同时运行 Prefill 和 Decode。W8A8 版本需要 --quantization ascend。

运行以下脚本,在 1 台 950DT Products(96G x 8)上执行在线推理。量化版本(Qwen3-VL-235B-A22B-Instruct-w8a8-mxfp8)可以部署在单个 950DT Products 节点上。

#!/bin/sh

# Load model from ModelScope to speed up download.
export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=400
export HCCL_OP_EXPANSION_MODE="AIV"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True

# Reduce memory fragmentation and avoid out-of-memory errors.

# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3-VL-235B-A22B-Instruct-w8a8-mxfp8 \
  --host 0.0.0.0 \
  --port 8000 \
  --distributed-executor-backend mp \
  --data-parallel-size 1 \
  --tensor-parallel-size 8 \
  --enable-expert-parallel \
  --seed 1024 \
  --quantization ascend \
  --served-model-name qwen3-vl-235b \
  --max-num-seqs 32 \
  --max-model-len 32768 \
  --max-num-batched-tokens 8192 \
  --trust-remote-code \
  --no-enable-prefix-caching \
  --mm-processor-cache-gb 0 \
  --limit-mm-per-prompt.image 1 \
  --limit-mm-per-prompt.video 0 \
  --gpu-memory-utilization 0.9 \
  --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}'

运行以下脚本,在 1 个 Atlas 800 A3(64G x 16)节点上启动在线服务。W8A8 示例适用于功能验证和仅图像的在线服务。

#!/bin/sh

# Load model from ModelScope to speed up download.
export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=1536
export HCCL_OP_EXPANSION_MODE="AIV"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True

# Reduce memory fragmentation and avoid out-of-memory errors.
# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3-VL-235B-A22B-Instruct-w8a8-QuaRot \
  --host 0.0.0.0 \
  --port 8000 \
  --served-model-name qwen3-vl-235b \
  --quantization ascend \
  --data-parallel-size 4 \
  --tensor-parallel-size 4 \
  --enable-expert-parallel \
  --seed 1024 \
  --max-num-seqs 32 \
  --max-model-len 32768 \
  --max-num-batched-tokens 16384 \
  --trust-remote-code \
  --gpu-memory-utilization 0.92 \
  --no-enable-prefix-caching \
  --mm-processor-cache-gb 0 \
  --limit-mm-per-prompt.image 1 \
  --limit-mm-per-prompt.video 0 \
  --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY","cudagraph_capture_sizes":[1,2,4,8,16,24,32]}' \
  --additional-config '{"enable_fused_mc2": 1, "scheduler_config": {"enable_balance_scheduling": true}}'

对于 A2 上的 W8A8 部署,需要 2 个 Atlas 800 A2(64G x 8)节点。有关多节点 MP 部署,请参阅第 5.2 节。

常见问题提示:如果您遇到问题,请参阅公共常见问题解答进行故障排除。

关键参数:

  • --data-parallel-size 4 和 --tensor-parallel-size 4 将一个 A3 节点上的 16 个 NPU 映射为四个 DP 组,每组为 TP4。
  • --enable-expert-parallel 为 MoE 层启用专家并行。请勿在同一 MoE 层中混合使用 MoE 张量并行和专家并行。
  • --max-model-len 是单个请求的最大输入加输出长度。多模态输入会消耗文本 token 和视觉 token,因此仅在 KV 缓存充足时再增大该值。
  • --max-num-seqs 是每个 DP 组调度的最大活动请求数。对于性能测试,请将 --max-num-seqs * --data-parallel-size 设置为大于或等于测试并发数。
  • --max-num-batched-tokens 是一个调度器步骤中处理的最大 token 数。较大的值可以提高 Prefill 效率,但会消耗更多激活内存。
  • --gpu-memory-utilization 控制 vLLM 可用于计算 KV 缓存容量的 HBM 大小。较高的值会增大 KV 缓存大小,但如果运行时内存高于 profiling 运行时的内存,则可能触发 OOM。
  • --quantization ascend 为 W8A8 模型启用 Ascend 量化。部署 BF16 模型时请移除此选项。
  • --limit-mm-per-prompt.image 1 和 --limit-mm-per-prompt.video 0 为每个请求预留一张图像的多模态容量,并禁用视频输入以节省内存。
  • --mm-processor-cache-gb 0 禁用多模态处理器缓存。仅当您的工作负载受益于复用的媒体预处理且主机内存充足时,再增大该值。
  • --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' 启用完整解码 ACLGraph 重放,以减少分发开销。

多节点 MP 部署在节点间使用 vLLM 数据并行,在每个节点内使用张量并行。推荐用于 2 个 Atlas 800 A2(64G x 8)节点上的 BF16 模型,或用于长上下文验证,即单个节点无法提供足够 HBM 余量的场景。

假设你有 2 个 Atlas 800 A2 节点,并希望跨这些节点部署 Qwen3-VL-235B-A22B-Instruct-w8a8-QuaRot。请将 nic_name、local_ip 和 node0_ip 替换为你环境中实际的网卡名称和 IP 地址。

在节点 0 上运行以下脚本。

#!/bin/sh

# Get these values through ifconfig.
# nic_name is the network interface name corresponding to local_ip.
nic_name="xxxx"
local_ip="xxxx"

export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=1024
export HCCL_IF_IP=$local_ip
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_SOCKET_IFNAME=$nic_name
export GLOO_SOCKET_IFNAME=$nic_name
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True

# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3-VL-235B-A22B-Instruct-w8a8-QuaRot \
  --host 0.0.0.0 \
  --port 8000 \
  --quantization ascend \
  --data-parallel-size 2 \
  --api-server-count 2 \
  --data-parallel-size-local 1 \
  --data-parallel-address $local_ip \
  --data-parallel-rpc-port 13389 \
  --seed 1024 \
  --served-model-name qwen3-vl-235b \
  --tensor-parallel-size 8 \
  --enable-expert-parallel \
  --max-num-seqs 16 \
  --max-model-len 262144 \
  --max-num-batched-tokens 4096 \
  --trust-remote-code \
  --gpu-memory-utilization 0.9 \
  --no-enable-prefix-caching \
  --mm-processor-cache-gb 0 \
  --limit-mm-per-prompt.image 1 \
  --limit-mm-per-prompt.video 0 \
  --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
  --additional-config '{"enable_cpu_binding":true}'

常见问题提示:如果节点 1 无法加入服务或 HCCL 初始化超时,请参见 验证多节点通信环境 和 公共常见问题。请确保各节点上的网卡名称、IP 地址和 RPC 端口一致。

在节点 1 上运行以下脚本。

#!/bin/sh

# Get these values through ifconfig.
# nic_name is the network interface name corresponding to local_ip.
nic_name="xxxx"
local_ip="xxxx"

export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=1024
export HCCL_IF_IP=$local_ip
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_SOCKET_IFNAME=$nic_name
export GLOO_SOCKET_IFNAME=$nic_name
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True

# The value of node0_ip must be consistent with local_ip on node 0.
node0_ip="xxxx"

# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3-VL-235B-A22B-Instruct-w8a8-QuaRot \
  --host 0.0.0.0 \
  --port 8000 \
  --quantization ascend \
  --headless \
  --data-parallel-size 2 \
  --data-parallel-size-local 1 \
  --data-parallel-start-rank 1 \
  --data-parallel-address $node0_ip \
  --data-parallel-rpc-port 13389 \
  --seed 1024 \
  --tensor-parallel-size 8 \
  --served-model-name qwen3-vl-235b \
  --max-num-seqs 16 \
  --max-model-len 262144 \
  --max-num-batched-tokens 4096 \
  --enable-expert-parallel \
  --trust-remote-code \
  --gpu-memory-utilization 0.9 \
  --no-enable-prefix-caching \
  --mm-processor-cache-gb 0 \
  --limit-mm-per-prompt.image 1 \
  --limit-mm-per-prompt.video 0 \
  --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
  --additional-config '{"enable_cpu_binding":true}'

如果服务成功启动,节点 0 上会显示以下信息:

INFO:     Started server process [44610]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Started server process [44611]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

MP 部署的关键参数:

  • --data-parallel-size 是所有节点间的全局 DP 大小。示例中使用了 2 个 DP rank。
  • --data-parallel-size-local 是当前节点上的 DP rank 数量。示例中,每个 A2 节点有 1 个本地 DP rank。
  • --data-parallel-start-rank 是当前节点上的第一个 DP rank。节点 0 默认从 0 开始,节点 1 从 1 开始。
  • --data-parallel-address 必须指向主 DP 节点。在节点 0 上使用节点 0 的 local_ip,在其他节点上使用 node0_ip。
  • --data-parallel-rpc-port 是 DP RPC 端口。所有节点使用相同值,并确保端口可用。
  • --api-server-count 控制在主节点上启动多少个 API server 进程。
  • --headless 启动一个不暴露 API server 的工作节点。在非主节点上使用。
  • --tensor-parallel-size 8 将一个 TP 组映射到每个 A2 节点上的 8 个 NPU。
  • HCCL_IF_IP、GLOO_SOCKET_IFNAME 和 HCCL_SOCKET_IFNAME 将 HCCL 和 Gloo 通信绑定到所选网络。

5.3 多节点 PD 分离部署

PD 分离将 Prefill 和 Decode 拆分为不同的服务组。Prefill 节点处理大型 prompt 块,Decode 节点提供 token 生成,代理在它们之间转发请求。该模式适用于生产服务场景,其中需要分别调整 prefill 和 decode 的资源比例。

我们建议使用 Mooncake 进行部署。有关通用的 PD 分离工作流和请求转发配置,请参见 Mooncake。

以下示例与针对 Qwen3-VL-235B-A22B-Instruct-w8a8-QuaRot 验证过的 A3 双节点拓扑一致:

  • 1 个 Prefill 节点:1 个 Atlas 800 A3(64G x 16),DP2 + TP8 + EP。
  • 1 个 Decode 节点:1 个 Atlas 800 A3(64G x 16),DP4 + TP4 + EP + 完整 decode ACLGraph。

5.3.1 Prefill 节点

在 Prefill 节点上创建 run_p.sh。

#!/bin/bash

export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=1024
export HCCL_OP_EXPANSION_MODE="AIV"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True

# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3-VL-235B-A22B-Instruct-w8a8-QuaRot \
  --host 0.0.0.0 \
  --port 8080 \
  --quantization ascend \
  --data-parallel-size 2 \
  --data-parallel-size-local 2 \
  --tensor-parallel-size 8 \
  --seed 1024 \
  --served-model-name qwen3-vl-235b \
  --enable-expert-parallel \
  --max-num-seqs 32 \
  --max-model-len 8192 \
  --max-num-batched-tokens 8192 \
  --trust-remote-code \
  --no-enable-prefix-caching \
  --gpu-memory-utilization 0.9 \
  --kv-transfer-config \
  '{"kv_connector":"MooncakeConnectorV1",
    "kv_role":"kv_producer",
    "kv_port":"30000",
    "kv_connector_extra_config":{
      "prefill":{"dp_size":2,"tp_size":8},
      "decode":{"dp_size":4,"tp_size":4}
    }
  }'

常见问题提示:如果 prefill 服务长时间未就绪,请检查模型路径是否已共享、全部 16 个 NPU 是否可见,以及 Mooncake 的 kv_port 是否可用。

5.3.2 Decode 节点

在 decode 节点上创建 run_d.sh。

#!/bin/bash

export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=1024
export HCCL_OP_EXPANSION_MODE="AIV"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True

# Ensure the model path matches the directory recorded during download
vllm serve Eco-Tech/Qwen3-VL-235B-A22B-Instruct-w8a8-QuaRot \
  --host 0.0.0.0 \
  --port 8080 \
  --quantization ascend \
  --data-parallel-size 4 \
  --data-parallel-size-local 4 \
  --tensor-parallel-size 4 \
  --seed 1024 \
  --served-model-name qwen3-vl-235b \
  --enable-expert-parallel \
  --max-num-seqs 32 \
  --max-model-len 8192 \
  --max-num-batched-tokens 8192 \
  --trust-remote-code \
  --no-enable-prefix-caching \
  --gpu-memory-utilization 0.9 \
  --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
  --kv-transfer-config \
  '{"kv_connector":"MooncakeConnectorV1",
    "kv_role":"kv_consumer",
    "kv_port":"30200",
    "kv_connector_extra_config":{
      "prefill":{"dp_size":2,"tp_size":8},
      "decode":{"dp_size":4,"tp_size":4}
    }
  }'

PD 分离的关键参数:

  • Prefill 侧使用 --data-parallel-size 2、--data-parallel-size-local 2 和 --tensor-parallel-size 8。
  • Decode 侧使用 --data-parallel-size 4、--data-parallel-size-local 4 和 --tensor-parallel-size 4。
  • 在本验证拓扑中,Prefill 和 Decode 两侧的 --max-num-batched-tokens 均设置为 8192。仅在激活内存充足时,才可增大 Prefill 侧的该值。
  • --kv-transfer-config 用于设置 Mooncake 连接器。在 Prefill 侧,kv_role 为 kv_producer;在 Decode 侧,kv_role 为 kv_consumer。
  • kv_connector_extra_config.prefill.dp_size/tp_size 和 decode.dp_size/tp_size 必须与实际全局 DP 和 TP 布局保持一致。
  • --no-enable-prefix-caching 用于禁用前缀缓存。对于 PD 分离部署,请先在不启用前缀缓存的情况下验证服务,然后再启用其他缓存特性。
  • 建议在 Decode 节点上使用 --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}',以减少 Decode 分发开销。

常见问题提示:如果遇到问题,请参阅公共 FAQ进行排查。

服务验证:

curl http://<server_ip>:<port>/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "qwen3-vl-235b",
        "messages": [
            {
                "role": "user",
                "content": "Who are you?"
            }
        ],
        "max_tokens": 256,
        "temperature": 0
    }'

预期结果:

服务返回 HTTP 200 OK,且 JSON 响应中包含 choices 字段。

6 功能验证

服务器启动后,发送请求以验证基本的多模态功能。对于单节点和 MP 部署,请使用节点 0 上的 API 端点。对于 PD 分离部署,请使用 Mooncake 部署指南中的代理端点。

curl http://<server_ip>:<port>/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3-vl-235b",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": [
        {"type": "image_url", "image_url": {"url": "https://modelscope.oss-cn-beijing.aliyuncs.com/resource/qwen.png"}},
        {"type": "text", "text": "What is the text in the illustration?"}
      ]}
    ],
    "max_completion_tokens": 100,
    "temperature": 0
  }'

预期结果:HTTP 状态码为 200,JSON 响应中包含带有生成文本的 choices 字段,例如与 TONGYI Qwen 类似的文本。

7 精度评估

使用 AISBench

  1. 有关详细信息,请参阅使用 AISBench。

  2. 执行完成后,即可获取结果。

数据集 版本 指标 模式 vllm-api-general-chat
textvqa-lite - 准确率 gen 83
aime2024 - 准确率 gen 93

8 性能评估

8.1 使用 AISBench

有关详细信息,请参阅使用 AISBench 进行性能评估。对于多模态性能测试,请使用包含图像负载的数据集(例如 TextVQA 风格的请求),而不是随机的纯文本提示词。

8.2 使用 vLLM Benchmark

以 Qwen3-VL-235B-A22B-Instruct 为例运行性能评估。更多详细信息,请参阅 vLLM benchmark。

vllm bench 包含三个子命令:

  • latency:对单批请求的延迟进行基准测试。
  • serve:对在线服务吞吐量进行基准测试。
  • throughput:对离线推理吞吐量进行基准测试。

以 serve 为例:

export VLLM_USE_MODELSCOPE=True

vllm bench serve \
  --model Eco-Tech/Qwen3-VL-235B-A22B-Instruct-w8a8-QuaRot \
  --served-model-name qwen3-vl-235b \
  --dataset-name random \
  --random-input 200 \
  --num-prompts 200 \
  --request-rate 1 \
  --save-result \
  --result-dir ./

几分钟后,即可获得性能评估结果。该随机基准测试适用于服务流水线验证;如需测试图像 token 性能,请使用 AISBench 或自定义多模态数据集。

9 性能调优

注意:以下配置已在特定测试环境中验证通过,仅供参考。最佳配置取决于硬件类型、最大输入/输出长度、图像分辨率、请求并发数、前缀缓存命中率、量化方式以及 prefill/decode 比例。请根据实际工作负载调整第 9.2 节中的参数。

表 1:场景概览

场景 部署模式 *NPU 总数 权重版本 关键注意事项
功能验证 单节点在线服务 16 个 A3 NPU W8A8 使用较短的上下文,禁用视频,并设置 --mm-processor-cache-gb 0 以降低内存压力。
长上下文 多节点 MP 16 个 A3 NPU W8A8 每个节点内使用 TP,节点间使用 DP。如果发生 OOM,请降低图像数量或上下文长度。
低时延 1P1D PD 分离 32 个 A3 NPU W8A8 分离 prefill 和 decode 资源,并在 decode 节点上启用 Full Decode ACLGraph。

*NPU 总数 指所有节点使用的 NPU 总数。1 个节点 = 1 台 Atlas 800 A3 服务器(64GB × 16 个 NPU)。

表 2:详细节点配置

场景 节点角色 NPU 数量 TP DP 最大序列数 最大模型长度 最大批处理 Token 数 前缀缓存 主要优化
功能验证 单节点 16 4 4 32 32768 16384 关闭 W8A8、FullGraph、序列并行、Fused MC2
长上下文 MP 节点 每节点 8 8 每节点 1,全局 2 每个 DP 16 262144 4096 关闭 FullGraph、序列并行、CPU 绑定
低时延 Prefill 节点 16 8 2 32 8192 8192 关闭 Mooncake KV producer、EP
低时延 Decode 节点 16 4 4 32 8192 8192 关闭 Mooncake KV consumer、FullGraph、EP

完整的启动命令和参数说明,请参阅第 5 章中的部署示例。

9.2 调优指南

9.2.1 通用调优参考

调优方法请参考公共性能调优文档。

详细的特性说明请参考特性矩阵。

  1. 首先确定部署拓扑。验证场景使用单节点部署,简单的多节点服务使用 MP 部署,当 prefill 和 decode 需要不同资源比例时使用 PD 分离部署。
  2. 使用 --max-model-len 选择最大上下文长度。多模态请求的 KV 缓存同时消耗文本 token 和视觉 token,因此如果发生 OOM,请降低图像分辨率、图像数量、--max-num-seqs 或上下文长度。
  3. 调整多模态限制。使用 --limit-mm-per-prompt.image 和 --limit-mm-per-prompt.video 匹配您的请求形态。仅处理图像的服务可使用 --limit-mm-per-prompt.video 0 禁用视频。
  4. 调整 --max-num-batched-tokens。较大的值通常能提高 prefill 吞吐量,但会增加激活内存。以 decode 为主的工作负载通常需要较小的值。
  5. 根据服务并发度调整 --max-num-seqs。超过该值的请求将在队列中等待,等待时间计入 TTFT 和 TPOT。
  6. 调整 --gpu-memory-utilization。增大该值可提供更多 KV 缓存,但需预留余量以应对运行时内存波动、图像预处理和专家负载不均。
  7. 调整 ACLGraph 捕获。decode 场景推荐使用 FULL_DECODE_ONLY。如果手动设置 cudagraph_capture_sizes,请包含常见的 decode 批处理大小。

9.3 模型专项优化

优化项 启用方式 收益 备注
多模态 Prompt 限制 --limit-mm-per-prompt.image、--limit-mm-per-prompt.video 避免为未使用的媒体类型预留内存。 仅图像服务时禁用视频。
多模态处理器缓存 --mm-processor-cache-gb 当重复媒体出现时缓存已处理的媒体特征。 内存受限的验证场景可设为 0。
Full Decode ACLGraph --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' 降低算子分发开销,稳定 decode 性能。 推荐用于以 decode 为主的服务。
Fused MC2 --additional-config '{"enable_fused_mc2": 1}' 启用 MoE 融合算子以提升 MoE 效率。 如果精度或性能下降,请与禁用状态进行对比。
前缀缓存 --enable-prefix-caching 改善重复前缀工作负载的性能。 先验证 HBM 使用情况。PD 场景建议先禁用前缀缓存。
PD 分离 --kv-transfer-config 将 prefill 和 decode 资源分离。 确保生产者/消费者的 DP 和 TP 大小与实际拓扑匹配。

10 常见问题

常见环境、安装和通用参数问题请参考公共 FAQ。本节仅介绍 Qwen3-VL-235B-A22B-Instruct 的模型相关问题。

Q1:为什么服务在启动时或接受请求后不久报 OOM?

现象: 服务在 profile run 阶段失败,或者成功启动但在真实流量到达时报 OOM。

原因: Qwen3-VL-235B-A22B-Instruct 的权重、KV 缓存和多模态预处理内存需求较高。较大的 --max-model-len、--max-num-seqs、--max-num-batched-tokens、较高的图像分辨率、每个 Prompt 中图像过多,或较高的 --gpu-memory-utilization,都可能导致 HBM 预留空间不足。

解决方案: 尽可能使用启用了 --quantization ascend 的 W8A8 模型,降低 --max-model-len、--max-num-seqs、--max-num-batched-tokens,降低图像/视频限制,或减小 --gpu-memory-utilization。保持 PYTORCH_NPU_ALLOC_CONF=expandable_segments:True。

Q2:为什么多节点 MP 部署在初始化期间挂起?

现象: 某个节点等待其他 rank,HCCL 初始化超时,或者 headless 节点退出。

原因: 各节点之间的网络接口名称、IP 地址、DP rank 或 RPC 端口不一致。

解决方案: 首先验证多节点通信。确保 HCCL_IF_IP、GLOO_SOCKET_IFNAME 和 HCCL_SOCKET_IFNAME 与所选 NIC 匹配。确保所有节点使用相同的 --data-parallel-rpc-port,非主节点使用 --headless,且 --data-parallel-start-rank 不重叠。

Q3:为什么在仅图像示例中禁用了视频?

现象: 服务预留了比预期更多的内存,或者即使请求仅包含图像,启动时也会发生 OOM。

原因: 允许视频输入会为长视觉嵌入和图像专用工作负载不需要的预处理路径预留内存。

解决方案: 对于仅图像服务,使用 --limit-mm-per-prompt.video 0。仅在您的工作负载需要时启用视频,如有需要,降低 --max-model-len 或请求并发数。

Q4:为什么启用前缀缓存后性能没有提升?

现象: 已启用前缀缓存,但吞吐量或延迟没有改善。

原因: 前缀缓存仅在请求共享可复用前缀时才有用。随机提示、唯一图像或较低的缓存命中率可能会增加内存压力,而没有可见收益。

解决方案: 对重复前缀工作负载启用前缀缓存。对于随机基准数据集、内存受限的长上下文工作负载或 PD 验证,请与 --no-enable-prefix-caching 进行比较。

Q5:为什么 PD 分离无法传输 KV 缓存?

现象: 请求到达代理或预填充服务,但解码节点不产生输出或报告 KV 传输错误。

原因: Mooncake 连接器端口、生产者/消费者角色,或 kv_connector_extra_config 中的 DP/TP 大小与实际拓扑不匹配。

解决方案: 检查所有节点上的 kv_role、kv_port 以及预填充/解码 DP/TP 大小。从第 5.4 节中经过验证的拓扑开始,然后每次只更改一个维度。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 vl/vllm-ascend