后缀投机解码#
简介#
后缀解码是一种基于模式匹配的投机解码优化技术。它同时从提示词和已生成内容中检索重复序列,利用频率统计来预测最有可能的 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 pull quay.io/ascend/vllm-ascend:v0.13.0rc1
使用 Docker 运行#
容器启动命令:
# Update the vllm-ascend image
export IMAGE=quay.io/ascend/vllm-ascend:v0.13.0rc1
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。使用以下命令在容器内安装:
pip install arctic-inference
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% |