后缀投机解码¶
简介¶
后缀解码是一种基于模式匹配的投机解码优化技术。它同时从提示词和已生成内容中检索重复序列,利用频率统计来预测最有可能的 token 延续。与传统的投机解码方法不同,后缀解码完全在 CPU 上运行,无需额外的 GPU 资源或草稿模型,从而为 AI Agent 和代码生成等重复性任务带来显著的加速效果。
本文档提供了如何在 Atlas A2 硬件上部署和测试 vllm-ascend 所支持的后缀解码投机推理技术的逐步指南。配置使用单台 Atlas 800T A2 节点,以 4 卡方式部署 Qwen3-32B 模型实例。基准测试使用真实的开源数据集进行,涵盖以下类别:
| 数据集类别 | 数据集名称 |
|---|---|
| 代码生成 | HumanEval |
| 常识推理 | ARC |
| 数学推理 | gsm8k |
| 自然语言理解 | SuperGLUE_BoolQ |
| 综合考试 | AGIEval |
| 多轮对话 | ShareGPT |
本教程使用的基准测试工具是 AISBench,它支持上述所有数据集的性能测试。教程的最后一部分展示了在不同数据集和并发级别下,满足 SLO TPOT < 50ms 的条件下,启用与禁用后缀解码的性能对比。验证表明,Qwen3-32B 模型在启用后缀解码后,在各种真实数据集上的吞吐量提升了约 20% 到 80%。
下载 vllm-ascend 镜像¶
本教程使用官方镜像,版本 v0.13.0rc1。使用以下命令下载:
使用 Docker 运行¶
容器启动命令:
# Update the vllm-ascend image
export IMAGE=quay.io/ascend/vllm-ascend:v0.22.1rc1
export NAME=vllm-ascend
# Run the container using the defined variables
# This test uses four Atlas A2 NPU cards to create the container.
# Mount the hccn.conf file from the host node into the container.
docker run --rm \
--name $NAME \
--net=host \
--shm-size=1g \
--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/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
安装 arctic-inference¶
在 Ascend 上启用后缀解码投机推理之前,必须安装 Arctic Inference 插件。Arctic Inference 是 Snowflake 推出的开源插件,专门用于优化 LLM 推理速度。详细技术原理请参考以下文章:Fastest Speculative Decoding in vLLM with Arctic Inference and Arctic Training。使用以下命令在容器内安装:
vLLM 实例部署¶
使用以下命令启动容器服务实例。通过 --speculative-config 参数启用投机推理,其中 method 设置为 suffix。本次测试中,num_speculative_tokens 统一设置为 3。
# 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
# 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 /data/Qwen3-32B \
--served-model-name qwen3 \
--trust-remote-code \
--distributed-executor-backend mp \
--tensor-parallel-size 4 \
--max-model-len 5500 \
--max-num-batched-tokens 40960 \
--speculative-config '{"method": "suffix", "num_speculative_tokens": 3}' \
--gpu-memory-utilization 0.9 \
--additional-config '{"pa_shape_list":[48,64,72,80], "weight_prefetch_config":{"enable":true}}' \
--port 8011
AISbench 基准测试¶
所有开源数据集的性能均使用 AISbench 进行测试。具体说明请参考使用 AISBench 进行性能评估。
模型配置:
# "ignore_eos" must be set to "False", and "max_out_len" should be set to a large value to allow the model to output completely and naturally.
from ais_bench.benchmark.models import VLLMCustomAPIChatStream
models = [
dict(
attr="service",
type=VLLMCustomAPIChatStream,
abbr='vllm-api-stream-chat',
path="<path_to_your_model>/Qwen3-32B",
model="qwen3",
request_rate = 0,
retry = 2,
host_ip = "<your_server_ip>",
host_port = 8011,
max_out_len = 4000,
batch_size= 16,
trust_remote_code=False,
generation_kwargs = dict(
temperature = 0,
ignore_eos = False
)
)
]
性能基准测试命令:
# Example command to test gsm8k dataset performance using the first 100 prompts. Commands for other datasets are similar.
ais_bench --models vllm-api-stream-chat \
--datasets gsm8k_gen_0_shot_cot_str_perf \
--debug --summarizer default_perf --mode perf --num-prompts 100
测试结果¶
以下是本次评估中六个开源数据集的详细测试结果。与基线性能相比,启用后缀解码后,不同并发级别下的 TPOT 和吞吐量性能提升因数据集而异。各数据集启用后缀解码后的提升幅度不尽相同。以下是结果汇总:
| 数据集类别 | 典型代表 | 吞吐量提升(BS=1-10) | SLO TPOT |
|---|---|---|---|
| 高收益 | AGIEval、GSM8K | > 50% | < 50ms |
| 中低收益 | ARC、ShareGPT | 20% ~ 30% | < 50ms |
以下是原始详细测试结果:
| 并发数 | 平均输入长度 | 平均输出长度 | 请求数 | 基线 TPOT(毫秒) | 基线吞吐量(TPS) | 后缀解码 TPOT(毫秒) | 后缀解码吞吐量(TPS) | 接受率 | TPOT 提升 | TPS 提升 |
|---|---|---|---|---|---|---|---|---|---|---|
| Humaneval | ||||||||||
| 1 | 150 | 2700 | 100 | 55.1 | 18.1 | 37.9 | 26.3 | 27.0% | 45.2% | 45.1% |
| 15 | 150 | 2700 | 100 | 61.6 | 233.8 | 45.8 | 318.2 | 27.0% | 34.6% | 36.1% |
| 26 | 150 | 2700 | 100 | 64.7 | 403.8 | 50.9 | 519.2 | 27.0% | 27.2% | 28.6% |
| ARC | ||||||||||
| 1 | 76 | 960 | 100 | 52.8 | 18.9 | 39.5 | 25.4 | 23.9% | 33.7% | 34.6% |
| 8 | 76 | 960 | 100 | 59.1 | 125.4 | 47.0 | 163.1 | 23.9% | 25.7% | 30.0% |
| 15 | 76 | 960 | 100 | 59.8 | 245.8 | 48.9 | 311.7 | 23.9% | 22.3% | 26.8% |
| GSM8K | ||||||||||
| 1 | 67 | 1570 | 100 | 55.5 | 18.0 | 35.7 | 28.5 | 31.1% | 55.6% | 58.4% |
| 17 | 67 | 1570 | 100 | 61.5 | 279.8 | 45.4 | 403.0 | 31.1% | 35.6% | 44.0% |
| 26 | 67 | 1570 | 100 | 63.9 | 396.4 | 50.0 | 527.6 | 31.1% | 27.8% | 33.1% |
| ShareGPT | ||||||||||
| 1 | 666 | 231 | 327 | 54.1 | 18.3 | 39.2 | 24.1 | 23.9% | 37.9% | 31.5% |
| 8 | 666 | 231 | 327 | 58.8 | 125.0 | 46.2 | 153.2 | 23.9% | 27.1% | 22.5% |
| 14 | 666 | 231 | 327 | 61.8 | 227.0 | 49.9 | 273.9 | 23.9% | 23.8% | 20.7% |
| SuperGLUE_BoolQ | ||||||||||
| 1 | 207 | 314 | 100 | 54.1 | 18.4 | 36.1 | 26.8 | 33.4% | 49.8% | 45.6% |
| 16 | 207 | 314 | 100 | 60.0 | 229.7 | 43.5 | 303.9 | 33.4% | 38.0% | 32.3% |
| 32 | 207 | 314 | 100 | 62.7 | 396.4 | 47.8 | 507.5 | 33.4% | 31.3% | 28.0% |
| AGIEval | ||||||||||
| 1 | 735 | 1880 | 100 | 53.1 | 18.7 | 31.8 | 34.1 | 50.3% | 66.8% | 81.9% |
| 24 | 735 | 1880 | 100 | 64.0 | 381.2 | 43.3 | 629.0 | 50.3% | 47.8% | 65.0% |
| 34 | 735 | 1880 | 100 | 70.0 | 494.6 | 50.2 | 768.4 | 50.3% | 39.4% | 55.3% |