GLM-5.3-Flash¶
1 简介¶
GLM-5.3-Flash 是 GLM-5 系列中首个原生多模态模型。它基于 GLM 系列中首次结合稀疏注意力和线性注意力的混合架构构建,采用流形约束超连接(mHC),并在 30T token 的多模态预训练语料上进行训练。该模型总参数量为 320B,但仅有 18B 激活参数,在基准测试和实际工作负载上以十分之一的价格超越 GLM-5.2,同时在编码和智能体基准上接近 Claude Opus 4.8。GLM-5.3-Flash 还支持通过 reasoning_effort 参数(low、high、max)控制思考预算。
本文档介绍该模型的主要验证步骤,包括支持的特性、特性配置、环境准备、单节点部署、1P1D Prefill-Decode(PD)分离部署、多节点部署,以及精度与性能评估。
本文档基于 vLLM-Ascend v0.30.0RC1,该版本支持在 Atlas 800I A2 和 Atlas 800I A3 上部署 GLM-5.3-Flash。950DT Products 当前为实验性支持,将在后续版本中正式支持。
2 支持的特性¶
请参考支持特性列表获取该模型的支持特性矩阵。
请参考特性指南获取特性的配置方法。
GLM-5.3-Flash 目前在昇腾上仅支持 model runner V1,因此所有 Atlas 800I A3 脚本均显式设置 VLLM_USE_V2_MODEL_RUNNER=0。
3 前提条件¶
3.1 模型权重¶
GLM-5.3-Flash-w8a8-mxfp8 (950DT Products mxfp8 Quantized):需要 1 个 950DT Products(96GB × 8)节点。下载模型权重。GLM-5.3-Flash-w8a8:单节点部署需要 1 个 Atlas 800I A3(128GB × 8)节点,1P1D PD 分离部署需要 2 个节点。下载模型权重。-
GLM-5.3-Flash-w8a8:需要 2 个 Atlas 800I A2(64GB × 8)节点。下载模型权重。 -
您可以使用 msmodelslim 直接对模型进行量化。
建议将模型权重下载到多个节点的共享目录中,例如 /root/.cache/
3.2 验证多节点通信(可选)¶
如果您想部署多节点环境,需要根据验证多节点通信环境进行验证。
4 安装¶
4.1 Docker 镜像安装¶
- 您可以使用官方 Docker 镜像直接运行 GLM-5.3-Flash。
在每个节点上启动 docker 镜像。
export IMAGE=quay.io/ascend/vllm-ascend:glm-5.3-flash-a5-openeuler
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/bin/urma_admin:/usr/bin/urma_admin \
-v /lib/route.conf:/lib/route.conf \
-itd $IMAGE bash
在每个节点上启动 docker 镜像。
export IMAGE=quay.io/ascend/vllm-ascend:v0.30.0rc1-a3
export NAME=vllm-ascend
# Run the container using the defined variables
# Note: If you are running bridge network with docker, please expose available ports for multiple nodes communication in advance
docker run --rm \
--name $NAME \
--net=host \
--shm-size=100g \
--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:ro \
-v /root/.cache:/root/.cache \
-it $IMAGE bash
在每个节点上启动 docker 镜像。
export IMAGE=quay.io/ascend/vllm-ascend:v0.30.0rc1
export NAME=vllm-ascend
docker run --rm \
--name $NAME \
--net=host \
--shm-size=500g \
--privileged \
--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/Ascend/driver:/usr/local/Ascend/driver \
-v /usr/local/Ascend/firmware:/usr/local/Ascend/firmware \
-v /usr/local/sbin/npu-smi:/usr/local/sbin/npu-smi \
-v /usr/local/sbin:/usr/local/sbin \
-v /etc/hccn.conf:/etc/hccn.conf:ro \
-v /root/.cache:/root/.cache \
-it $IMAGE bash
5 在线服务部署¶
Note
请勿为 GLM-5.3-Flash 设置 enable_thinking: false / thinking: false,否则输出质量可能会下降。
5.1 单节点在线部署¶
- 量化模型
GLM-5.3-Flash-w8a8-mxfp8可部署在 1 个 950DT Products(96GB × 8)上。
运行以下脚本执行在线推理。
export VLLM_USE_V2_MODEL_RUNNER=0
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=1024
vllm serve Eco-Tech/GLM-5.3-Flash-w8a8-mxfp8 \
--host 0.0.0.0 \
--port 8000 \
--data-parallel-size 1 \
--tensor-parallel-size 8 \
--enable-expert-parallel \
--seed 1024 \
--quantization ascend \
--served-model-name glm \
--max-num-seqs 32 \
--max-model-len 132096 \
--max-num-batched-tokens 8192 \
--trust-remote-code \
--gpu-memory-utilization 0.9 \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [1,2,4,8,16,32,64,96,128]}' \
--speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp", "enforce_eager": true}'
- 量化模型
GLM-5.3-Flash-w8a8可以部署在 1 个 Atlas 800I A3(64GB × 16)上。
运行以下脚本执行在线推理。
#!/bin/sh
export VLLM_USE_V2_MODEL_RUNNER=0
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_BUFFSIZE=1024
vllm serve Eco-Tech/GLM-5.3-Flash-w8a8 \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 1048576 \
--data-parallel-size 1 \
--tensor-parallel-size 16 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name glm \
--safetensors-load-strategy prefetch \
--max-num-seqs 32 \
--max-num-batched-tokens 8192 \
--trust-remote-code \
--quantization ascend \
--kv-cache-dtype int8 \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--gpu-memory-utilization 0.92 \
--speculative-config '{"num_speculative_tokens": 5, "method": "deepseek_mtp", "enforce_eager": false}' \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
--additional-config '{"multistream_overlap_shared_expert": true}' \
--api-server-count 1
关键参数说明¶
下面仅描述该模型/场景特有的关键参数。max-model-len 和 max-num-seqs 需要根据实际使用场景进行设置。
模型特有参数:
--data-parallel-size 1:运行单个 DP rank。--tensor-parallel-size在 950DT Products上为 8,在 Atlas 800I A3 上为 16。建议使用此布局,以平衡 w8a8 权重的内存容量与计算效率。--enable-expert-parallel:GLM-5.3-Flash 采用 MoE 架构,必须启用此参数。--quantization ascend:为 w8a8 量化权重启用昇腾量化。--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}':仅在 Decode 阶段启用图捕获,通过降低算子启动开销提升 Decode 性能。--limit-mm-per-prompt '{"image":1,"video":0}':所有部署示例均设置为每个提示词最多允许 1 张图像,并禁用视频输入。--speculative-config:使用 GLM-5.3-Flash 的 DeepSeek 风格 MTP 草稿头启用多 Token 预测(MTP)推测解码。单节点示例在 950DT Products 上使用 3 个推测 Token,在 Atlas 800I A3 上使用 5 个。950DT Products 使用enforce_eager: true让 MTP 草稿模型以 eager 模式运行;Atlas 800I A3 使用enforce_eager: false启用草稿模型的图模式。v0.30.0RC1 已支持 GLM-5.3-Flash 的 MTP 草稿图执行,其他 GLM 模型的强制 eager 限制不适用于此模型。
5.2 多节点混部部署¶
- 量化模型
GLM-5.3-Flash-w8a8可以部署在 2 个 Atlas 800I A2(64GB × 8)节点上,跨两个节点使用 DP2(每个节点一个 DP rank),节点内使用 TP8。
分别在两个节点上运行以下脚本。
节点 0
# this obtained through ifconfig
# nic_name is the network interface name corresponding to local_ip of the current node
nic_name="xxxx"
local_ip="xx.xx.xx.1"
# The value of node0_ip must be consistent with the value of local_ip set in node0 (master node)
node0_ip="xx.xx.xx.1"
export VLLM_USE_V2_MODEL_RUNNER=0
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_OP_EXPANSION_MODE=AIV
export HCCL_BUFFSIZE=1024
export VLLM_RPC_TIMEOUT=3600000
export VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS=3000
export HCCL_EXEC_TIMEOUT=3600
export HCCL_CONNECT_TIMEOUT=1200
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export HCCL_IF_IP=$local_ip
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
vllm serve /path/to/GLM-5.3-Flash-w8a8 \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 133120 \
--data-parallel-size 2 \
--data-parallel-size-local 1 \
--data-parallel-start-rank 0 \
--data-parallel-address $node0_ip \
--data-parallel-rpc-port 12321 \
--tensor-parallel-size 8 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name glm \
--safetensors-load-strategy prefetch \
--max-num-seqs 32 \
--max-num-batched-tokens 8192 \
--trust-remote-code \
--quantization ascend \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--gpu-memory-utilization 0.85 \
--speculative-config '{"num_speculative_tokens":3,"method":"deepseek_mtp","enforce_eager":true}' \
--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY","cudagraph_capture_sizes":[4,8,16,32,64,96,128]}' \
--api-server-count 1
节点 1
# this obtained through ifconfig
# nic_name is the network interface name corresponding to local_ip of the current node
nic_name="xxxx"
local_ip="xx.xx.xx.2"
# The value of node0_ip must be consistent with the value of local_ip set in node0 (master node)
node0_ip="xx.xx.xx.1"
export VLLM_USE_V2_MODEL_RUNNER=0
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_OP_EXPANSION_MODE=AIV
export HCCL_BUFFSIZE=1024
export VLLM_RPC_TIMEOUT=3600000
export VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS=3000
export HCCL_EXEC_TIMEOUT=3600
export HCCL_CONNECT_TIMEOUT=1200
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export HCCL_IF_IP=$local_ip
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
vllm serve /path/to/GLM-5.3-Flash-w8a8 \
--host 0.0.0.0 \
--port 8000 \
--headless \
--max-model-len 133120 \
--data-parallel-size 2 \
--data-parallel-size-local 1 \
--data-parallel-start-rank 1 \
--data-parallel-address $node0_ip \
--data-parallel-rpc-port 12321 \
--tensor-parallel-size 8 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name glm \
--safetensors-load-strategy prefetch \
--max-num-seqs 32 \
--max-num-batched-tokens 8192 \
--trust-remote-code \
--quantization ascend \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--gpu-memory-utilization 0.85 \
--speculative-config '{"num_speculative_tokens":3,"method":"deepseek_mtp","enforce_eager":true}' \
--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY","cudagraph_capture_sizes":[4,8,16,32,64,96,128]}'
关键参数说明¶
多节点网络和数据并行配置:
HCCL_IF_IP、GLOO_SOCKET_IFNAME、TP_SOCKET_IFNAME、HCCL_SOCKET_IFNAME:用于多节点通信的网络接口配置。将nic_name设置为网络接口名称(通过ifconfig获取),并将local_ip设置为当前节点的 IP 地址。每个节点都必须正确配置这些参数,才能实现成功的多节点通信。--data-parallel-size 2 --data-parallel-size-local 1:在两个节点上运行两个 DP rank,每个节点一个 rank;每个 rank 在其节点内使用 TP8。--data-parallel-start-rank:当前节点的起始 DP rank 偏移量。节点 0 使用0,节点 1 使用1。--data-parallel-address:数据并行主节点(节点 0)的 IP 地址。必须与主节点的local_ip一致。--data-parallel-rpc-port 12321:数据并行主节点通信的 RPC 端口。所有节点必须相同。--headless:表示非主节点(在节点 1 上使用)。不要在节点 0 上使用。
5.3 1P1D PD 分离部署¶
Atlas 800I A3 和 Atlas 800I A2 部署均使用同一个 launch_online_dp.py 脚本,为每个本地 DP rank 启动一个 vLLM 进程。在按照下方各平台说明操作前,请将该脚本保存到每个 Prefill 和 Decode 节点。
5.3.1 准备 DP 启动器¶
import argparse
import multiprocessing
import subprocess
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("--template", default="./run_p.sh")
parser.add_argument("--dp-size", type=int, required=True)
parser.add_argument("--tp-size", type=int, default=1)
parser.add_argument("--dp-size-local", type=int, default=-1)
parser.add_argument("--dp-rank-start", type=int, default=0)
parser.add_argument("--dp-address", required=True)
parser.add_argument("--dp-rpc-port", default="12325")
parser.add_argument("--vllm-start-port", type=int, default=8000)
args = parser.parse_args()
if args.dp_size_local == -1:
args.dp_size_local = args.dp_size
return args
def run(args, devices, port, dp_rank):
subprocess.run(
[
"bash",
args.template,
devices,
str(port),
str(args.dp_size),
str(dp_rank),
args.dp_address,
args.dp_rpc_port,
str(args.tp_size),
],
check=True,
)
if __name__ == "__main__":
args = parse_args()
processes = []
for i in range(args.dp_size_local):
devices = ",".join(
str(device)
for device in range(i * args.tp_size, (i + 1) * args.tp_size)
)
process = multiprocessing.Process(
target=run,
args=(
args,
devices,
args.vllm_start_port + i,
args.dp_rank_start + i,
),
)
processes.append(process)
process.start()
for process in processes:
process.join()
启动器通过 $1 到 $7 向各角色脚本依次传入可见设备、引擎端口、全局 DP 大小、DP rank、DP 地址、DP RPC 端口和 TP 大小。
本示例使用两台 Atlas 800I A3 服务器。Prefill 节点运行 2 个 DP rank,每个 rank 使用 TP8(DP2/TP8);Decode 节点运行 8 个 DP rank,每个 rank 使用 TP2(DP8/TP2)。两种布局均使用各自服务器的全部 16 个逻辑设备。MooncakeConnectorV2 将 KV cache 从 Prefill 引擎传输至 Decode 引擎。
启动服务前,请将以下脚本中的 LOCAL_IP、NIC_NAME 和 MODEL_PATH 替换为部署环境的实际值。这些脚本适用于使用 HCCS 且设备 RoCE 端口关闭的 Atlas 800I A3 超节点,显式选择 hccs:device 进行设备通信;socket 接口变量仍用于选择主机网络。其他网络拓扑需要相应调整资源配置。
Atlas 800I A3 服务脚本和启动命令
启动 Prefill 节点
在 Prefill 节点上,将以下脚本保存为 run_p.sh。启动器通过位置参数传入可见设备、API 端口、DP 配置和 TP 大小。
#!/usr/bin/env bash
# Usage: bash run_p.sh <visible_devices> <http_port> <dp_size> \
# <dp_rank> <dp_address> <rpc_port> <tp_size>
# This Atlas 800I A3 supernode uses HCCS; its device RoCE ports are down.
export ASCEND_GLOBAL_RESOURCE_CONFIG='{"comm_resource_config.protocol_desc":["hccs:device"]}'
export ASCEND_LOCAL_COMM_RES='{"version":"1.2"}'
LOCAL_IP="<PREFILL_NODE_IP>"
NIC_NAME="<NETWORK_INTERFACE>"
MODEL_PATH="<YOUR_MODEL_PATH>"
export HCCL_IF_IP="$LOCAL_IP"
export GLOO_SOCKET_IFNAME="$NIC_NAME"
export TP_SOCKET_IFNAME="$NIC_NAME"
export HCCL_SOCKET_IFNAME="$NIC_NAME"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_USE_V2_MODEL_RUNNER=0
export HCCL_OP_EXPANSION_MODE=AIV
export HCCL_BUFFSIZE=1024
export ASCEND_RT_VISIBLE_DEVICES="$1"
exec vllm serve "$MODEL_PATH" \
--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" \
--enable-expert-parallel \
--seed 1024 \
--served-model-name glm \
--safetensors-load-strategy prefetch \
--max-num-seqs 64 \
--max-model-len 1048576 \
--max-num-batched-tokens 4096 \
--trust-remote-code \
--quantization ascend \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--gpu-memory-utilization 0.92 \
--tool-call-parser glm47 \
--reasoning-parser glm45 \
--enable-auto-tool-choice \
--kv-cache-dtype int8 \
--prefix-cache-retention-interval None \
--speculative-config '{"num_speculative_tokens": 5, "method": "deepseek_mtp", "enforce_eager": true}' \
--additional-config '{
"enable_flashcomm1": true,
"enable_dsa_cp": true,
"enable_prefill_mc2": true,
"enable_fused_mc2": 1,
"enable_shared_expert_dp": true,
"multistream_overlap_shared_expert": false
}' \
--kv-transfer-config \
'{"kv_connector": "MooncakeConnectorV2", "kv_role": "kv_producer", "kv_port": "36680"}'
启动 2 个 DP2/TP8 Prefill 引擎。--dp-address 使用 Prefill 节点的 IP 地址,启动器分配 API 端口 9081-9082。
python launch_online_dp.py \
--template ./run_p.sh \
--dp-size 2 \
--tp-size 8 \
--dp-address "<PREFILL_NODE_IP>" \
--vllm-start-port 9081
启动 Decode 节点
在 Decode 节点上,将以下脚本保存为 run_d.sh。Decode 为目标模型使用 FULL_DECODE_ONLY 图模式,为 MTP 草稿模型启用图模式,并启用 FlashComm1。
#!/usr/bin/env bash
# Usage is the same as run_p.sh.
# This Atlas 800I A3 supernode uses HCCS; its device RoCE ports are down.
export ASCEND_GLOBAL_RESOURCE_CONFIG='{"comm_resource_config.protocol_desc":["hccs:device"]}'
export ASCEND_LOCAL_COMM_RES='{"version":"1.2"}'
LOCAL_IP="<DECODE_NODE_IP>"
NIC_NAME="<NETWORK_INTERFACE>"
MODEL_PATH="<YOUR_MODEL_PATH>"
export HCCL_IF_IP="$LOCAL_IP"
export GLOO_SOCKET_IFNAME="$NIC_NAME"
export TP_SOCKET_IFNAME="$NIC_NAME"
export HCCL_SOCKET_IFNAME="$NIC_NAME"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_USE_V2_MODEL_RUNNER=0
export HCCL_OP_EXPANSION_MODE=AIV
export HCCL_BUFFSIZE=1024
export ASCEND_RT_VISIBLE_DEVICES="$1"
exec vllm serve "$MODEL_PATH" \
--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" \
--enable-expert-parallel \
--seed 1024 \
--served-model-name glm \
--safetensors-load-strategy prefetch \
--max-num-seqs 32 \
--max-model-len 1048576 \
--max-num-batched-tokens 192 \
--trust-remote-code \
--quantization ascend \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--gpu-memory-utilization 0.92 \
--tool-call-parser glm47 \
--reasoning-parser glm45 \
--enable-auto-tool-choice \
--kv-cache-dtype int8 \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
--speculative-config '{"num_speculative_tokens": 5, "method": "deepseek_mtp", "enforce_eager": false}' \
--additional-config '{
"multistream_overlap_shared_expert": true,
"recompute_scheduler_enable": true,
"enable_flashcomm1": true
}' \
--kv-transfer-config \
'{"kv_connector": "MooncakeConnectorV2", "kv_role": "kv_consumer", "kv_port": "36580"}'
启动 8 个 DP8/TP2 Decode 引擎。--dp-address 使用 Decode 节点的 IP 地址,启动器分配 API 端口 9900-9907。
python launch_online_dp.py \
--template ./run_d.sh \
--dp-size 8 \
--tp-size 2 \
--dp-address "<DECODE_NODE_IP>" \
--vllm-start-port 9900
部署 PD 代理
所有 Prefill 和 Decode 引擎就绪后,在 Prefill 容器中打开另一个终端,启动负载均衡代理。代理监听端口 8081,将请求分发至 Prefill 端点 9081-9082,再将 Decode 工作转发至端点 9900-9907。
#!/usr/bin/env bash
P_IP="${P_IP:-<PREFILL_NODE_IP>}"
P_N=${P_N:-2}
P_PORT0=${P_PORT0:-9081}
D_IP="${D_IP:-<DECODE_NODE_IP>}"
D_N=${D_N:-8}
D_PORT0=${D_PORT0:-9900}
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY all_proxy
python /vllm-workspace/vllm-ascend/examples/disaggregated_prefill_v1/load_balance_proxy_server_example.py \
--host 0.0.0.0 \
--port 8081 \
--prefiller-hosts $(printf "$P_IP %.0s" $(seq 1 "$P_N")) \
--prefiller-ports $(seq "$P_PORT0" $((P_PORT0 + P_N - 1))) \
--decoder-hosts $(printf "$D_IP %.0s" $(seq 1 "$D_N")) \
--decoder-ports $(seq "$D_PORT0" $((D_PORT0 + D_N - 1)))
关键参数说明
--data-parallel-size和--tensor-parallel-size分别指定 Prefill 的 DP2/TP8 和 Decode 的 DP8/TP2 布局。两种布局均使用各自 Atlas 800I A3 节点的全部 16 个逻辑设备。--data-parallel-address和--data-parallel-rpc-port协调同一角色内的 DP rank。Prefill 和 Decode 使用各自节点的 IP 地址。由于两个角色运行在不同主机上,可以复用默认 RPC 端口12325。--vllm-start-port 9081为 Prefill 分配 API 端口9081-9082,--vllm-start-port 9900为 Decode 分配端口9900-9907。代理必须能够访问所有端点。- 两个角色均使用
--max-model-len 1048576、--kv-cache-dtype int8,以及包含 5 个推测 Token 的 MTP 推测解码。MTP 草稿模型在 Prefill 上使用enforce_eager: true,在 Decode 上使用enforce_eager: false。 VLLM_USE_V2_MODEL_RUNNER=0为此配置的两个角色显式选择 model runner V1。- Prefill 使用
--max-num-seqs 64和--max-num-batched-tokens 4096,Decode 使用--max-num-seqs 32和--max-num-batched-tokens 192。请根据目标工作负载分别调整两个角色的调度限制。 - Prefill 设置
--prefix-cache-retention-interval None。部署 KV Cache 池时,请按照第 5.4 节调整前缀缓存配置。 - Decode 使用
FULL_DECODE_ONLY图模式。两个角色均显式启用 FlashComm1。 - Prefill 设置
enable_dsa_cp: true、enable_prefill_mc2: true、enable_fused_mc2: 1和enable_shared_expert_dp: true,同时设置multistream_overlap_shared_expert: false。Decode 设置multistream_overlap_shared_expert: true和recompute_scheduler_enable: true。 - Prefill 和 Decode 均使用
--limit-mm-per-prompt '{"image":1,"video":0}',每个提示词最多允许 1 张图像,并禁用视频输入。 MooncakeConnectorV2在两个角色之间传输 KV cache。Prefill 的kv_role必须为kv_producer,Decode 必须为kv_consumer。各角色的 KV 端口必须在各自主机上可用。ASCEND_GLOBAL_RESOURCE_CONFIG选择hccs:device,ASCEND_LOCAL_COMM_RES为该 HCCS 超节点设置资源配置版本1.2。HCCL_IF_IP和所有 socket 接口变量必须选择所配置节点 IP 所在的主机网络。主机防火墙必须允许 DP RPC、引擎、Mooncake 和代理端口。
本示例使用四台 Atlas 800I A2(64GB × 8)服务器:两个 Prefill 节点各运行 1 个使用 TP8 的 DP rank(全局为 DP2/TP8),两个 Decode 节点各运行 4 个使用 TP2 的 DP rank(全局为 DP8/TP2)。每个 Prefill rank 使用 8 个设备,每个 Decode rank 使用 2 个设备,各服务器上的本地 rank 合计使用全部 8 个设备。MooncakeConnectorV2 将 KV cache 从 Prefill 引擎传输至 Decode 引擎。拓扑中两个 Prefill 节点分别命名为 P0/P1,两个 Decode 节点分别命名为 D0/D1。P0 提供 Prefill API 端点,P1 以 headless 模式运行。代理访问两个 Decode 节点上的 API 端点。
第 5.2.1 节中的共享启动器 launch_online_dp.py 用于在全部四个节点上启动引擎。请将以下通用服务模板和各节点的包装脚本分别保存到对应节点,并替换所有 IP、网卡名称和模型路径占位符。
通用 Prefill 模板
将以下脚本保存为 P0 和 P1 上的 run_p.sh。下方的节点包装脚本提供 LOCAL_IP 及 API/headless 角色。
#!/usr/bin/env bash
# Usage: bash run_p.sh <visible_devices> <http_port> <dp_size> \
# <dp_rank> <dp_address> <rpc_port> <tp_size>
: "${LOCAL_IP:?Set LOCAL_IP in the P0 or P1 wrapper}"
: "${NIC_NAME:?Set NIC_NAME in the P0 or P1 wrapper}"
: "${MODEL_PATH:?Set MODEL_PATH in the P0 or P1 wrapper}"
export HCCL_IF_IP="$LOCAL_IP"
export GLOO_SOCKET_IFNAME="$NIC_NAME"
export TP_SOCKET_IFNAME="$NIC_NAME"
export HCCL_SOCKET_IFNAME="$NIC_NAME"
export VLLM_HOST_IP="$LOCAL_IP"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_USE_V2_MODEL_RUNNER=0
export HCCL_OP_EXPANSION_MODE=AIV
export HCCL_BUFFSIZE=1024
export VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS=3000
export HCCL_EXEC_TIMEOUT=3600
export HCCL_CONNECT_TIMEOUT=1200
export VLLM_RPC_TIMEOUT=3600000
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export ASCEND_RT_VISIBLE_DEVICES="$1"
exec vllm serve "$MODEL_PATH" \
--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" \
--enable-expert-parallel \
--enable-chunked-prefill \
--enable-prefix-caching \
--seed 1024 \
--served-model-name glm \
--safetensors-load-strategy prefetch \
--max-model-len 200000 \
--max-num-seqs 64 \
--max-num-batched-tokens 8192 \
--trust-remote-code \
--quantization ascend \
--gpu-memory-utilization 0.92 \
--async-scheduling \
--enforce-eager \
--tool-call-parser glm47 \
--reasoning-parser glm45 \
--enable-auto-tool-choice \
--speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp", "enforce_eager": true}' \
${SERVER_ROLE_ARGS:-} \
--kv-transfer-config '{
"kv_connector": "MooncakeConnectorV2",
"kv_role": "kv_producer",
"kv_port": "30000",
"kv_connector_extra_config": {
"use_ascend_direct": true,
"prefill": {"dp_size": 2, "tp_size": 8},
"decode": {"dp_size": 8, "tp_size": 2}
}
}'
P0 和 P1 包装脚本
将以下 run_p0.sh 保存到 P0。P0 提供 Prefill API 端点。
#!/usr/bin/env bash
export LOCAL_IP="<PREFILL_NODE0_IP>"
export NIC_NAME="<PREFILL_NODE0_NIC>"
export MODEL_PATH="<YOUR_MODEL_PATH>"
export SERVER_ROLE_ARGS="--api-server-count 1"
exec bash ./run_p.sh "$@"
将以下 run_p1.sh 保存到 P1。P1 是以 headless 模式运行的 Prefill rank。
#!/usr/bin/env bash
export LOCAL_IP="<PREFILL_NODE1_IP>"
export NIC_NAME="<PREFILL_NODE1_NIC>"
export MODEL_PATH="<YOUR_MODEL_PATH>"
export SERVER_ROLE_ARGS="--headless"
exec bash ./run_p.sh "$@"
使用共享启动器启动两个 Prefill rank:
# P0
python launch_online_dp.py \
--template ./run_p0.sh \
--dp-size 2 \
--tp-size 8 \
--dp-size-local 1 \
--dp-rank-start 0 \
--dp-address "<PREFILL_NODE0_IP>" \
--dp-rpc-port 12321 \
--vllm-start-port 9081
# P1
python launch_online_dp.py \
--template ./run_p1.sh \
--dp-size 2 \
--tp-size 8 \
--dp-size-local 1 \
--dp-rank-start 1 \
--dp-address "<PREFILL_NODE0_IP>" \
--dp-rpc-port 12321 \
--vllm-start-port 9082
通用 Decode 模板
将以下 run_d.sh 保存到 D0 和 D1。Decode 为目标模型使用 FULL_DECODE_ONLY 图模式,并保持 FlashComm1 禁用。下方的节点包装脚本提供 LOCAL_IP。
#!/usr/bin/env bash
# Usage: bash run_d.sh <visible_devices> <http_port> <dp_size> \
# <dp_rank> <dp_address> <rpc_port> <tp_size>
: "${LOCAL_IP:?Set LOCAL_IP in the D0 or D1 wrapper}"
: "${NIC_NAME:?Set NIC_NAME in the D0 or D1 wrapper}"
: "${MODEL_PATH:?Set MODEL_PATH in the D0 or D1 wrapper}"
export HCCL_IF_IP="$LOCAL_IP"
export GLOO_SOCKET_IFNAME="$NIC_NAME"
export TP_SOCKET_IFNAME="$NIC_NAME"
export HCCL_SOCKET_IFNAME="$NIC_NAME"
export VLLM_HOST_IP="$LOCAL_IP"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True,pin_memory_expandable_segments:True
export VLLM_USE_V2_MODEL_RUNNER=0
export HCCL_OP_EXPANSION_MODE=AIV
export HCCL_BUFFSIZE=1024
export VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS=3000
export HCCL_EXEC_TIMEOUT=3600
export HCCL_CONNECT_TIMEOUT=1200
export VLLM_RPC_TIMEOUT=3600000
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
# Reserve disjoint HCCL port ranges per DP rank so multiple engines on
# one node never share host/NPU socket ports.
export HCCL_HOST_SOCKET_PORT_RANGE="$((60000 + $4 * 100))-$((60099 + $4 * 100))"
export HCCL_NPU_SOCKET_PORT_RANGE="$((60000 + $4 * 100))-$((60099 + $4 * 100))"
export ASCEND_RT_VISIBLE_DEVICES="$1"
exec vllm serve "$MODEL_PATH" \
--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" \
--enable-expert-parallel \
--enable-chunked-prefill \
--enable-prefix-caching \
--seed 1024 \
--served-model-name glm \
--safetensors-load-strategy prefetch \
--max-model-len 200000 \
--max-num-seqs 32 \
--max-num-batched-tokens 1024 \
--trust-remote-code \
--quantization ascend \
--gpu-memory-utilization 0.85 \
--skip-mm-profiling \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--async-scheduling \
--tool-call-parser glm47 \
--reasoning-parser glm45 \
--enable-auto-tool-choice \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
--speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp", "enforce_eager": true}' \
--kv-transfer-config '{
"kv_connector": "MooncakeConnectorV2",
"kv_role": "kv_consumer",
"kv_port": "30100",
"kv_connector_extra_config": {
"use_ascend_direct": true,
"prefill": {"dp_size": 2, "tp_size": 8},
"decode": {"dp_size": 8, "tp_size": 2}
}
}'
D0 和 D1 包装脚本
将以下 run_d0.sh 保存到 D0:
#!/usr/bin/env bash
export LOCAL_IP="<DECODE_NODE0_IP>"
export NIC_NAME="<DECODE_NODE0_NIC>"
export MODEL_PATH="<YOUR_MODEL_PATH>"
exec bash ./run_d.sh "$@"
将以下 run_d1.sh 保存到 D1:
#!/usr/bin/env bash
export LOCAL_IP="<DECODE_NODE1_IP>"
export NIC_NAME="<DECODE_NODE1_NIC>"
export MODEL_PATH="<YOUR_MODEL_PATH>"
exec bash ./run_d.sh "$@"
在每个 Decode 节点上启动 4 个 DP8/TP2 引擎。D0 的 --dp-rank-start 为 0,D1 为 4。两个节点的 --dp-address 均为 D0 的 IP 地址,启动器为每个节点分配 API 端口 9900-9903。
# D0
python launch_online_dp.py \
--template ./run_d0.sh \
--dp-size 8 \
--tp-size 2 \
--dp-size-local 4 \
--dp-rank-start 0 \
--dp-address "<DECODE_NODE0_IP>" \
--vllm-start-port 9900
# D1
python launch_online_dp.py \
--template ./run_d1.sh \
--dp-size 8 \
--tp-size 2 \
--dp-size-local 4 \
--dp-rank-start 4 \
--dp-address "<DECODE_NODE0_IP>" \
--vllm-start-port 9900
启动顺序
按以下顺序启动服务:各组的第一个节点、其余节点、代理。
- 完成全部四个节点的容器及多节点通信检查。
- 使用上方的启动器命令启动 P0(
--dp-rank-start 0)。P0 提供 Prefill API 端点,并作为 Prefill DP 主节点。 - 使用对应的启动器命令启动 D0(
--dp-rank-start 0)。D0 作为 Decode DP 主节点,并提供 4 个 API 端点。 - 启动 P0 和 D0 后,立即使用各自的命令启动 P1 和 D1(
--dp-rank-start 1和--dp-rank-start 4)。每个 DP 组在其全部 rank 启动后完成初始化。 - 全部 10 个引擎就绪后,使用
curl http://127.0.0.1:<port>/v1/models验证 P0、D0 和 D1 上的 API 端点,并检查 headless 节点 P1 的初始化日志。启动代理,然后向<PREFILL_NODE0_IP>:8081发送请求。
部署 PD 代理
在任一 Prefill 容器中打开另一个终端,启动负载均衡代理。代理监听端口 8081,将 Prefill 请求发送至 P0 API 端点,并将 Decode 工作转发至 8 个 Decode 端点。
#!/usr/bin/env bash
P0_IP="${P0_IP:-<PREFILL_NODE0_IP>}"
D0_IP="${D0_IP:-<DECODE_NODE0_IP>}"
D1_IP="${D1_IP:-<DECODE_NODE1_IP>}"
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY all_proxy
python /vllm-workspace/vllm-ascend/examples/disaggregated_prefill_v1/load_balance_proxy_server_example.py \
--host 0.0.0.0 \
--port 8081 \
--prefiller-hosts "$P0_IP" \
--prefiller-ports 9081 \
--decoder-hosts "$D0_IP" "$D0_IP" "$D0_IP" "$D0_IP" "$D1_IP" "$D1_IP" "$D1_IP" "$D1_IP" \
--decoder-ports 9900 9901 9902 9903 9900 9901 9902 9903
与 Atlas 800I A3 布局相比的关键参数差异
- Atlas 800I A2 使用与 Atlas 800I A3 相同的全局 Prefill DP2/TP8 和 Decode DP8/TP2 配置,但每个角色分布在两个各有 8 个设备的节点上。Atlas 800I A3 的每个角色运行在一个具有 16 个逻辑设备的节点上。
- P0 和 P1 使用共享启动器,每个节点运行 1 个本地 DP rank。P0 通过
--api-server-count 1提供 Prefill API;P1 以 headless 模式运行。D0 和 D1 通过各自的节点包装脚本,各运行 4 个提供 API 服务的 DP8/TP2 引擎。 kv_connector_extra_config启用use_ascend_direct,直接在 NPU 之间传输 KV,并声明实际的 Prefill 和 Decode{dp_size, tp_size}拓扑。声明的值必须与实际部署一致。- Prefill 使用
--max-num-seqs 64、--max-num-batched-tokens 8192和--enforce-eager;Decode 使用--max-num-seqs 32、--max-num-batched-tokens 1024和FULL_DECODE_ONLY图模式。两个角色均使用--async-scheduling。 - 两个角色均通过
VLLM_USE_V2_MODEL_RUNNER=0使用 model runner V1,与本指南其他标签页一致。VLLM_HOST_IP指定其他引擎在 KV 传输时用于访问本引擎的 IP 地址。 - Atlas 800I A2 上的 MTP 推测解码使用 3 个推测 Token。
enforce_eager: true使 MTP 草稿模型使用 eager 模式。 - Decode 上的
HCCL_HOST_SOCKET_PORT_RANGE和HCCL_NPU_SOCKET_PORT_RANGE为每个 DP rank 预留互不重叠的 100 个端口(起始端口为60000 + rank * 100)。当多个引擎共用一个节点时,这些端口范围可避免 HCCL 主机侧 socket 在不同 rank 之间意外共用端口,导致引擎启动阻塞。 - 其余超时和运行时变量(
VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS、HCCL_EXEC_TIMEOUT、HCCL_CONNECT_TIMEOUT、VLLM_RPC_TIMEOUT、OMP_PROC_BIND、OMP_NUM_THREADS)是针对该模型规模验证过的 Atlas 800I A2 启动默认值。除非环境要求其他值,否则请保持这些设置。 HCCL_IF_IP和所有 socket 接口变量必须选择所配置节点 IP 使用的服务网络。主机防火墙必须允许 DP RPC、引擎、Mooncake 和代理端口。
5.4 使用 KV Cache 池的 Prefill-Decode 分离部署¶
本节在 Atlas 800I A3 上使用 Memcache 后端,在 Atlas 800I A2 上使用 Mooncake 后端。请选择与第 5.3 节中的 PD 拓扑对应的平台说明。两个平台均使用 MultiConnector 组合以下两个连接器:
MooncakeConnectorV2继续将 KV cache 从 Prefill 传输至 Decode。AscendStoreConnector支持 Prefill 在 KV Cache 池中查询、加载和保存缓存前缀,减少重复的 Prefill 计算。
有关后端安装、硬件依赖、内存大小、缓存淘汰和租户选项,请参阅 KV Cache 池部署指南。
复用第 5.3 节中的 Atlas 800I A3 Prefill DP2/TP8 和 Decode DP8/TP2 拓扑、启动器及代理端点映射。
准备 Memcache 后端
请按照场景 2:Memcache 后端完成前置检查和内存大小配置。Atlas 800I A3 HCCS 配置使用 device_sdma,需要灵衢计算网络 1.5 或更高版本。还需检查指南中HDK 和 CANN 版本兼容性参考列出的 HDK 和 CANN 要求。在 Prefill 和 Decode 两个节点上启动 Atlas 800I A3 容器时,必须在第 4.1 节的 Docker 启动命令中配置以下只读挂载:
第 4.1 节的 Docker 镜像已经包含 memfabric-hybrid 和 memcache-hybrid。在每个容器中定位已安装的 Memcache 包:
pip show 输出中的 Location 字段对应以下命令中的 <PYTHON_SITE_PACKAGES>。请将 <CONFIG_DIRECTORY> 替换为各节点上存放配置文件的绝对路径。
本示例在 Prefill 和 Decode 两个节点的 DDR 内存中存储池化 KV cache。Memcache LocalService 在各个 vLLM worker 内部初始化,每个 worker 向池中贡献 20GB DDR 内存。Decode 通过 MooncakeConnectorV2 接收 KV cache。
在 Prefill 节点上创建 mmc-meta.conf:
ock.mmc.meta_service_url = tcp://<PREFILL_NODE_IP>:5000
ock.mmc.meta_service.config_store_url = tcp://<PREFILL_NODE_IP>:6000
ock.mmc.meta_service.metrics_url = http://<PREFILL_NODE_IP>:8000
ock.mmc.log_level = info
在 Prefill 和 Decode 两个节点上创建以下 mmc-local.conf:
ock.mmc.meta_service_url = tcp://<PREFILL_NODE_IP>:5000
ock.mmc.local_service.config_store_url = tcp://<PREFILL_NODE_IP>:6000
ock.mmc.log_level = info
ock.mmc.local_service.world_size = 256
ock.mmc.local_service.protocol = device_sdma
ock.mmc.local_service.dram.size = 20GB
ock.mmc.local_service.max.dram.size = 1024GB
ock.mmc.local_service.storage.enabled = false
dram.size 指定为每个 worker 分配的 DDR 容量。Prefill(DP2/TP8)和 Decode(DP8/TP2)各启动 16 个 worker。每个 worker 分配 20GB 时,每个节点贡献 320GB,DDR 池总容量为 640GB。请为操作系统和 vLLM 预留足够的 DDR 内存。使用 device_sdma 时,每个非零容量值均需按 1GB 对齐。
world_size 是 Memcache 支持的最大 LocalService 数量。所有 worker 的配置必须一致,且足以容纳本部署中的 32 个 worker。
添加池化环境变量
在 run_p.sh 和 run_d.sh 中,保留第 5.3 节的环境变量,并在 exec vllm serve 前添加以下导出语句:
MEMCACHE_PACKAGE_DIR="<PYTHON_SITE_PACKAGES>/memcache_hybrid"
PYTHON_LIB_DIR="$(python -c 'import sysconfig; print(sysconfig.get_config_var("LIBDIR"))')"
export PYTHONHASHSEED=0
export MMC_LOCAL_CONFIG_PATH="<CONFIG_DIRECTORY>/mmc-local.conf"
export LD_LIBRARY_PATH="${MEMCACHE_PACKAGE_DIR}/lib:${PYTHON_LIB_DIR}:${LD_LIBRARY_PATH:-}"
# Atlas 800I A3 HCCS fabric-memory pooling.
export ACL_OP_INIT_MODE=1
export ASCEND_ENABLE_USE_FABRIC_MEM=1
两个节点须使用相同的 PYTHONHASHSEED 和 Memcache 服务端点。请保留第 5.3 节的 HCCS 通信设置,包括 ASCEND_GLOBAL_RESOURCE_CONFIG 和 ASCEND_LOCAL_COMM_RES。
更新 Prefill 和 Decode 连接器
部署 Atlas 800I A3 KV Cache 池时,请在第 5.3 节的 run_p.sh 和 run_d.sh 中添加 --enable-prefix-caching,并保持分块预填充启用(模型默认行为)。GLM-5.3-Flash 包含线性注意力状态,AscendStoreConnector 要求 mamba_cache_mode=align;启用前缀缓存后,模型配置会选择此模式。此配置需要保持混合 KV cache 管理器启用,并禁用 use_layerwise。
将 run_p.sh 最后的 --kv-transfer-config 参数替换为以下片段。除上述前缀缓存调整外,请保留第 5.3 节中的其他 Atlas 800I A3 Prefill 参数,包括 --max-num-seqs 64。
--kv-transfer-config \
'{
"kv_connector": "MultiConnector",
"kv_role": "kv_producer",
"engine_id": "glm53-flash-prefill-dp'"$4"'",
"kv_connector_extra_config": {
"connectors": [
{
"kv_connector": "MooncakeConnectorV2",
"kv_role": "kv_producer",
"kv_port": "36680"
},
{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_producer",
"kv_connector_extra_config": {
"backend": "memcache",
"memcache_dp_init_barrier": true,
"use_layerwise": false,
"lookup_rpc_port": '"$((37000 + $4))"'
}
}
]
}
}'
将 run_d.sh 最后的 --kv-transfer-config 参数替换为以下片段。除上述前缀缓存调整外,请保留第 5.3 节中的其他 Atlas 800I A3 Decode 参数,包括 FULL_DECODE_ONLY 图模式和 MTP 配置。
--kv-transfer-config \
'{
"kv_connector": "MultiConnector",
"kv_role": "kv_consumer",
"engine_id": "glm53-flash-decode-dp'"$4"'",
"kv_connector_extra_config": {
"connectors": [
{
"kv_connector": "MooncakeConnectorV2",
"kv_role": "kv_consumer",
"kv_port": "36580"
},
{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_consumer",
"kv_connector_extra_config": {
"backend": "memcache",
"memcache_dp_init_barrier": true,
"use_layerwise": false,
"consumer_is_to_load": false,
"consumer_is_to_put": false,
"lookup_rpc_port": '"$((37100 + $4))"'
}
}
]
}
}'
$4 是 launch_online_dp.py 传入的 DP rank。每个引擎必须具有唯一的 engine_id 和 lookup_rpc_port;子连接器继承外层的 engine_id。Prefill 的查询端口为 37000-37001,Decode 为 37100-37107。请保留第 5.3 节中各角色的 Mooncake KV 基础端口,其 worker 和调度器会根据拓扑计算各自的端口。
每个 DP 组的所有 rank 均须将 memcache_dp_init_barrier 设置为 true。它在 Memcache 初始化后、NPU 图捕获前同步 worker。请如上所示,将该参数设置在 AscendStoreConnector 子连接器中。
启动服务
按以下顺序启动服务:Memcache MetaService、Decode、Prefill、代理。每个 vLLM worker 会在启动期间初始化自己的 Memcache LocalService。
- 在 Prefill 容器中的独立终端启动 MetaService。确保两个节点均可访问端口
5000和6000,且指标端口8000可用。
MEMCACHE_PACKAGE_DIR="<PYTHON_SITE_PACKAGES>/memcache_hybrid"
PYTHON_LIB_DIR="$(python -c 'import sysconfig; print(sysconfig.get_config_var("LIBDIR"))')"
export LD_LIBRARY_PATH="${MEMCACHE_PACKAGE_DIR}/lib:${PYTHON_LIB_DIR}:${LD_LIBRARY_PATH:-}"
export MMC_META_CONFIG_PATH="<CONFIG_DIRECTORY>/mmc-meta.conf"
python -c "from memcache_hybrid import MetaService; MetaService.main()"
- 使用第 5.3 节中的 Atlas 800I A3 启动器命令启动 Decode,等待端口
9900-9907上的全部 8 个 Decode 引擎就绪,且其 Memcache LocalService 已预留配置的 DDR 池内存。 - 使用第 5.3 节中的 Atlas 800I A3 启动器命令启动 Prefill,等待端口
9081-9082上的两个 Prefill 引擎就绪,且其 Memcache LocalService 已预留配置的 DDR 池内存。 - 启动第 5.3 节中的 Atlas 800I A3 代理,使用第 6 节的示例向
<PREFILL_NODE_IP>:8081发送推理请求。
验证 KV Cache 复用
通过代理发送长度超过一个缓存块的提示词以预热缓存池,然后重复发送具有相同前缀的请求。检查 Prefill 输出,确认缓存池保存、查询、加载和缓存命中成功;检查 Decode 输出,确认 P→D 传输成功。
代理在两个 Prefill 引擎之间分发请求。重复请求也可能命中某个引擎的本地前缀缓存,因此需要在另一个 Prefill rank 上确认缓存池加载或命中信息,以验证共享池复用。只有完整且可缓存的块会被复用,末尾不完整的块仍可能需要计算。
复用第 5.3 节中的 launch_online_dp.py 启动器、P0/P1 和 D0/D1 脚本、Prefill DP2/TP8 和 Decode DP8/TP2 拓扑,以及代理配置。Atlas 800I A2 节点不具备 Atlas 800I A3 HCCS 网络,缓存池通过 Atlas 800I A2 RoCE 网络运行,使用 P2PHANDSHAKE 元数据服务器和 ascend 协议,不适用 Atlas 800I A3 的 fabric 内存环境变量。
有关后端安装、内存大小、缓存淘汰和租户选项,请参阅 KV Cache 池部署指南。
准备 Mooncake 配置
第 4.1 节中的 Atlas 800I A2 Docker 命令已挂载 /etc/hccn.conf。请按照 KV Cache 池部署指南安装 Mooncake 后端,然后在两个 Prefill 节点上创建以下 mooncake.json。Mooncake Master 运行在第一个 Prefill 容器中,地址为 <PREFILL_NODE0_IP>:50088。
{
"metadata_server": "P2PHANDSHAKE",
"protocol": "ascend",
"device_name": "",
"master_server_address": "<PREFILL_NODE0_IP>:50088",
"global_segment_size": "8GB",
"preferred_segment": true,
"prefer_alloc_in_same_node": true,
"enable_ssd_offload": false,
"tenant_id": "default"
}
两个 Decode 节点使用相同的 JSON 配置,但将 global_segment_size 设置为 0。全部四个节点须使用相同的 tenant_id。global_segment_size 按 worker 注册:DP2/TP8 分布在两个 Prefill 节点上,每个节点启动 8 个 worker。验证过的示例为每个 worker 分配 8GB,池总容量为 128GB。请根据可用主机内存调整每个 worker 的容量,并保持每个非零段大小按 1GB 对齐。Decode 的 mooncake.json 中应保持 global_segment_size 为 0。
添加池化环境变量
在 run_p.sh 和 run_d.sh 中,保留第 5.3 节的环境变量,并在 exec vllm serve 前添加以下导出语句。请将 <CONFIG_DIRECTORY> 替换为该节点上存放 mooncake.json 的绝对路径。
所有节点必须使用相同的 PYTHONHASHSEED。不要添加 Atlas 800I A3 的 ASCEND_ENABLE_USE_FABRIC_MEM 导出语句,它仅适用于 Atlas 800I A3 HCCS 网络。KV Cache 池部署指南的通用 Atlas 800I A2 配置还建议使用大页和 HCCL_INTRA_ROCE_ENABLE;使用 P2PHANDSHAKE 元数据服务器和 ascend 协议时不需要这些设置,验证过的配置也未设置它们。
更新 Prefill 和 Decode 连接器
保持前缀缓存和分块预填充启用。此模型的 use_layerwise 必须保持为 false:GLM-5.3-Flash 的混合 KV cache 包含不可进行前缀缓存的组,而逐层缓存池传输要求所有组均可缓存,因此缓存池按整段存储和加载。也无需手动设置 --mamba-cache-mode 参数:连接器列表包含 AscendStoreConnector 时,引擎会自动将 mamba 缓存模式切换为 align。
将 run_p.sh 最后的 --kv-transfer-config 参数替换为以下片段。请保留第 5.3 节中的其他 Prefill 参数,包括 --max-num-seqs 64。
--kv-transfer-config \
'{
"kv_connector": "MultiConnector",
"kv_role": "kv_producer",
"engine_id": "glm53-flash-prefill-dp'"$4"'",
"kv_connector_extra_config": {
"connectors": [
{
"kv_connector": "MooncakeConnectorV2",
"kv_role": "kv_producer",
"kv_port": "30000",
"kv_connector_extra_config": {
"use_ascend_direct": true,
"prefill": {"dp_size": 2, "tp_size": 8},
"decode": {"dp_size": 8, "tp_size": 2}
}
},
{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_producer",
"kv_connector_extra_config": {
"backend": "mooncake",
"use_layerwise": false,
"lookup_rpc_port": '"$((37000 + $4))"'
}
}
]
}
}'
将 run_d.sh 最后的 --kv-transfer-config 参数替换为以下片段。请保留第 5.3 节中的其他 Decode 参数,包括 FULL_DECODE_ONLY 图模式和 MTP 配置。
--kv-transfer-config \
'{
"kv_connector": "MultiConnector",
"kv_role": "kv_consumer",
"engine_id": "glm53-flash-decode-dp'"$4"'",
"kv_connector_extra_config": {
"connectors": [
{
"kv_connector": "MooncakeConnectorV2",
"kv_role": "kv_consumer",
"kv_port": "30100",
"kv_connector_extra_config": {
"use_ascend_direct": true,
"prefill": {"dp_size": 2, "tp_size": 8},
"decode": {"dp_size": 8, "tp_size": 2}
}
},
{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_consumer",
"kv_connector_extra_config": {
"backend": "mooncake",
"use_layerwise": false,
"consumer_is_to_load": false,
"consumer_is_to_put": false,
"lookup_rpc_port": '"$((37100 + $4))"'
}
}
]
}
}'
两个角色模板均使用启动器传入的 DP rank 参数 $4 生成 engine_id 后缀和查询端口。每个引擎必须具有唯一的 engine_id 和 lookup_rpc_port;子连接器继承外层的 engine_id。Prefill 的查询端口为 37000-37001,Decode 为 37100-37107。MooncakeConnectorV2 片段中声明的 prefill 和 decode 拓扑必须与实际部署一致。
启动服务
按以下顺序启动服务:Mooncake Master → Decode → Prefill → 代理。
- 在第一个 Prefill 容器中的独立终端启动 Mooncake Master,确保全部四个节点均可访问端口
50088。
mooncake_master \
--port 50088 \
--eviction_high_watermark_ratio 0.9 \
--eviction_ratio 0.1 \
--default_kv_lease_ttl 11000 \
--enable_offload=false \
--client_ttl=120
- 使用第 5.3 节中的启动器命令启动 D0 和 D1(
--dp-rank-start 0和4;每个节点在端口9900-9903上运行 4 个引擎),等待全部 8 个 Decode 引擎均可响应curl /v1/models。 - 使用第 5.3 节中的启动器命令启动 P0 和 P1(
--dp-rank-start 0和1;P0 在端口9081上提供 API 端点,P1 以 headless 模式运行),等待 P0 的 API 端点就绪,且 P1 日志确认初始化成功。 - 启动第 5.3 节中的 Atlas 800I A2 代理,使用第 6 节的示例向
<PREFILL_NODE0_IP>:8081发送推理请求。
验证 KV Cache 复用
按照 Atlas 800I A3 小节中的步骤验证 KV Cache 复用。代理向 P0 API 发送请求,而 DP 组使用两个 Prefill rank。重复请求可能命中本地前缀缓存,因此需要在另一个 Prefill rank 上确认缓存池加载或命中信息,以验证共享池复用。
6 功能验证¶
所选部署就绪后,请查询对应的服务端点。1P1D PD 部署使用 Prefill 节点 IP 和代理端口 8081;单节点或 Atlas 800I A2 混部部署使用其 vLLM 服务提供的 API 端点。
curl http://<service_ip>:<service_port>/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "glm",
"prompt": "The future of AI is",
"max_tokens": 50
}'
预期结果: 此请求的预期结果是一个 JSON 负载,其中包含模型以 text_completion 格式生成的文本。
{
"id": "cmpl-123abc",
"object": "text_completion",
"created": 1725444000,
"model": "glm",
"choices": [
{
"text": " incredibly promising, with rapid advancements in machine learning and autonomous systems.",
"index": 0,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 5,
"completion_tokens": 15,
"total_tokens": 20
}
}
7 精度评估¶
7.1 使用 AISBench¶
有关详细说明,请参阅使用 AISBench 进行精度评估。
7.2 PD 分离精度结果¶
以下精度结果使用第 5.3 节中的 Atlas 800I A3 PD 配置测得,其中 Prefill 节点采用 DP2/TP8,Decode 节点采用 DP8/TP2。评估请求通过 PD 代理发送。下表分别列出各数据集使用的生成参数。
| 数据集 | 硬件 | 分数 | generation_kwargs |
|---|---|---|---|
| GPQA | Atlas 800I A3 | 89.9 | temperature=1.0, top_p=0.95, max_tokens=131072 |
| MMMU-PRO | Atlas 800I A3 | 78.4 | temperature=1.0, top_p=0.95, max_tokens=98304 |
8 性能评估¶
8.1 使用 AISBench¶
有关详细信息,请参阅 使用 AISBench 进行性能评估。
8.2 使用 vLLM Benchmark¶
有关更多详细信息,请参阅 vllm benchmark。
9 性能调优¶
9.1 Atlas 800I A3 PD 优化¶
第 5.3 节的参考配置已启用以下优化。复现部署时,请使用相同的 W8A8 权重和对应角色的配置。
| 优化项 | 角色 | 配置 | 作用与约束 |
|---|---|---|---|
| FlashComm1 | Prefill 和 Decode | enable_flashcomm1: true |
优化张量并行通信。 |
| DSA 上下文并行 | Prefill | enable_dsa_cp: true |
分布式处理长提示词的稀疏注意力计算;使用模型运行器 V1。 |
| Prefill MoE 通信 | Prefill | enable_prefill_mc2: true, enable_fused_mc2: 1, enable_shared_expert_dp: true |
使用参考配置中的 W8A8 权重和 EP16 布局进行融合 MoE 通信;该角色保持 multistream_overlap_shared_expert: false。 |
| 共享专家重叠执行 | Decode | multistream_overlap_shared_expert: true |
将共享专家计算与其他工作重叠执行;Decode 配置未启用融合 MC2。 |
| Decode 执行 | Decode | FULL_DECODE_ONLY |
降低解码阶段的启动开销。 |
| MTP | Prefill 和 Decode | num_speculative_tokens: 5 |
Prefill 草稿模型保持 eager 模式,Decode 草稿模型启用图执行。 |
| KV 容量 | Prefill 和 Decode | --kv-cache-dtype int8 |
减少长上下文场景下的 KV cache 内存消耗。 |
9.2 按工作负载调优¶
- 分别调节各角色的
--max-num-seqs和--max-num-batched-tokens。参考配置在 Prefill 上使用 64 条序列和 4096 个批处理 Token,在 Decode 上使用 32 条序列和 192 个批处理 Token。修改这些上限前,请先测量首 Token 时延、每个输出 Token 的时延和吞吐量。 - 根据所需上下文长度设置
--max-model-len,并根据可用 NPU 内存调节--gpu-memory-utilization。参考配置在两个角色上均使用 1048576 个 Token 和 0.92 的内存利用率。 - Decode 启用
recompute_scheduler_enable: true,以便在 Decode KV cache 不足时在 Prefill 上重新计算。Prefill 上应保持禁用。 - 对于重复前缀,请使用第 5.4 节中的 DDR KV Cache 池配置。Prefill 和 Decode 的每个 worker 均贡献
20GB。评估复用收益时,请确认池命中情况。
10 常见问题¶
- 问:如何为 GLM-5.3-Flash 启用函数调用?
答:请在 vLLM 启动命令中添加以下配置
- 问:GLM-5.3-Flash 是否支持
enable_thinking: false?
答:不支持,GLM-5.3-Flash 不支持 enable_thinking。