跳转至

Qwen3.5-27B 与 Qwen3.6-27B

1 简介

Qwen3.5-27B 和 Qwen3.6-27B 是 Qwen3.5/Qwen3.6 系列中的稠密混合 Mamba-Transformer 语言模型,融合了架构效率、强化学习规模和全球可访问性方面的突破。它们采用相同的混合注意力设计(GDN + 全注意力),因此在 Ascend NPU 上的部署方式对两个模型一致。它们适用于在 Ascend NPU 上运行的通用文本生成任务,例如对话、内容创作和代码生成。

本文档将演示这些模型的主要验证步骤,包括支持的特性、特性配置、环境准备、单节点和多节点部署,以及精度和性能评估。

强烈建议使用 vllm-ascend 的最新候选版本(rc)或最新正式版本。作为最低版本要求,Qwen3.5-27B 首次在 vllm-ascend:v0.17.0rc1 中得到支持,Qwen3.6-27B 首次在 vllm-ascend:v0.18.0rc1 中得到支持。对 Atlas 300I DUO 和 950DT Products 的支持从 vllm-ascend:v0.23.0rc1 开始。

2 支持的特性

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

有关特性配置信息,请参阅特性指南。

3 前提条件

3.1 模型权重

权重版本 硬件要求 下载链接
Qwen3.5-27B(BF16 版本) 1 个 Atlas 800 A3(64GB × 16)节点,或 1 个 Atlas 800 A2(64GB × 8)节点,或 Atlas 300I DUO ModelScope | Hugging Face
Qwen3.5-27B-w8a8(量化版本) 1 个 Atlas 800 A3(64GB × 16)节点,或 1 个 Atlas 800 A2(64GB × 8)节点,或 Atlas 300I DUO ModelScope
Qwen3.6-27B(BF16 版本) 1 个 950DT Products(96GB × 8)节点,或 1 个 Atlas 800 A3(64GB × 16)节点,或 1 个 Atlas 800 A2(64GB × 8)节点,或 Atlas 300I DUO ModelScope | Hugging Face
Qwen3.6-27B-w8a8(量化版本) 1 个 Atlas 800 A3(64GB × 16)节点,或 1 个 Atlas 800 A2(64GB × 8)节点 ModelScope
Qwen3.6-27B-w8a8-mxfp8(量化版本) 1 个 950DT Products(96GB × 8)节点 ModelScope
Qwen3.6-27B-w8a8-310p(量化版本) 1 个 Atlas 300I DUO ModelScope

建议将模型权重下载到多节点的共享目录,例如 /root/.cache/。

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

3.2 验证多节点通信

如果要部署多节点环境,需要按照验证多节点通信环境进行多节点通信验证。

4 安装

4.1 Docker 镜像安装

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

建议使用 vllm-ascend 镜像的最新候选版本(rc)或最新正式版本,以确保最佳兼容性并获取最新特性。作为最低版本要求,对于 Qwen3.5-27B 使用 vllm-ascend:v0.17.0rc1(或更高版本),对于 Qwen3.6-27B 使用 vllm-ascend:v0.18.0rc1(或更高版本)。对于 Atlas 800 A3 上的 Qwen3.6-27B,请使用匹配的 v0.18.0rc1-a3(或更高版本的 -a3)镜像。对于 Atlas 300I DUO,请使用 vllm-ascend:v0.23.0rc1-310p(或更高版本的 -310p)镜像。

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

export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-a3
docker run --rm \
    --name vllm-ascend \
    --shm-size=1g \
    --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 /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=1g \
    --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 /root/.cache:/root/.cache \
    -it $IMAGE bash

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

export IMAGE=quay.io/ascend/vllm-ascend:v0.23.0-310p
docker run --rm \
    --name vllm-ascend \
    --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/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

在每个节点上启动 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 \
    -it $IMAGE bash

docker run 成功之后,你可以通过执行 docker ps 命令来验证正在运行的容器服务。预期结果是容器 vllm-ascend 出现在列表中且状态为 Up,这确认 docker 安装成功。

4.2 源码安装

如果你不想像上面那样使用 docker 镜像,你也可以全部从源码构建:

  1. 克隆仓库并从源码安装 vllm-ascend:

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

    完整的安装步骤请参阅 安装。

    Note

    在 Atlas 300I DUO 上,你可能需要卸载 triton-ascend 和 triton 以避免依赖冲突:

    pip uninstall -y triton-ascend triton
    
  2. 如果你想部署多节点环境,你需要在每个节点上设置环境。

要验证源码安装,请运行以下命令并确认显示的版本与你安装的版本一致:

pip show vllm-ascend

预期结果:显示 vllm-ascend 的版本信息,确认安装成功。

5 在线服务部署

5.1 单节点在线部署

单节点部署在同一节点内完成 Prefill 和 Decode,适用于开发、测试以及中等规模推理场景。Qwen3.5-27B、Qwen3.5-27B-w8a8、Qwen3.6-27B 和 Qwen3.6-27B-w8a8 模型均可部署在 1 台 Atlas 800 A3(64GB × 16)或 1 台 Atlas 800 A2(64GB × 8)上。在 Atlas 300I DUO 上,至少需要 2 个设备。Qwen3.6-27B 和 Qwen3.6-27B-w8a8-mxfp8 模型均可部署在 1 台 950DT Products(96GB × 8)上。量化版本需要使用 --quantization ascend 参数启动。

Qwen3.5-27B 和 Qwen3.6-27B 共享相同的 MTP 头部设计,因此两者都可以使用 qwen3_5_mtp 投机解码方法。

以下示例适用于 Atlas 800 A3 / Atlas 800 A2。量化版本需要 --quantization ascend。

启动命令:

#!/bin/sh
# Load model from ModelScope to speed up download
export MODEL_PATH=Eco-Tech/Qwen3.5-27B-w8a8-mtp
export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=512
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# To reduce memory fragmentation and avoid out of memory
# Size of the shared buffer (in MB) used by HCCL for NPU-to-NPU collective communication

# Model weight path; can be a ModelScope model id (e.g., Eco-Tech/Qwen3.5-27B-w8a8-mtp) or a local directory path
# Ensure the model path matches the directory recorded during download

vllm serve $MODEL_PATH \
    --host 0.0.0.0 \
    --port 8000 \
    --data-parallel-size 1 \
    --tensor-parallel-size 2 \
    --seed 1024 \
    --quantization ascend \
    --served-model-name qwen3.5 \
    --max-num-seqs 32 \
    --max-model-len 133000 \
    --max-num-batched-tokens 16384 \
    --trust-remote-code \
    --gpu-memory-utilization 0.90 \
    --no-enable-prefix-caching \
    --speculative-config '{"method": "qwen3_5_mtp", "num_speculative_tokens": 3, "enforce_eager": true}' \
    --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
    --additional-config '{"enable_cpu_binding":true}'

启动命令:

#!/bin/sh
# Load model from ModelScope to speed up download
export MODEL_PATH=Eco-Tech/Qwen3.6-27B-w8a8
export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=512
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# To reduce memory fragmentation and avoid out of memory
# Size of the shared buffer (in MB) used by HCCL for NPU-to-NPU collective communication

# Model weight path; can be a ModelScope model id (e.g., Eco-Tech/Qwen3.6-27B-w8a8) or a local directory path
# Ensure the model path matches the directory recorded during download

vllm serve $MODEL_PATH \
    --host 0.0.0.0 \
    --port 8000 \
    --data-parallel-size 1 \
    --tensor-parallel-size 2 \
    --seed 1024 \
    --quantization ascend \
    --served-model-name qwen3.6 \
    --max-num-seqs 32 \
    --max-model-len 262144 \
    --max-num-batched-tokens 16384 \
    --trust-remote-code \
    --gpu-memory-utilization 0.90 \
    --no-enable-prefix-caching \
    --speculative-config '{"method": "qwen3_5_mtp", "num_speculative_tokens": 3, "enforce_eager": true}' \
    --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
    --additional-config '{"enable_cpu_binding":true}'

关键参数说明:

- `--data-parallel-size 1` 和 `--tensor-parallel-size 2` 是数据并行(DP)和张量并行(TP)大小的常见设置。
- `--max-model-len` 表示上下文长度,即单个请求的输入加输出的最大值。Qwen3.6-27B 模型最高支持 262144。
- `--max-num-seqs` 表示每个 DP 组允许处理的最大请求数。如果发送到服务的请求数超过该限制,超出的请求将保持等待状态,不会被调度。请注意,等待状态所花费的时间也会计入 TTFT 和 TPOT 等指标。因此,在测试性能时,通常建议 `--max-num-seqs` * `--data-parallel-size` >= 实际总并发数。
- `--max-num-batched-tokens` 表示模型在单个步骤中可处理的最大 token 数。目前,vLLM v1 调度默认启用 ChunkPrefill/SplitFuse,其含义为:
    - (1) 如果请求的输入长度大于 `--max-num-batched-tokens`,将根据 `--max-num-batched-tokens` 拆分为多轮计算;
    - (2) 解码请求优先调度,仅在存在可用容量时才调度 prefill 请求。
    - 通常,如果将 `--max-num-batched-tokens` 设置为更大的值,整体延迟会更低,但对 HBM 内存(激活值占用)的压力会更大。
- `--gpu-memory-utilization` 表示 vLLM 将用于实际推理的 HBM 比例。其本质功能是计算可用的 kv_cache 大小。在预热阶段(在 vLLM 中称为 profile run),vLLM 会记录输入大小为 `--max-num-batched-tokens` 的推理过程中的峰值 HBM 内存使用量。随后,可用的 kv_cache 大小按以下公式计算:`--gpu-memory-utilization` * HBM 大小 - 峰值 HBM 内存使用量。因此,`--gpu-memory-utilization` 的值越大,可使用的 kv_cache 就越多。然而,由于预热阶段的 HBM 内存使用量可能与实际推理时不同(例如由于 EP 负载不均衡),将 `--gpu-memory-utilization` 设置得过高可能导致实际推理中出现 OOM(内存溢出)问题。默认值为 `0.9`。
- `--no-enable-prefix-caching` 在上面的示例中禁用了前缀缓存。对于具有长共享前缀的工作负载,可以使用 `--enable-prefix-caching --prefix-match-unit 16` 启用更细粒度的混合前缀匹配。匹配单元必须能整除每个 KV cache 组的块大小。更小的单元可以复用更多部分物理页,但代价是额外的哈希元数据、写时复制操作,以及在最终匹配边界处额外的一次 prefill 拆分。
- `--quantization ascend` 表示使用了量化。若要禁用量化,请移除此选项。
- `--speculative-config` 对 `Qwen3.5-27B` 和 `Qwen3.6-27B` 均使用 `qwen3_5_mtp`,因为它们共享相同的 MTP head 设计。
- `--compilation-config` 包含与 aclgraph 图模式相关的配置。最重要的配置是 `"cudagraph_mode"` 和 `"cudagraph_capture_sizes"`,其含义如下:
    - `"cudagraph_mode"`:表示具体的图模式。目前支持 `"PIECEWISE"` 和 `"FULL_DECODE_ONLY"`。图模式主要用于降低算子调度开销。目前推荐 `"FULL_DECODE_ONLY"`。
    - `"cudagraph_capture_sizes"`:表示不同级别的图模式。默认值为 `[1, 2, 4, 8, 16, 24, 32, 40,..., --max-num-seqs]`。在图模式下,不同级别图的输入是固定的,级别之间的输入会自动填充到下一级。目前推荐默认设置。仅在某些场景下,才需要单独设置该项以获得最佳性能。

目前仅支持 TP 场景。根据可用设备选择 TP=2 或 TP=4。将 MODEL_PATH 替换为 ModelScope 模型 ID 或本地目录路径。量化版本需要以 --quantization ascend 参数启动。

启动命令:

#!/bin/sh
# Load model from ModelScope to speed up download
export MODEL_PATH=Eco-Tech/Qwen3.5-27B-w8a8-mtp
export VLLM_USE_MODELSCOPE=True

# Model weight path; can be a ModelScope model id (e.g., Eco-Tech/Qwen3.5-27B-w8a8-mtp) or a local directory path
# Ensure the model path matches the directory recorded during download

vllm serve $MODEL_PATH \
    --host 127.0.0.1 \
    --port 8000 \
    --tensor-parallel-size 4 \
    --served-model-name qwen3.5 \
    --max-num-seqs 128 \
    --max-model-len 16384 \
    --trust-remote-code \
    --gpu-memory-utilization 0.90 \
    --mamba-ssm-cache-dtype float16 \
    --dtype float16 \
    --speculative-config '{"method": "qwen3_5_mtp","num_speculative_tokens":1}' \
    --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [2,16]}' \
    --additional-config '{"ascend_compilation_config": {"enable_npugraph_ex": false}}'

启动命令:

#!/bin/sh
# Load model from ModelScope to speed up download
export MODEL_PATH=Eco-Tech/Qwen3.6-27B-w8a8-310p
export VLLM_USE_MODELSCOPE=True

# Model weight path; can be a ModelScope model id (e.g., Eco-Tech/Qwen3.6-27B-w8a8) or a local directory path
# Ensure the model path matches the directory recorded during download

vllm serve $MODEL_PATH \
    --host 127.0.0.1 \
    --port 8000 \
    --tensor-parallel-size 4 \
    --served-model-name qwen3.6 \
    --max-num-seqs 128 \
    --max-model-len 16384 \
    --trust-remote-code \
    --gpu-memory-utilization 0.90 \
    --mamba-ssm-cache-dtype float16 \
    --dtype float16 \
    --speculative-config '{"method": "qwen3_5_mtp","num_speculative_tokens":1}' \
    --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [2,16]}' \
    --additional-config '{"ascend_compilation_config": {"enable_npugraph_ex": false}}'

Key Parameter Descriptions:

- `--tensor-parallel-size` 设置张量并行大小。根据可用设备选择 **TP=2** 或 **TP=4**。
- `--max-model-len` 表示上下文长度,即单次请求的输入加输出的最大值。请根据实际工作负载和可用内存进行配置;Qwen3.6-27B 模型最大支持 262144。
- `--max-num-seqs` 表示最大并发请求数。请按需配置——设置过高可能导致 OOM。
- `--gpu-memory-utilization` 表示 vLLM 将用于实际推理的 HBM 比例。请根据实际设备内存配置该值;设置过高可能导致 OOM。默认值为 `0.9`。
- `--mamba-ssm-cache-dtype` 设置 Mamba SSM 缓存的数据类型。在 Atlas 300I DUO 上,仅支持 `float16`。
- `--dtype float16` 必须在 Atlas 300I DUO 上设置。这些设备仅支持 FP16 数据类型。
- `--speculative-config` 对于 `Qwen3.5-27B` 和 `Qwen3.6-27B` 都使用 `qwen3_5_mtp`,因为它们共享相同的 MTP 头设计。在 Atlas 300I DUO 上,建议将 `num_speculative_tokens` 设置为 `1`。
- `--compilation-config` 包含与 aclgraph 图模式相关的配置。其中最重要的配置是 `"cudagraph_mode"` 和 `"cudagraph_capture_sizes"`,含义如下:
    - `"cudagraph_mode"`:表示具体的图模式。目前支持 `"PIECEWISE"` 和 `"FULL_DECODE_ONLY"`。图模式主要用于降低算子分发开销。目前推荐使用 `"FULL_DECODE_ONLY"`。
    - `"cudagraph_capture_sizes"`:表示不同级别的图模式。启用张量并行(TP)时,硬件 event-id 约束最多允许两个捕获大小(例如 `[1, 8]`)。启用 MTP 时,每个捕获大小按 `n * (num_speculative_tokens + 1)` 计算,其中 `n` 是未启用 MTP 时的捕获大小。例如,当 `num_speculative_tokens` 为 `1` 时,非 MTP 大小 `[1,2,4,8]` 变为 `[2,4,8,16]`。
- `--additional-config` 在 Atlas 300I DUO 上需要设置,其中包含 `"ascend_compilation_config": {"enable_npugraph_ex": false}`,因为该平台不支持 `enable_npugraph_ex`。

以下示例适用于 950DT 产品。量化版本需要 --quantization ascend。

启动命令:

#!/bin/sh
# Load model from ModelScope to speed up download
export MODEL_PATH=Eco-Tech/Qwen3.6-27B-w8a8-mxfp8
export VLLM_USE_MODELSCOPE=True
export HCCL_BUFFSIZE=512
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# To reduce memory fragmentation and avoid out of memory
# Size of the shared buffer (in MB) used by HCCL for NPU-to-NPU collective communication

# Model weight path; can be a ModelScope model id (e.g., Eco-Tech/Qwen3.6-27B-w8a8-mxfp8) or a local directory path
# Ensure the model path matches the directory recorded during download

vllm serve $MODEL_PATH \
    --host 0.0.0.0 \
    --port 8000 \
    --data-parallel-size 1 \
    --tensor-parallel-size 1 \
    --seed 1024 \
    --quantization ascend \
    --served-model-name qwen3.6 \
    --max-num-seqs 32 \
    --max-model-len 262144 \
    --max-num-batched-tokens 16384 \
    --trust-remote-code \
    --gpu-memory-utilization 0.90 \
    --no-enable-prefix-caching \
    --speculative-config '{"method": "qwen3_5_mtp", "num_speculative_tokens": 3, "enforce_eager": true}' \
    --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
    --additional-config '{"enable_cpu_binding":true}'

关键参数说明:

  • --data-parallel-size 1 和 --tensor-parallel-size 1 分别是数据并行(DP)和张量并行(TP)大小的常用设置。
  • --max-model-len 表示上下文长度,即单次请求的输入加输出的最大值。Qwen3.6-27B 模型最大支持 262144。
  • --max-num-seqs 表示每个 DP 组允许处理的最大请求数。如果发送到服务的请求数超过此限制,超出的请求将保持等待状态,不会被调度。请注意,等待状态花费的时间也会计入 TTFT 和 TPOT 等指标。因此,在测试性能时,通常建议 --max-num-seqs * --data-parallel-size >= 实际总并发数。
  • --max-num-batched-tokens 表示模型单步可处理的最大 token 数。目前,vLLM v1 调度默认启用 ChunkPrefill/SplitFuse,这意味着:
    • (1) 如果请求的输入长度大于 --max-num-batched-tokens,则按 --max-num-batched-tokens 将输入分成多轮计算;
    • (2) 优先调度 Decode 请求,仅当有剩余容量时才调度 Prefill 请求。
    • 通常,--max-num-batched-tokens 设置得越大,整体时延越低,但对 HBM 内存(激活值占用)的压力也越大。
  • --gpu-memory-utilization 表示 vLLM 将用于实际推理的 HBM 比例。其核心作用是计算可用的 kv_cache 大小。在预热阶段(vLLM 中称为 profile run),vLLM 会记录在输入大小为 --max-num-batched-tokens 的推理过程中的 HBM 峰值内存占用。可用 kv_cache 大小计算如下:--gpu-memory-utilization * HBM 大小 - HBM 峰值内存占用。因此,--gpu-memory-utilization 的值越大,可用的 kv_cache 越多。但由于预热阶段的 HBM 内存占用可能与实际推理时不同(例如,由于 EP 负载不均衡),设置过高可能会导致实际推理时出现 OOM(内存不足)问题。默认值为 0.9。
  • --no-enable-prefix-caching 表示禁用前缀缓存。Qwen3.6-27B 当前的混合 kv cache 实现可能会导致启用前缀缓存时实际的 block_size 非常大(例如 2048),这意味着任何短于 block_size 的前缀都不会被缓存。如果工作负载中有大量较短且重复的前缀,请考虑保持禁用前缀缓存。相关问题请参阅常见问题。
  • --quantization ascend 表示使用量化。要禁用量化,请移除该选项。
  • --speculative-config 对 Qwen3.6-27B 使用 qwen3_5_mtp,因为它与 Qwen3.5-27B 共享相同的 MTP 头设计。
  • --compilation-config 包含与 aclgraph 图模式相关的配置。其中最重要的配置是 "cudagraph_mode" 和 "cudagraph_capture_sizes",含义如下:
    • "cudagraph_mode":表示具体的图模式。目前支持 "PIECEWISE" 和 "FULL_DECODE_ONLY"。图模式主要用于降低算子分发开销。目前推荐使用 "FULL_DECODE_ONLY"。
    • "cudagraph_capture_sizes":表示不同级别的图模式。默认值为 [1, 2, 4, 8, 16, 24, 32, 40,..., --max-num-seqs]。在图模式下,不同级别图的输入是固定的,级别之间的输入会自动填充到下一级别。目前推荐使用默认设置。仅在部分场景下需要单独设置以获得最佳性能。

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

服务验证:

如果服务启动成功,将显示以下启动日志:

(APIServer pid=<pid>) INFO:     Started server process [<pid>]
(APIServer pid=<pid>) INFO:     Waiting for application startup.
(APIServer pid=<pid>) INFO:     Application startup complete.

有关功能测试(例如,带预期响应的 completions 和 chat.completions curl 示例),请参阅第 6 节。

5.2 多节点 PD 分离部署

Note

多节点 PD 分离部署在 Atlas 300I DUO 上不受支持。

对于高并发生产场景,可以使用多节点 PD(Prefill-Decode)分离来扩展服务。推荐使用 Mooncake 进行部署:Mooncake 多节点 PD 分离指南。

在标准的单节点部署模式下,Prefill(提示处理)和 Decode(令牌生成)任务运行在同一组 NPU 上。这可能导致两个问题:

  1. Prefill 抢占中断 Decode:Prefill 是一项计算密集型任务,一次性处理整个输入上下文,而 Decode 逐个生成令牌。当新的用户请求到达时,其 Prefill 阶段会抢占并中断正在进行的 Decode 任务,导致抖动和更高的每输出令牌时间(TPOT)延迟。
  2. 资源分配不灵活:Prefill 和 Decode 具有根本不同的计算特征——Prefill 受计算限制且对内存带宽要求高,而 Decode 受内存带宽限制。将它们运行在同一硬件上会迫使二者妥协,无法使任何一方达到最优。

PD(Prefill-Decode)分离通过在专用的节点组上分别运行 Prefill 和 Decode 来解决这些问题,每个节点组独立配置:

  • Prefill 节点专注于高吞吐量的提示处理,针对计算和通信进行了优化(例如,启用序列并行以实现 Allreduce 加速)。
  • Decode 节点专注于低延迟的令牌生成,针对内存带宽进行了优化(例如,启用 full-decode aclgraph)。

对于 Qwen3.5-27B-w8a8 和 Qwen3.6-27B-w8a8,典型的 1P1D 配置需要 2 个 Atlas 800 A3(64GB × 16)节点(1 个 Prefill 节点 + 1 个 Decode 节点),每个节点上 TP=2 和 DP=8,这充分利用了 Atlas A3 的全部 16 个 NPU。下面的示例使用 Qwen3.5-27B-w8a8;对于 Qwen3.6-27B-w8a8,请将模型路径替换为 Eco-Tech/Qwen3.6-27B-w8a8,并将 --served-model-name 调整为 qwen3.6(如有需要,--max-model-len 可调整为 262144)。

为什么是 TP=2 + DP=8(DP 优先策略)? Qwen3.5-27B-w8a8(以及 Qwen3.6-27B-w8a8)模型仅约 30 GB,可以轻松放入单个 NPU(每个 NPU 有 64 GB HBM)。TP > 1 主要用于无法放入单个 NPU 的模型。 对于 27 B 的模型,TP=2 足以在 NPU 之间平衡算子分发开销,同时 最大化 DP 可让 Atlas A3 的全部 16 个 NPU 忙于处理独立的请求批次,从而充分利用硬件。这种 DP 优先的并行策略 是小型稠密模型(例如 Qwen3.5-27B、Qwen3.6-27B、Llama-3-8B)的标准做法,并已通过 Qwen3.5-27B B200 基准测试 验证,其中从 TP=8 切换到 DP=8 后,单节点吞吐量从 9.5k 提升到 95k tokens/s。

注意:由于 Qwen3.5-27B 和 Qwen3.6-27B 适合在单个节点上运行,多节点 PD 分离仅推荐用于高并发生产部署。有关 Mooncake 部署的具体信息,请参阅 Mooncake 多节点 PD 分离指南。

要运行 vllm-ascend Prefill-Decode 分离服务,您需要:

  • 在每个节点上部署 launch_online_dp.py 脚本和 run_dp_template.sh 脚本;
  • 在 prefill 主节点上部署 load_balance_proxy_server_example.py 脚本以转发请求。

  • launch_online_dp.py 用于启动外部 dp vllm 服务器。 launch_online_dp.py

    参数说明:

    参数 类型 是否必填 默认值 描述
    --dp-size int 是 - 数据并行大小(所有节点上 DP rank 的总数)。
    --tp-size int 否 1 每个 DP rank 内的张量并行大小。
    --dp-size-local int 否 (与 --dp-size 相同) 当前节点上的 DP rank 数量。如果未设置,默认值为 --dp-size。
    --dp-rank-start int 否 0 此节点上数据并行 rank 的起始 rank 偏移量。
    --dp-address str 是 - 数据并行主节点(节点 0)的 IP 地址。
    --dp-rpc-port str 否 12345 用于数据并行主节点通信的 RPC 端口。
    --vllm-start-port int 否 9000 此节点上每个 vLLM 引擎实例的起始端口。每个 DP rank 的引擎端口 = vllm_start_port + 本地 rank 索引。
  • Prefill 节点 0 的 run_dp_template.sh 脚本。您可以在仓库的 examples 目录中获取该模板:run_dp_template.sh。

    # nic_name is the network interface name corresponding to local_ip of the current node
    nic_name="xxx"
    local_ip="192.xx.xx.1"
    
    export HCCL_BUFFSIZE=1024
    export HCCL_IF_IP=$local_ip
    export HCCL_OP_EXPANSION_MODE="AIV"
    export HCCL_SOCKET_IFNAME=$nic_name
    export ASCEND_RT_VISIBLE_DEVICES=$1
    export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages/mooncake:$LD_LIBRARY_PATH
    export GLOO_SOCKET_IFNAME=$nic_name
    export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
    
    # [Optional] jemalloc
    # jemalloc is for better performance, if `libjemalloc.so` is installed on your machine, you can turn it on.
    # export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libjemalloc.so.2:$LD_PRELOAD
    
    
    # Ensure the model path matches the directory recorded during download
    vllm serve Eco-Tech/Qwen3.5-27B-w8a8-mtp \
      --host 0.0.0.0 \
      --port $2 \
      --data-parallel-size $3 \
      --data-parallel-rank $4 \
      --data-parallel-address $5 \
      --data-parallel-rpc-port $6 \
      --tensor-parallel-size $7 \
      --seed 1024 \
      --quantization ascend \
      --served-model-name qwen3.5 \
      --trust-remote-code \
      --max-num-seqs 4 \
      --max-model-len 32768 \
      --max-num-batched-tokens 16384 \
      --no-enable-prefix-caching \
      --gpu-memory-utilization 0.95 \
      --enforce-eager \
      --speculative-config '{"method": "qwen3_5_mtp", "num_speculative_tokens": 3, "enforce_eager": true}' \
      --additional-config '{"enable_cpu_binding":true}' \
      --kv-transfer-config \
      '{"kv_connector": "MooncakeConnectorV1",
      "kv_role": "kv_producer",
      "kv_port": "30000",
      "engine_id": "0",
      "kv_connector_extra_config": {
                "prefill": {
                        "dp_size": 8,
                        "tp_size": 2
                },
                "decode": {
                        "dp_size": 8,
                        "tp_size": 2
            }
        }
      }'
    
  • 解码节点 0 的 run_dp_template.sh 脚本。您可以在仓库的 examples 目录中获取该模板:run_dp_template.sh。

    # nic_name is the network interface name corresponding to local_ip of the current node
    nic_name="xxx"
    local_ip="192.xx.xx.2"
    
    export HCCL_BUFFSIZE=1024
    export HCCL_IF_IP=$local_ip
    export HCCL_OP_EXPANSION_MODE="AIV"
    export HCCL_SOCKET_IFNAME=$nic_name
    export ASCEND_RT_VISIBLE_DEVICES=$1
    export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages/mooncake:$LD_LIBRARY_PATH
    export GLOO_SOCKET_IFNAME=$nic_name
    export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
    
    # [Optional] jemalloc
    # jemalloc is for better performance, if `libjemalloc.so` is installed on your machine, you can turn it on.
    # export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libjemalloc.so.2:$LD_PRELOAD
    
    
    # Ensure the model path matches the directory recorded during download
    vllm serve Eco-Tech/Qwen3.5-27B-w8a8-mtp \
      --host 0.0.0.0 \
      --port $2 \
      --data-parallel-size $3 \
      --data-parallel-rank $4 \
      --data-parallel-address $5 \
      --data-parallel-rpc-port $6 \
      --tensor-parallel-size $7 \
      --seed 1024 \
      --quantization ascend \
      --served-model-name qwen3.5 \
      --trust-remote-code \
      --max-num-seqs 16 \
      --max-model-len 32768 \
      --max-num-batched-tokens 2048 \
      --no-enable-prefix-caching \
      --gpu-memory-utilization 0.91 \
      --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
      --additional-config '{"recompute_scheduler_enable":true,"enable_cpu_binding":true}' \
      --speculative-config '{"method": "qwen3_5_mtp", "num_speculative_tokens": 3, "enforce_eager": true}' \
      --kv-transfer-config \
      '{"kv_connector": "MooncakeConnectorV1",
      "kv_role": "kv_consumer",
      "kv_port": "30200",
      "engine_id": "1",
      "kv_connector_extra_config": {
                "prefill": {
                        "dp_size": 8,
                        "tp_size": 2
                },
                "decode": {
                        "dp_size": 8,
                        "tp_size": 2
            }
        }
      }'
    

关键参数说明:

  • recompute_scheduler_enable: true:启用重计算调度器。当解码节点的 KV Cache 不足时,请求将被发送到预填充节点以重新计算 KV Cache。在 PD 分离场景中,仅在解码节点上启用此配置。
  • --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}'(在解码节点上):启用完整解码 aclgraph 模式,可显著降低解码侧的调度延迟。

  • 为每个节点运行服务器:

    # p0 (Prefill node 0)
    python launch_online_dp.py --dp-size 8 --tp-size 2 --dp-size-local 8 --dp-rank-start 0 --dp-address 192.xx.xx.1 --dp-rpc-port 12321 --vllm-start-port 7100
    # d0 (Decode node 0)
    python launch_online_dp.py --dp-size 8 --tp-size 2 --dp-size-local 8 --dp-rank-start 0 --dp-address 192.xx.xx.2 --dp-rpc-port 12321 --vllm-start-port 7100
    
  • 在预填充主节点上运行代理服务器。

    您可以在仓库的 examples 目录中获取代理程序:load_balance_proxy_server_example.py。

    注意:由于每个节点有 8 个 DP rank(使用 --vllm-start-port 7100 + 本地 rank 索引,占用端口 7100-7107),您需要在代理命令中为每个节点列出全部 8 个端口:

    python load_balance_proxy_server_example.py \
      --port 8000 \
      --host 192.xx.xx.1 \
      --prefiller-hosts \
        192.xx.xx.1 \
        192.xx.xx.1 \
        192.xx.xx.1 \
        192.xx.xx.1 \
        192.xx.xx.1 \
        192.xx.xx.1 \
        192.xx.xx.1 \
        192.xx.xx.1 \
      --prefiller-ports \
        7100 7101 7102 7103 7104 7105 7106 7107 \
      --decoder-hosts \
        192.xx.xx.2 \
        192.xx.xx.2 \
        192.xx.xx.2 \
        192.xx.xx.2 \
        192.xx.xx.2 \
        192.xx.xx.2 \
        192.xx.xx.2 \
        192.xx.xx.2 \
      --decoder-ports \
        7100 7101 7102 7103 7104 7105 7106 7107
    

部署验证:

在 PD 分离服务完全启动后,通过预填充主节点上的代理端口发送请求,以验证 Prefill 和 Decode 节点是否协同正常工作:

curl http://<proxy_node0_ip>:8000/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "qwen3.5",
        "messages": [
            {"role": "user", "content": "The future of AI is"}
        ],
        "max_tokens": 1024,
        "temperature": 1.0,
        "top_p": 0.95
    }'

注意:对于 Qwen3.6-27B-w8a8,将上述 model 字段更改为 "qwen3.6",并将 Prefill/Decode 节点的 --served-model-name 更改为 qwen3.6。

预期结果:代理返回 HTTP 200 OK。JSON 响应包含带有生成文本的 choices 字段,确认 Prefill 节点已成功处理提示词,Decode 节点已生成响应。

常见问题提示:如果在 PD 分离部署中遇到问题,请参阅 公共常见问题 进行排查。

6 功能验证

服务启动后,可以通过发送提示词来调用模型。支持两个 API 接口:completions 和 chat.completions。请使用您配置的 --served-model-name(Qwen3.5-27B 使用 qwen3.5,Qwen3.6-27B 使用 qwen3.6)。

Completions API:

curl http://localhost:8000/v1/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "qwen3.5",
        "prompt": "The future of AI is",
        "max_tokens": 50,
        "temperature": 0
    }'

注意:对于 Qwen3.6-27B,请在请求体中设置 "model": "qwen3.6"。

Chat Completions API:

curl http://localhost:8000/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "qwen3.5",
        "messages": [
            {"role": "user", "content": "The future of AI is"}
        ],
        "max_completion_tokens": 1024,
        "temperature": 0.7,
        "top_p": 0.95
    }'

注意:对于 Qwen3.6-27B,请在请求体中设置 "model": "qwen3.6"。

预期结果:服务返回 HTTP 200 OK。JSON 响应包含带有生成文本的 choices 字段。completions API 的示例输出(为简洁起见,内容已截断):

{
    "id": "cmpl-xxxxxxxxxxxxx",
    "object": "text_completion",
    "created": 1780971952,
    "model": "qwen3.5",
    "choices": [
        {
            "index": 0,
            "text": "The future of AI is a rapidly evolving landscape with breakthroughs in natural language understanding, multimodal reasoning, and autonomous agents. As models grow more capable and efficient...",
            "logprobs": null,
            "finish_reason": "length"
        }
    ],
    "usage": {
        "prompt_tokens": 4,
        "total_tokens": 54,
        "completion_tokens": 50
    }
}

7 精度评估

以下是两种精度评估方法。

7.1 使用 AISBench

  1. 详情请参见 使用 AISBench。

  2. 执行后,您可以获取结果。以下是 Qwen3.5-27B-w8a8 在 vllm-ascend:v0.17.0rc1 中的结果,仅供参考。Qwen3.6-27B-w8a8 的精度结果可以以相同方式获取,此处不再列出。

精度评估配置文件:

# Example configuration: benchmarks/ais_bench/benchmark/configs/models/vllm_api/vllm_api_general_chat.py
from ais_bench.benchmark.models import VLLMCustomAPIChat
from ais_bench.benchmark.utils.model_postprocessors import extract_non_reasoning_content

models = [
    dict(
        attr="service",
        type=VLLMCustomAPIChat,
        abbr="vllm-api-general-chat",
        path="your_model_path",
        model="qwen3.5",
        request_rate=0,
        retry=2,
        host_ip="127.0.0.1",
        host_port=8000,
        max_out_len=32768,
        batch_size=32,
        trust_remote_code=False,
        generation_kwargs=dict(
            temperature=1.0,
            top_p=0.95,
            top_k=20,
            min_p=0.0,
            presence_penalty=1.5,
            repetition_penalty=1.0,
            ignore_eos=False,
        ),
        pred_postprocessor=dict(type=extract_non_reasoning_content)
    )
]

对于 Qwen3.6-27B-w8a8,请将 model 更改为 qwen3.6,并将 path 更改为对应的模型权重路径。

数据集 版本 指标 模式 vllm-api-general-chat
gsm8k - accuracy gen 96.74

7.2 使用 Language Model Evaluation Harness

以 gsm8k 数据集作为示例测试数据集,在在线模式下运行 Qwen3.5-27B-w8a8 的精度评估。

  1. 关于 lm_eval 的安装,请参见 使用 lm_eval。
  2. 运行 lm_eval 执行精度评估。
# For Qwen3.5-27B-w8a8
export VLLM_USE_MODELSCOPE=True
vllm serve Eco-Tech/Qwen3.5-27B-w8a8-mtp \
    --served-model-name qwen3.5 \
    --trust-remote-code \
    --quantization ascend \
    --tensor-parallel-size 2 \
    --max-model-len 133000 \
    --max-num-seqs 32 \
    --gpu-memory-utilization 0.90 \
    --no-enable-prefix-caching

# Run lm_eval in another terminal
lm_eval \
  --model local-completions \
  --model_args model=qwen3.5,base_url=http://127.0.0.1:8000/v1/completions,tokenized_requests=False,trust_remote_code=True \
  --tasks gsm8k \
  --output_path ./

8 性能评估

8.1 使用 AISBench

详情请参见 使用 AISBench 进行性能评估。

8.2 使用 vLLM Benchmark

以运行 Qwen3.5-27B-w8a8 或 Qwen3.6-27B-w8a8 的性能评估为例。

更多详情请参见 vllm benchmark。

vllm bench 有三个子命令:

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

以 serve 为例,按如下方式运行代码。

export VLLM_USE_MODELSCOPE=True
# For Qwen3.5-27B-w8a8:
vllm bench serve --model Eco-Tech/Qwen3.5-27B-w8a8-mtp --dataset-name random --random-input 200 --num-prompts 200 --request-rate 1 --save-result --result-dir ./
# For Qwen3.6-27B-w8a8:
vllm bench serve --model Eco-Tech/Qwen3.6-27B-w8a8 --dataset-name random --random-input 200 --num-prompts 200 --request-rate 1 --save-result --result-dir ./

大约几分钟后,您可以获取性能评估结果。

9 性能调优

注意:以下配置已在特定测试环境中验证,仅供参考。最优配置取决于最大输入/输出长度、前缀缓存命中率、精度要求以及部署机器比例等因素。建议根据实际条件参考 第 9.2 节 进行调优。

并行策略:Qwen3.5-27B-w8a8 和 Qwen3.6-27B-w8a8 仅 ~30 GB,可以轻松放入单个 NPU(每个 NPU 64 GB HBM)。遵循 DP 优先 原则,在大多数场景中,TP=2 是推荐默认值,其余 NPU 应分配给 DP,用于并行处理请求批次。TP=8 仅推荐用于超长上下文(256k+)场景,此时它会将 KV 缓存分片到 8 个 NPU 上,以最大化每个 rank 可用的上下文窗口。对于 Qwen3.6-27B-w8a8,在相同的 TP/DP 布局下,您还可以将 --max-model-len 提高到 262144。

Atlas 300I DUO:目前仅支持 TP 场景。根据可用设备选择 TP=2 或 TP=4。使用 TP=4 时,--max-model-len 可支持 128k 和 256k 长序列场景;请根据需要配置 --max-num-seqs——设置过高可能导致 OOM。

950DT 产品:Qwen3.6-27B-w8a8-mxfp8 模型权重可以轻松放入单个 NPU(每个 NPU 96 GB HBM)。遵循 DP 优先 原则,在大多数场景中,TP=1 是推荐默认值,其余 NPU 应分配给 DP,用于并行处理请求批次。对于 Qwen3.6-27B-w8a8-mxfp8,在相同的 TP=1 + DP=8 布局下,--max-model-len 最高可支持 262144。

表 1:场景概览

场景 部署模式 *总 NPU 数量 权重版本 关键考量
高吞吐
(128k 上下文)
单节点(A2) 8(A2) Qwen3.5-27B-w8a8 / Qwen3.6-27B-w8a8 TP=2 + DP=4 充分利用全部 8 个 NPU 处理并行请求批次
高吞吐
(128k 上下文)
单节点(A3) 16(A3) Qwen3.5-27B-w8a8 / Qwen3.6-27B-w8a8 TP=2 + DP=8 充分利用全部 16 个 NPU 处理并行请求批次
低延迟
(128k 上下文)
单节点(A3) 16(A3) Qwen3.5-27B-w8a8 / Qwen3.6-27B-w8a8 TP=2 + DP=8 降低小交互式批次的逐层 Allreduce 开销
长上下文
(256k+ 上下文)
单节点(A3) 16(A3) Qwen3.5-27B-w8a8 / Qwen3.6-27B-w8a8 TP=8 + DP=2 将 KV 缓存分片到 8 个 NPU 上,以最大化可用上下文窗口
高吞吐
(128k 上下文)
单节点(950DT Products) 8(950DT Products) Qwen3.6-27B-w8a8-mxfp8 TP=1 + DP=8 充分利用全部 8 个 NPU 处理并行请求批次
长上下文
(256k+ 上下文)
单节点(950DT Products) 8(950DT Products) Qwen3.6-27B-w8a8-mxfp8 TP=1 + DP=8 在保持全部 8 个 NPU 忙碌的同时最大化可用上下文窗口

*Total NPUs 表示所有节点使用的 NPU 总数。1 个 Atlas 800 A3 节点 = 16 个 NPU,1 个 Atlas 800 A2 节点 = 8 个 NPU,1 个 950DT Products 节点 = 8 个 NPU。

表 2:详细节点配置

场景 配置 NPU 数量 TP DP 最大序列数 最大批处理 Token 数 最大模型长度 MTP 推测数量 异步调度
高吞吐(128k) 单节点(A2) 8 2 4 32 16384 133000 3 开启
高吞吐(128k) 单节点(A3) 16 2 8 32 16384 133000 3 开启
低延迟(128k) 单节点(A3) 16 2 8 4 4096 133000 3 开启
长上下文(256k+) 单节点(A3) 16 8 2 8 8192 262144 3 开启
高吞吐(128k) 单节点(950DT Products) 8 1 8 32 16384 133000 3 开启
长上下文(256k+) 单节点(950DT Products) 8 1 8 32 16384 262144 3 开启

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

9.2 调优指南

9.2.1 通用调优参考

请参阅 公开性能调优文档 了解调优方法。 请参阅 功能矩阵 了解详细功能说明。

10 常见问题

对于常见的环境、安装和通用参数问题,请参阅 公开常见问题。

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