Qwen3-Dense(Qwen3-0.6B/8B/32B)#
简介#
Qwen3 是 Qwen 系列最新一代的大语言模型,提供了一套完整的稠密模型和专家混合(MoE) 模型。基于广泛的训练,Qwen3 在推理、指令遵循、智能体能力和多语言支持方面实现了突破性进展。
欢迎阅读在 vLLM-Ascend 环境中优化 Qwen 稠密模型的教程。本指南将帮助您为您的用例配置最有效的设置,并通过实际示例突出关键优化点。我们还将探讨如何调整服务参数以在各种场景下最大化吞吐性能。
本文档将展示模型的主要验证步骤,包括支持的特性、特性配置、环境准备、精度和性能评估。
Qwen3 稠密模型首次在 v0.8.4rc2 中得到支持。本示例需要版本 v0.11.0rc2。更早的版本可能缺少某些特性。
支持的特性#
请参考 支持的特性 以获取模型支持的特性矩阵。
请参考 特性指南 以获取特性的配置信息。
环境准备#
模型权重#
Qwen3-0.6B(BF16 版本): 需要 1 张 Atlas 800 A3 (64G × 2) 卡或 1 张 Atlas 800I A2 (64G × 1) 卡。下载模型权重Qwen3-1.7B(BF16 版本): 需要 1 张 Atlas 800 A3 (64G × 2) 卡或 1 张 Atlas 800I A2 (64G × 1) 卡。下载模型权重Qwen3-4B(BF16 版本): 需要 1 张 Atlas 800 A3 (64G × 2) 卡或 1 张 Atlas 800I A2 (64G × 1) 卡。下载模型权重Qwen3-8B(BF16 版本): 需要 1 张 Atlas 800 A3 (64G × 2) 卡或 1 张 Atlas 800I A2 (64G × 1) 卡。下载模型权重Qwen3-14B(BF16 版本): 需要 1 张 Atlas 800 A3 (64G × 2) 卡或 2 张 Atlas 800I A2 (64G × 1) 卡。下载模型权重Qwen3-32B(BF16 版本): 需要 2 张 Atlas 800 A3 (64G × 4) 卡或 4 张 Atlas 800I A2 (64G × 4) 卡。下载模型权重Qwen3-32B-W8A8(量化版本): 需要 2 张 Atlas 800 A3 (64G × 4) 卡或 4 张 Atlas 800I A2 (64G × 4) 卡。下载模型权重
这些是推荐的卡数,可以根据实际情况进行调整。
建议将模型权重下载到多节点的共享目录,例如 /root/.cache/
验证多节点通信(可选)#
如果您想部署多节点环境,需要根据 验证多节点通信环境 来验证多节点通信。
安装#
您可以使用我们的官方 docker 镜像来支持 Qwen3 稠密模型。目前,我们提供一体化镜像。下载镜像
Docker 拉取(通过标签)#
docker pull quay.io/ascend/vllm-ascend:v0.18.0
Docker 运行#
# Update --device according to your device (Atlas A2: /dev/davinci[0-7] Atlas A3:/dev/davinci[0-15]).
# Update the vllm-ascend image according to your environment.
# Note you should download the weight to /root/.cache in advance.
# For Atlas A2 machines:
# export IMAGE=quay.io/ascend/vllm-ascend:v0.18.0
# For Atlas A3 machines:
export IMAGE=quay.io/ascend/vllm-ascend:v0.18.0-a3
docker run --rm \
--name vllm-ascend-env \
--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
默认工作目录是 /workspace,vLLM 和 vLLM Ascend 代码放置在 /vllm-workspace 中,并以 开发模式 (pip install -e) 安装,以帮助开发者立即应用更改而无需重新安装。
在 运行 docker 容器 中,通过具体示例提供了详细说明。
此外,如果您不想使用上述 docker 镜像,也可以从源码构建所有内容:
从源码安装
vllm-ascend,请参考 安装。
如果您想部署多节点环境,需要在每个节点上设置环境。
部署#
在本节中,我们将演示在 vLLM-Ascend 中调整超参数以实现最大推理吞吐性能的最佳实践。通过定制服务级配置以适应不同的用例,您可以确保您的系统在各种场景下都能达到最佳性能。我们将指导您如何根据观察到的现象(例如 max_model_len、max_num_batched_tokens 和 cudagraph_capture_sizes)来微调超参数,以获得最佳性能。
具体示例如下:
机器环境是 Atlas 800 A3 (64G*16)
LLM 是 Qwen3-32B-W8A8
数据场景是固定长度输入 3.5K 和输出 1.5K。
并行配置要求是 DP=1&TP=4
如果机器环境是 Atlas 800I A2(64G*8),部署方法保持不变。
运行 docker 容器#
备注
vllm-ascend/Qwen3-32B-W8A8 是默认模型路径,请替换为您的实际路径。
v0.11.0rc2-a3 是镜像标签,请替换为您的实际标签。
请替换为您的实际端口:'-p 8113:8113'。
请替换为您的实际卡:'--device /dev/davinci0'。
# Update the vllm-ascend image
export IMAGE=quay.io/ascend/vllm-ascend:v0.18.0
docker run --rm \
--name vllm-ascend \
--shm-size=1g \
--privileged=true \
--device /dev/davinci0 \
--device /dev/davinci1 \
--device /dev/davinci2 \
--device /dev/davinci3 \
--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 8113:8113 \
-it $IMAGE bash
多 NPU 在线推理#
运行以下脚本以在多 NPU 上启动 vLLM 服务器。
此脚本配置为在上述特定示例场景下实现最佳性能,在两块 A3 卡上 batchsize = 72。
# set the NPU device number
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3
# Set the operator dispatch pipeline level to 1 and disable manual memory control in ACLGraph
export TASK_QUEUE_ENABLE=1
# [Optional] jemalloc
# jemalloc is for better performance, if `libjemalloc.so` is installed on your machine, you can turn it on.
# if os is Ubuntu
# export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libjemalloc.so.2:$LD_PRELOAD
# if os is openEuler
# export LD_PRELOAD=/usr/lib64/libjemalloc.so.2:$LD_PRELOAD
# Enable the AIVector core to directly schedule ROCE communication
export HCCL_OP_EXPANSION_MODE="AIV"
# Enable FlashComm_v1 optimization when tensor parallel is enabled.
export VLLM_ASCEND_ENABLE_FLASHCOMM1=1
vllm serve vllm-ascend/Qwen3-32B-W8A8 \
--served-model-name qwen3 \
--trust-remote-code \
--async-scheduling \
--quantization ascend \
--distributed-executor-backend mp \
--tensor-parallel-size 4 \
--max-model-len 5500 \
--max-num-batched-tokens 40960 \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
--additional-config '{"pa_shape_list":[48,64,72,80], "weight_prefetch_config":{"enabled":true}}' \
--port 8113 \
--block-size 128 \
--gpu-memory-utilization 0.9
备注
vllm-ascend/Qwen3-32B-W8A8 是默认模型路径,请替换为您的实际路径。
如果模型不是量化模型,请移除
--quantization ascend参数。[可选]
--additional-config '{"pa_shape_list":[48,64,72,80]}':pa_shape_list指定了您希望切换到 PA 算子的批次大小。这是一个临时的调优旋钮。目前,注意力算子调度默认使用 FIA 算子。在某些批次大小(并发)设置下,FIA 可能性能不佳。通过设置pa_shape_list,当运行时批次大小与列出的值之一匹配时,vLLM-Ascend 将用 PA 算子替换 FIA 算子以防止性能下降。未来,FIA 将针对这些场景进行优化,此参数将被移除。如果需要极致性能,可以启用 cudagraph_capture_sizes 参数,参考:关键优化点、优化亮点。以下是批次大小为 72 的示例:
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes":[1,8,24,48,60,64,72,76]}'。
服务器启动后,您可以使用输入提示词查询模型
curl http://localhost:8113/v1/chat/completions -H "Content-Type: application/json" -d '{
"model": "qwen3",
"messages": [
{"role": "user", "content": "Give me a short introduction to large language models."}
],
"temperature": 0.6,
"top_p": 0.95,
"top_k": 20,
"max_completion_tokens": 4096
}'
多 NPU 离线推理#
运行以下脚本以在多 NPU 上执行离线推理。
备注
vllm-ascend/Qwen3-32B-W8A8 是默认模型路径,请替换为您的实际路径。
如果模型不是量化模型,请移除
quantization="ascend"参数。
import gc
import torch
from vllm import LLM, SamplingParams
from vllm.distributed.parallel_state import (destroy_distributed_environment,
destroy_model_parallel)
def clean_up():
destroy_model_parallel()
destroy_distributed_environment()
gc.collect()
torch.npu.empty_cache()
prompts = [
"Hello, my name is",
"The future of AI is",
]
sampling_params = SamplingParams(temperature=0.6, top_p=0.95, top_k=40)
llm = LLM(model="vllm-ascend/Qwen3-32B-W8A8",
tensor_parallel_size=4,
trust_remote_code=True,
distributed_executor_backend="mp",
max_model_len=5500,
max_num_batched_tokens=5500,
quantization="ascend",
compilation_config={"cudagraph_mode": "FULL_DECODE_ONLY"})
outputs = llm.generate(prompts, sampling_params)
for output in outputs:
prompt = output.prompt
generated_text = output.outputs[0].text
print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")
del llm
clean_up()
精度评估#
这里是一种精度评估方法。
使用 AISBench#
详情请参阅使用 AISBench。
执行后,您将获得结果。此处展示的是
Qwen3-32B-W8A8在vllm-ascend:0.11.0rc2环境下的结果,仅供参考。
数据集 |
版本 |
指标 |
模式 |
任务名称 |
vllm-api-general-chat |
|---|---|---|---|---|---|
gsm8k |
- |
准确率 |
生成 |
gsm8k_gen_0_shot_noncot_chat_prompt |
96.44 |
math500 |
- |
准确率 |
生成 |
math500_gen_0_shot_cot_chat_prompt |
97.60 |
aime |
- |
准确率 |
生成 |
aime2024_gen_0_shot_chat_prompt |
76.67 |
性能#
使用 AISBench#
详情请参阅使用 AISBench 进行性能评估。
使用 vLLM 基准测试#
以运行 Qwen3-32B-W8A8 的性能评估为例。
更多详情请参阅 vLLM 基准测试。
vllm bench 包含三个子命令:
latency:基准测试单批次请求的延迟。serve:基准测试在线服务吞吐量。throughput:基准测试离线推理吞吐量。
以 serve 为例。按如下方式运行代码。
备注
vllm-ascend/Qwen3-32B-W8A8 是默认模型路径,请替换为您的实际路径。
vllm bench serve --model vllm-ascend/Qwen3-32B-W8A8 --served-model-name qwen3 --port 8113 --dataset-name random --random-input 200 --num-prompts 200 --request-rate 1 --save-result --result-dir ./
大约几分钟后,您将获得性能评估结果。
关键优化点#
本节将介绍能显著提升 Qwen Dense 模型性能的关键优化点。这些技术旨在提升各种场景下的吞吐量和效率。
1.Rope 优化#
Rope 优化通过修改位置编码过程来提升模型效率。具体来说,它确保 cos_sin_cache 及相关索引选择操作仅在正向传播的第一层执行。对于后续层,位置编码被直接复用,消除了冗余计算,并显著加快了解码阶段的推理速度。
此优化默认启用,无需设置任何额外的环境变量。
2.AddRMSNormQuant 融合#
AddRMSNormQuant 融合将地址感知多尺度归一化与量化操作合并,实现了更高效的内存访问和计算,从而提升了吞吐量。
此优化默认启用,无需设置任何额外的环境变量。
3.FlashComm_v1#
FlashComm_v1 通过将传统的 allreduce 集合通信分解为 reduce-scatter 和 all-gather,显著提升了大批量场景下的性能。这种分解有助于减少 RMSNorm 令牌维度的计算,从而实现更高效的处理。在量化场景中,FlashComm_v1 还通过减少比特级数据传输来降低通信开销,从而进一步最小化预填充阶段的端到端延迟。
需要注意的是,将 allreduce 通信分解为 reduce-scatter 和 all-gather 操作仅在无显著通信降级的高并发场景下有益。在其他情况下,这种分解可能导致明显的性能下降。为缓解此问题,当前实现采用基于阈值的方法,仅当每个推理调度的实际令牌数超过阈值时才启用 FlashComm_v1。这确保了该功能仅在能提升性能的场景下激活,避免了在低并发情况下可能出现的性能下降。
此优化需要设置环境变量 VLLM_ASCEND_ENABLE_FLASHCOMM1 = 1 来启用。
4.矩阵乘法和 ReduceScatter 融合#
一旦启用 FlashComm_v1,可以应用额外的优化。此优化融合了矩阵乘法和 ReduceScatter 操作,并包含分片优化。矩阵乘法计算被视为一个流水线,而 ReduceScatter 和反量化操作则在另一个独立的流水线中处理。这种方法显著减少了通信步骤,提高了计算效率,并实现了更好的资源利用,从而提升了吞吐量,尤其在大规模分布式环境中效果显著。
此优化在 FlashComm_v1 激活后会自动启用。然而,由于融合后在小并发场景下存在性能下降的问题,目前采用基于阈值的方法来缓解此问题。该优化仅在令牌数超过阈值时应用,确保在可能对性能产生负面影响的情况下不被启用。
5.权重预取#
权重预取通过在需要之前将权重预加载到缓存中来优化内存使用,从而最小化模型执行期间因内存访问造成的延迟。
在稠密模型场景中,MLP 的 gate_up_proj 和 down_proj 线性层通常表现出相对较高的 MTE 利用率。为解决此问题,我们创建了一个专门用于权重预取的独立流水线,该流水线与 MLP 之前的原始向量计算流水线(如 RMSNorm 和 SiLU)并行运行。这种方法允许权重提前预加载到 L2 缓存中,从而降低 MLP 计算期间的 MTE 利用率,并通过最小化资源争用和优化数据流,间接提升 Cube 计算效率。
此前用于启用MLP权重预取的环境变量 VLLM_ASCEND_ENABLE_PREFETCH_MLP,以及用于设置MLP gate_up_proj和down_proj权重预取大小的 VLLM_ASCEND_MLP_GATE_UP_PREFETCH_SIZE 和 VLLM_ASCEND_MLP_DOWN_PREFETCH_SIZE 已被弃用。请改用以下配置:"weight_prefetch_config": { "enabled": true, "prefetch_ratio": { "mlp": { "gate_up": 1.0, "down": 1.0}}}。详情请参阅用户指南->特性指南->权重预取指南。
6.类零消除#
此消除操作移除了Attention前向传播中与类零张量相关的不必要操作,提高了矩阵运算效率并减少了内存使用。
此优化默认启用,无需设置任何额外的环境变量。
7.全图优化#
ACLGraph提供了多项关键优化以提升模型执行效率。通过一次性重放整个模型执行图,与多次重放较小图相比,我们显著降低了调度延迟。这种方法还能稳定多设备性能,因为将模型捕获为单个静态图可以缓解跨设备的调度波动。此外,整合图捕获可以释放流,从而允许捕获更多图并优化资源使用,最终提高系统效率并减少开销。
启动服务时使用配置 compilation_config = { "cudagraph_mode": "FULL_DECODE_ONLY"}。此设置对于启用aclgraph的完全仅解码模式是必需的。
8.异步调度#
异步调度是一种用于优化推理效率的技术。它允许非阻塞的任务调度,以提高并发性和吞吐量,尤其是在处理大规模模型时。
此优化通过设置 --async-scheduling 来启用。
优化亮点#
基于前面概述的具体示例场景,本节重点介绍在实现最佳性能中起关键作用的关键调优点。通过关注对超参数和优化最具影响力的调整,我们将强调可用于最大化吞吐量、最小化延迟并确保在各种环境中高效利用资源的策略。这些见解将帮助指导您微调自己的配置,以获得最佳结果。
1.预取缓冲区大小#
设置正确的预取缓冲区大小对于优化权重加载至关重要,且此预取缓冲区的大小与向量计算可隐藏的时间直接相关。为了实现预取流与计算流近乎完美的重叠,您可以通过性能分析和观察不同缓冲区大小下的重叠程度来灵活调整缓冲区大小。
例如,在上述实际场景中,我将MLP中gate_up_proj和down_proj的预取缓冲区大小设置为18MB。这样做的原因是,在此数值下,RMSNorm和SiLU的向量计算能够有效隐藏预取流,从而加速两个线性层的Matmul计算。
2.最大批处理令牌数#
最大批处理令牌数参数决定了单批次可处理的令牌数量上限。调整此值有助于平衡吞吐量与内存使用。若设置过小,每批次处理的令牌数较少,可能降低效率,从而对端到端性能产生负面影响。反之,若设置过大,则会因内存消耗过高而增加内存溢出(OOM)错误的风险。
在上述实际场景中,我们不仅通过大量测试确定了最具性价比的数值,还考虑了启用分块预填充时解码令牌的累积问题。若该值设置过小,单个请求可能被多次分块处理,且在推理早期阶段,单个批次可能仅包含少量解码令牌,从而导致端到端吞吐量无法达到预期。
3.Cudagraph_capture_sizes#
CUDA图捕获尺寸参数控制推理过程中图捕获的粒度。调整此值决定了单次捕获的计算图范围,这对性能和内存使用均有显著影响。
若未手动指定此列表,系统将自动填充一系列均匀分布的值,这通常能保证良好性能。但若需进一步微调,手动指定数值将获得更佳效果。这是因为当批次大小介于两个尺寸之间时,框架会自动将令牌数填充至较大尺寸,这常导致实际性能偏离预期甚至下降。
因此,如上述实际场景所示,在调整基准测试请求并发度时,我们始终确保并发度实际包含在CUDA图捕获尺寸列表中。这样在解码阶段基本避免了填充操作,从而保证了实验数据的可靠性。
需特别注意,若启用FlashComm_v1,此列表中的值必须是TP尺寸的整数倍。不满足此条件的任何值都将被自动过滤。因此,建议在启用FlashComm_v1后,基于TP尺寸逐步增加并发度。