Qwen3-VL-235B-A22B-Instruct#

1 引言#

Qwen3-VL-235B-A22B-Instruct 是 Qwen3-VL 系列中的大规模稀疏 MoE 视觉语言模型,专为多模态对话、图像理解、多图推理、类OCR视觉问答以及长上下文生成而设计。

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

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

2 支持特性#

请参阅支持特性列表以获取该模型的支持特性矩阵。

请参考特性指南获取特性的配置说明。

3 前提条件#

3.1 模型权重#

  • Qwen3-VL-235B-A22B-Instruct(BF16版本):需要1个Atlas 800 A3(64G x 16)节点或2个Atlas 800 A2(64G x 8)节点。模型权重

  • Qwen3-VL-235B-A22B-Instruct-w8a8-QuaRot(单节点验证使用的量化版本):需要1个Atlas 800 A3(64G x 16)节点。模型权重

  • Qwen3-VL-235B-A22B-Instruct-w8a8-mxfp8(量化版本):需要1个Ascend 950DT(96G x 8)节点。模型权重

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

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

如果要在多节点环境中部署模型,请按照验证多节点通信环境验证通信环境。

4 安装#

4.1 Docker镜像安装#

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

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

export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-#TODO
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 \
    --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 \
    -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 \
    --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 \
    -it $IMAGE bash

成功运行docker后,可通过执行docker ps命令验证正在运行的容器服务。

4.2 源码安装#

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

  1. 克隆并安装vLLM:

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

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

安装验证:

pip show vllm vllm-ascend

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

备注

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

更多详情请参考安装指南

5 在线服务部署#

5.1 单节点在线部署#

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

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

#!/bin/sh

# Load model from ModelScope to speed up download.
export VLLM_USE_MODELSCOPE=True

# Reduce memory fragmentation and avoid out-of-memory errors.
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True

export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_BUFFSIZE=400
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=100
export TASK_QUEUE_ENABLE=1
export VLLM_ASCEND_ENABLE_FLASHCOMM1=1

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

# Reduce memory fragmentation and avoid out-of-memory errors.
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True

export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_BUFFSIZE=1536
export OMP_NUM_THREADS=1
export OMP_PROC_BIND=false
export TASK_QUEUE_ENABLE=1
export VLLM_ASCEND_ENABLE_FLASHCOMM1=1
export VLLM_ASCEND_ENABLE_FUSED_MC2=1
export VLLM_ASCEND_BALANCE_SCHEDULING=1

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]}'

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

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

关键参数:

  • --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缓存大小,但如果运行时内存高于profile运行值,可能触发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 重放以减少调度开销。

5.3 多节点 PD 分离部署#

PD 分离将 Prefill 和 Decode 划分为不同的服务组。Prefill 节点处理大型提示块,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 + 完整解码 ACLGraph。

5.3.1 Prefill 节点#

在 prefill 节点上创建 run_p.sh

#!/bin/bash

export VLLM_USE_MODELSCOPE=True
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=1024
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=1
export HCCL_OP_EXPANSION_MODE="AIV"
export TASK_QUEUE_ENABLE=1

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 PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=1024
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=1
export HCCL_OP_EXPANSION_MODE="AIV"
export TASK_QUEUE_ENABLE=1

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

  • 在此验证拓扑中,两侧的 --max-num-batched-tokens 均设置为 8192。仅在激活内存充足时增加 prefill 的值。

  • --kv-transfer-config 设置 Mooncake 连接器。kv_role 在 prefill 上为 kv_producer,在 decode 上为 kv_consumer

  • kv_connector_extra_config.prefill.dp_size/tp_sizedecode.dp_size/tp_size 必须与实际全局 DP 和 TP 布局匹配。

  • --no-enable-prefix-caching 禁用前缀缓存。对于 PD 分离,请先在不启用前缀缓存的情况下验证服务,然后再启用其他缓存功能。

  • 建议在 decode 节点上使用 --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' 以减少解码调度开销。

常见问题提示:如果遇到问题,请参考公共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

-

准确率

生成

83

aime2024

-

准确率

生成

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 ./

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

9 性能调优#

9.2 调优指南#

9.2.1 通用调优参考#

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

详细功能说明请参考功能矩阵

9.3 模型特定优化#

优化项

启用方式

收益

备注

多模态提示限制

--limit-mm-per-prompt.image, --limit-mm-per-prompt.video

避免为未使用的媒体类型预留内存。

纯图像服务时禁用视频。

多模态处理器缓存

--mm-processor-cache-gb

当重复媒体出现时缓存已处理的媒体特征。

内存受限验证时设为 0。

全解码 ACLGraph

--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}'

减少算子调度开销,稳定解码性能。

推荐用于解码密集型服务。

FlashComm1

VLLM_ASCEND_ENABLE_FLASHCOMM1=1--additional-config '{"enable_flashcomm1":true}'

减少大 TP 和高并发场景下的通信开销。

可能对低并发工作负载无帮助。

融合 MC2

VLLM_ASCEND_ENABLE_FUSED_MC2=1

启用 MoE 融合算子以提升 MoE 效率。

若精度或性能下降,请与禁用状态对比。

前缀缓存

--enable-prefix-caching

改善重复前缀工作负载。

先验证 HBM 使用情况。对于 PD,建议先禁用前缀缓存。

异步调度

--async-scheduling

可提升高并发吞吐量。

对延迟敏感的工作负载,请禁用并对比。

PD 分离

--kv-transfer-config

分离预填充和解码资源。

确保生产者/消费者的 DP 和 TP 大小与实际拓扑匹配。

10 常见问题#

关于常见环境、安装和通用参数问题,请参考公共常见问题。本节仅涵盖 Qwen3-VL-235B-A22B-Instruct 的模型特定问题。

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

现象: 服务在 profile 运行期间失败,或者成功启动但在真实流量到达时报告 OOM。

原因: Qwen3-VL-235B-A22B-Instruct 对权重、KV 缓存和多模态预处理内存需求较高。较大的 --max-model-len--max-num-seqs--max-num-batched-tokens、高图像分辨率、每个提示中图像过多或较高的 --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 初始化超时,或无头节点退出。

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

解决方案: 首先验证多节点通信。确保 HCCL_IF_IPGLOO_SOCKET_IFNAMETP_SOCKET_IFNAMEHCCL_SOCKET_IFNAME 与所选网卡匹配。确保所有节点使用相同的 --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_rolekv_port以及预填充/解码的DP/TP大小。从第5.4节已验证的拓扑开始,然后每次只更改一个维度。