| 组件 | 版本 |
|---|---|
| 硬件环境 | 910C |
| 服务器数 | 6 机 |
| 组件 | 版本 |
|---|---|
| vllm-ascend | 0.18.0.RC1 |
| HDK | Ascend HDK 25.3.rc1 |
| CANN | 8.5.0 |
| 模型 | GLM-5 |
GLM-5 是智谱新一代的旗舰基座模型,面向智能体工程(Agentic Engineering)打造,能够在复杂系统工程与长程智能体任务中提供可靠生产力。在代码生成与智能体能力上,GLM-5 取得开源领域的最佳表现(SOTA),在真实编程场景的使用体验逼近 Claude Opus 4.5,擅长复杂系统工程与长程智能体任务,是通用智能体助手的理想基座。
GLM-5 模型是一款大语言模型(LLM),采用 MLA(DSA)+ MoE 结构,总参数量为 7740 亿,推理时激活的参数为 400 亿。从 GLM 4.x 到 GLM-5,结构上最大的变化是注意力(Attention)部分从 GQA 变为了 DSA,与 DeepSeek V3.2 类似。
基于 vLLM-Ascend 框架的初始(0 day)镜像存在开箱性能差、吞吐低的问题。经特性叠加性能调优后,模型推理速度提升,单卡吞吐提升了 x 倍。
通过接入 MLAPO 融合算子、muls_add 融合算子、MoE 大融合算子、共享专家多流特性、PD 分离特性、MTP 接受率提升、调整 PD 分离服务化参数等调优策略,实测在输入 65k 输出 1.5k 并发 80 的场景下,单卡总吞吐由 900+ 提升至 2300+ tokens/s,持续调优中。
bf16:GLM-5 · 模型库
w4a8 / w8a8 量化:
ModelSlim 安装与量化命令:
# git clone https://gitcode.com/Ascend/msmodelslim
git clone -b test_model <modelslim-repo-url>
cd ./msmodelslim
bash install.sh
cd ../
# W8A8
msmodelslim quant \
--model_path "glm-5-float-path" \
--save_path "save-path" \
--model_type GLM-5 \
--device "npu:0" \
--config_path "glm_5_w8a8_yaml_path" \
--trust_remote_code True
# W4A8
msmodelslim quant \
--model_path "glm-5-float-path" \
--save_path "save-path" \
--model_type GLM-5 \
--device "npu:0" \
--config_path "glm_5_w4a8_yaml_path" \
--trust_remote_code Trueglm_5_w4a8_yaml 文件apiversion: modelslim_v1
metadata:
config_id: glm_5_w4a8
score: 90
verified_model_types:
- GLM-5
label:
w_bit: 4
a_bit: 8
is_sparse: False
kv_cache: False
default_w4a8_dynamic: &default_w4a8_dynamic
act:
scope: "per_token"
dtype: "int8"
symmetric: True
method: "minmax"
weight:
scope: "per_channel"
dtype: "int4"
symmetric: True
method: "ssz"
default_w8a8_dynamic: &default_w8a8_dynamic
act:
scope: "per_token"
dtype: "int8"
symmetric: True
method: "minmax"
weight:
scope: "per_channel"
dtype: "int8"
symmetric: True
method: "minmax"
spec:
process:
- type: "quarot"
- type: "flex_awq_ssz"
qconfig:
act:
scope: "per_token"
dtype: "int8"
symmetric: True
method: "minmax"
weight:
scope: "per_channel"
dtype: "int4"
symmetric: True
method: "ssz"
ext:
step: 10
enable_subgraph_type:
- 'up-down'
include:
- "*"
exclude:
- "model.layers.0.*"
- "model.layers.1.*"
- "model.layers.2.*"
- "*mlp.shared_experts.*"
- type: "flex_smooth_quant"
enable_subgraph_type:
- 'norm-linear'
- 'ov'
- 'up-down'
include:
- "*self_attn*"
- "model.layers.0.mlp.*"
- "model.layers.1.mlp.*"
- "model.layers.2.mlp.*"
- "*mlp.shared_experts.*"
- "*input_layernorm*"
exclude:
- "*post_attention_layernorm*"
- type: "group"
configs:
- type: "linear_quant"
qconfig: *default_w8a8_dynamic
include:
- "*self_attn*"
exclude:
- "*kv_b_proj"
- "*wk"
- "*weights_proj"
- type: "linear_quant"
qconfig: *default_w8a8_dynamic
include:
- "*mlp*"
exclude:
- "*gate"
- "*mlp.experts.*"
- type: "linear_quant"
qconfig: *default_w8a8_dynamic
include:
- "model.layers.78.mlp.experts.*"
- type: "linear_quant"
qconfig: *default_w4a8_dynamic
include:
- "*mlp.experts.*"
exclude:
- "model.layers.78.*"
dataset: qwen3_cot_w4a4.json
save:
- type: "ascendv1_saver"
part_file_size: 4glm_5_w8a8_yaml 文件apiversion: modelslim_v1
metadata:
config_id: glm_5_w8a8
score: 90
verified_model_types:
- GLM-5
label:
w_bit: 8
a_bit: 8
is_sparse: False
kv_cache: False
default_w8a8_dynamic: &default_w8a8_dynamic
act:
scope: "per_token"
dtype: "int8"
symmetric: True
method: "minmax"
weight:
scope: "per_channel"
dtype: "int8"
symmetric: True
method: "minmax"
default_w8a8: &default_w8a8
act:
scope: "per_tensor"
dtype: "int8"
symmetric: False
method: "minmax"
weight:
scope: "per_channel"
dtype: "int8"
symmetric: True
method: "minmax"
spec:
process:
- type: "quarot"
- type: "flex_smooth_quant"
enable_subgraph_type:
- 'norm-linear'
- 'ov'
include:
- "*"
- type: "linear_quant"
qconfig: *default_w8a8
include:
- "*self_attn*"
exclude:
- "*kv_b_proj"
- "*wk"
- "*weights_proj"
- type: "linear_quant"
qconfig: *default_w8a8_dynamic
include:
- "*mlp*"
exclude:
- "*gate"
dataset: mix_calib.jsonl
save:
- type: "ascendv1_saver"
part_file_size: 4参考:GLM-5 Ascend 示例文档,基于 0 day 镜像更新如下版本号,并重新制作镜像:
| 组件 | 仓库/版本 | 提交 |
|---|---|---|
| vllm | <vllm-repo-url>,releases/v0.16.0 | 9fbaba936400bc2789a69442afce2e54bab4f99f |
| vllm-ascend | <vllm-ascend-repo-url>,br_glm | e42379dc1b7da893ed15bb2f9d73599215a7eb5b |
| transformers | v5.2.0 | 7d9754a05193eb79b1d86aa744b622b8068008cd |
docker run -itd --privileged --name=GLM5_test --net=host \
--shm-size 500g \
--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/hisi_hdc \
--device /dev/devmm_svm \
-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 \
-v /home:/home \
-v /disk1:/disk1 \
-v /disk2:/disk2 \
-v /disk3:/disk3 \
-v /opt:/opt \
-v /home:/home \
--entrypoint /bin/bash \
m.daocloud.io/quay.io/ascend/vllm-ascend:glm5-a3由于单算子模式需要频繁地下发算子,会造成 Host 瓶颈。为缓解此问题,可采用 ACL Graph 图模式,实现一次捕获、多次重放,从而减少 CPU 和框架的调度开销,提高吞吐性能。
异步调度特性 --async-scheduling 能够减少推理过程中 token 之间的空泡等待时间,提升整体推理性能。
启用方法:启动推理服务时添加以下启动选项。
--async-scheduling通过此环境变量可配置 task_queue 算子下发队列是否开启和优化等级。
0 时:关闭 task_queue 算子下发队列优化。1 或未配置时:开启 task_queue 算子下发队列 Level 1 优化。Level 1 优化:使能 task_queue 算子下发队列优化,将算子下发任务分为两段,一部分任务(主要是 aclnn 算子的调用)放在新增的二级流水上,一、二级流水通过算子队列传递任务,相互并行,通过部分掩盖减少整体的下发耗时,提升端到端性能。
使能方法:
export TASK_QUEUE_ENABLE=1jemalloc 是一款内存分配器,与传统内存分配器(例如 glibc)相比,其最大优势在于减少内存碎片和提升多线程高并发场景下内存的分配效率,进而充分发挥多核多并发的优势。
在内存分配过程中,锁会造成线程等待,对性能影响很大。jemalloc 采用线程变量,每个线程有对应的内存管理器,内存分配在该线程内完成,无需和其他线程竞争锁。
详细参考:Ascend CANN 安装指导 - jemalloc
使能方法:
export LD_PRELOAD=/usr/local/Ascend/ascend-toolkit/latest/lib64/libjemalloc.so开启 HCCL AIV 模式,代表通信算法的编排展开位置在 Device 侧的 Vector Core,执行也在 Vector Core。
详细参考:HCCL_OP_EXPANSION_MODE 环境变量
使能方法:
export HCCL_OP_EXPANSION_MODE="AIV"PR 已合入至 0.17.0.rc1。
MLA 的预处理阶段、Decoding 阶段会有大量小算子,单次执行时间会小于单次下发耗时,形成 host bound。加之拼接类算子、搬运类算子较多,融合是比较合理的优化途径。该方案将前处理过程中的 13 个小算子直接融合成一个超级大算子 MLAPO(MlaPreprocessOperation),进一步提升性能。
MLAPO 算子的完整流程可以分为以下几个步骤:
MLAPO 算子最初专为 DeepSeek V3 模型开发。在代码中,DeepSeek V3 的 MLA 维度参数被作为编译期常量(constexpr)硬编码在 C++ 源码中。当 GLM-5(glm_moe_dsa)模型尝试使用同一算子时,由于其 MLA 维度参数与 DeepSeek V3 不同,导致精度错误。
将维度参数通过 tiling 数据从 host 传递到 kernel,运行时动态读取。推导代码(op_host/mla_preprocess.h 中 mla_preprocess_tiling() 函数):
uint32_t qkNopeHeadDim = wuk.sizes()[1]; // DS=128, GLM5=192
uint32_t kvLoraRank = wuk.sizes()[2]; // DS=GLM5=512
uint32_t qLoraRank = gamma1.sizes()[0]; // DS=1536, GLM5=2048
uint32_t qkRopeHeadDim = kv_cache_rope.sizes().back(); // DS=GLM5=64从这 4 个基础维度可派生出 kernel 内部需要的全部 9 个复合维度:
mm1OutSize = qLoraRank + kvLoraRank + qkRopeHeadDim
splitSizeOne = kvLoraRank + qkRopeHeadDim
splitSizeTwo = qLoraRank
splitRmsNormSizeOne = kvLoraRank
splitRmsNormSizeTwo = qkRopeHeadDim
ropeSplitSizeOne = qkRopeHeadDim
ropeSplitSizeTwo = qkNopeHeadDim
hiddenStrateRope = qkNopeHeadDim + qkRopeHeadDim
qkNopeHeadDim = qkNopeHeadDimGLM-5 适配 PR:vLLM-Ascend PR #6902
fuse_muls_add 融合算子已合入。
硬编码的方式未能适配 GLM-5 模型。通过读取 hf_text_config 内的 routed_scaling_factor 字段,可以灵活解决 muls_add 融合算子在 GLM-5 模型上未生效的问题。
相关 PR:
启动示例:
export HCCL_OP_EXPANSION_MODE="AIV"
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export VLLM_USE_V1=1
export HCCL_BUFFSIZE=200
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_ASCEND_BALANCE_SCHEDULING=1
export VLLM_TORCH_PROFILER_DIR="/path/to/profiling"
export VLLM_TORCH_PROFILER_WITH_STACK=0
export PYTHONPATH=/path/to/vllm:/path/to/vllm-ascend:${PYTHONPATH}
nohup vllm serve /path/to/GLM-5-w4a8 \
--host <listen-host> \
--port 8077 \
--data-parallel-size 1 \
--tensor-parallel-size 16 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name glm-5 \
--max-num-seqs 8 \
--max-model-len 199000 \
--max-num-batched-tokens 4096 \
--trust-remote-code \
--gpu-memory-utilization 0.95 \
--quantization ascend \
--enable-chunked-prefill \
--no-enable-prefix-caching \
--reasoning-parser glm45 \
--enable-auto-tool-choice \
--tool-call-parser glm47 \
--async-scheduling \
--additional-config '{"ascend_compilation_config": {"enable_npugraph_ex": true, "fuse_qknorm_rope": true, "fuse_muls_add": true}, "multistream_overlap_shared_expert": true}' \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
--speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp"}' \
>> glm5.log &
tail -2199f glm5.log基于相同的集合通信逻辑,将 AllReduce 拆分为 ReduceScatter 和 AllGather,并选择通信算子的合适位置,实现低比特和低维度数据通信,从而有效降低通信数据量和通信时延,并消除模型中的冗余计算,提升推理性能。
使能方法:
export VLLM_ASCEND_ENABLE_FLASHCOMM1=1通过开启共享专家多流,共享专家与路由专家进行 CV 并行和通算并行,提升推理性能,单卡吞吐提升 5-10%。
使能方法:
{
"multistream_overlap_shared_expert": true
}MoE 大融合算子使能方法:
export VLLM_ASCEND_ENABLE_FUSED_MC2=1GLM-5 启用失败原因:
经过 ModelSlim 后量化的 MoE 模型(如 MiniMax-M2.5、GLM-5),其 config.json 中缺少 moe_quantize / quantize 字段,导致 quant_type=None,进而无法启用 FUSED_MC2。
相关问题修复:vLLM-Ascend PR #7217
解决方案:
读取 quant_model_description.json 文件,将其 value 作为量化类型(如 W8A8_DYNAMIC),确保 FUSED_MC2 算子正常启用。
算子接入成功:
待补充图示。
基线:
待补充图示。
w8a8 权重采信率低。
叠加 MTP 采信率修复。启动命令的 --additional-config 中需要增加:
{
"rot_path": "/path/to/rot.safetensors"
}rot.safetensors 下载地址:<rot-safetensors-download-url>
注意:rot.safetensors 不能放在权重路径下。
rot.safetensors 需要放到模型权重路径下。quant_model_weights.safetensors.index.json 增加相关配置。quant_model_description.json 增加相关配置。修复后:w8a8 权重 + MTP 采信率提升至 60%+。
0.18.0.rc1 版本参考:vLLM-Ascend GLM-5 教程
export PYTHONPATH=/vllm_ascend/vllm:${PYTHONPATH}
export VLLM_ASCEND_ENABLE_FUSED_MC2=1
export VLLM_ASCEND_ENABLE_MLAPO=1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
export VLLM_VERSION=0.16.0
# 通过 ifconfig 获取本机信息。
# nic_name 为当前节点 local_ip 对应的网卡接口名称。
nic_name="<nic-name>"
local_ip="<node0-local-ip>"
export PYTHONPATH=/workspace/vllm:/workspace/vllm-ascend:${PYTHONPATH}
# node0_ip 的值必须与节点 0(主节点)中设置的 local_ip 一致。
node0_ip="<node0-ip>"
export VLLM_ASCEND_ENABLE_MLAPO=1
export HCCL_OP_EXPANSION_MODE="AIV"
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 OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export VLLM_USE_V1=1
export HCCL_BUFFSIZE=256
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_VERSION=0.16.0
nohup vllm serve /path/to/GLM-5-w4a8 \
--host <listen-host> \
--port 8088 \
--data-parallel-size 1 \
--data-parallel-address $node0_ip \
--data-parallel-rpc-port 11276 \
--tensor-parallel-size 16 \
--quantization ascend \
--seed 1024 \
--served-model-name glm-5 \
--enable-expert-parallel \
--max-num-seqs 40 \
--max-model-len 200000 \
--max-num-batched-tokens 8192 \
--trust-remote-code \
--gpu-memory-utilization 0.92 \
--enable-chunked-prefill \
--async-scheduling \
--additional-config '{"enable_npugraph_ex": true, "fuse_qknorm_rope": true, "fuse_muls_add": true, "multistream_overlap_shared_expert": true, "rot_path": "/path/to/rot.safetensors"}' \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [4, 8, 12, 16, 32, 40]}' \
--speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp"}' \
--enable-auto-tool-choice \
--tool-call-parser glm47 \
--reasoning-parser glm45 \
>> log.log &
tail -200f log.log节点0:
export PYTHONPATH=/vllm_ascend/vllm:${PYTHONPATH}
export VLLM_ASCEND_ENABLE_FUSED_MC2=1
export VLLM_ASCEND_ENABLE_MLAPO=1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
export VLLM_VERSION=0.16.0
# 通过 ifconfig 获取本机信息。
# nic_name 为当前节点 local_ip 对应的网卡接口名称。
nic_name="<nic-name>"
local_ip="<node0-local-ip>"
export PYTHONPATH=/workspace/vllm:/workspace/vllm-ascend:${PYTHONPATH}
# node0_ip 的值必须与节点 0(主节点)中设置的 local_ip 一致。
node0_ip="<node0-ip>"
export VLLM_ASCEND_ENABLE_MLAPO=1
export HCCL_OP_EXPANSION_MODE="AIV"
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 OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export VLLM_USE_V1=1
export HCCL_BUFFSIZE=256
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_VERSION=0.16.0
nohup vllm serve /path/to/GLM-5-w8a8 \
--host <listen-host> \
--port 8088 \
--data-parallel-size 2 \
--data-parallel-size-local 1 \
--data-parallel-address $node0_ip \
--data-parallel-rpc-port 11276 \
--tensor-parallel-size 16 \
--quantization ascend \
--seed 1024 \
--served-model-name glm-5 \
--enable-expert-parallel \
--max-num-seqs 40 \
--max-model-len 200000 \
--max-num-batched-tokens 8192 \
--trust-remote-code \
--gpu-memory-utilization 0.92 \
--enable-chunked-prefill \
--async-scheduling \
--additional-config '{"enable_npugraph_ex": true, "fuse_qknorm_rope": true, "fuse_muls_add": true, "multistream_overlap_shared_expert": true, "rot_path": "/path/to/rot.safetensors"}' \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [4, 8, 12, 16, 32, 40]}' \
--speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp"}' \
--profiler-config \
'{"profiler": "torch",
"torch_profiler_dir": "/path/to/profiling",
"torch_profiler_with_stack": false}' \
--enable-auto-tool-choice \
--tool-call-parser glm47 \
--reasoning-parser glm45 \
>> log.log &
tail -200f log.log节点1:
export PYTHONPATH=/vllm_ascend/vllm:${PYTHONPATH}
export VLLM_ASCEND_ENABLE_FUSED_MC2=1
export VLLM_ASCEND_ENABLE_MLAPO=1
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
export VLLM_VERSION=0.16.0
# 通过 ifconfig 获取本机信息。
# nic_name 为当前节点 local_ip 对应的网卡接口名称。
nic_name="<nic-name>"
local_ip="<node1-local-ip>"
export PYTHONPATH=/workspace/vllm:/workspace/vllm-ascend:${PYTHONPATH}
# node0_ip 的值必须与节点 0(主节点)中设置的 local_ip 一致。
node0_ip="<node0-ip>"
export VLLM_ASCEND_ENABLE_MLAPO=1
export HCCL_OP_EXPANSION_MODE="AIV"
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 OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export VLLM_USE_V1=1
export HCCL_BUFFSIZE=256
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_VERSION=0.16.0
nohup vllm serve /path/to/GLM-5-w8a8 \
--host <listen-host> \
--port 8088 \
--headless \
--data-parallel-size 2 \
--data-parallel-size-local 1 \
--data-parallel-start-rank 1 \
--data-parallel-address $node0_ip \
--data-parallel-rpc-port 11276 \
--tensor-parallel-size 16 \
--quantization ascend \
--seed 1024 \
--served-model-name glm-5 \
--enable-expert-parallel \
--max-num-seqs 40 \
--max-model-len 200000 \
--max-num-batched-tokens 8192 \
--trust-remote-code \
--gpu-memory-utilization 0.92 \
--enable-chunked-prefill \
--async-scheduling \
--additional-config '{"enable_npugraph_ex": true, "fuse_qknorm_rope": true, "fuse_muls_add": true, "multistream_overlap_shared_expert": true, "rot_path": "/path/to/rot.safetensors"}' \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [4, 8, 12, 16, 32, 40]}' \
--speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp"}' \
--profiler-config \
'{"profiler": "torch",
"torch_profiler_dir": "/path/to/profiling",
"torch_profiler_with_stack": false}' \
--enable-auto-tool-choice \
--tool-call-parser glm47 \
--reasoning-parser glm45 \
>> log.log &
tail -200f log.loglaunch_online_dp.py 脚本import argparse
import multiprocessing
import os
import subprocess
import sys
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument(
"--dp-size",
type=int,
required=True,
help="Data parallel size.",
)
parser.add_argument(
"--tp-size",
type=int,
default=1,
help="Tensor parallel size.",
)
parser.add_argument(
"--dp-size-local",
type=int,
default=-1,
help="Local data parallel size.",
)
parser.add_argument(
"--dp-rank-start",
type=int,
default=0,
help="Starting rank for data parallel.",
)
parser.add_argument(
"--dp-address",
type=str,
required=True,
help="IP address for data parallel master node.",
)
parser.add_argument(
"--dp-rpc-port",
type=str,
default=12345,
help="Port for data parallel master node.",
)
parser.add_argument(
"--vllm-start-port",
type=int,
default=9000,
help="Starting port for the engine.",
)
return parser.parse_args()
args = parse_args()
dp_size = args.dp_size
tp_size = args.tp_size
dp_size_local = args.dp_size_local
if dp_size_local == -1:
dp_size_local = dp_size
dp_rank_start = args.dp_rank_start
dp_address = args.dp_address
dp_rpc_port = args.dp_rpc_port
vllm_start_port = args.vllm_start_port
def run_command(visible_devices, dp_rank, vllm_engine_port):
command = [
"bash",
"./run_dp_template.sh",
visible_devices,
str(vllm_engine_port),
str(dp_size),
str(dp_rank),
dp_address,
dp_rpc_port,
str(tp_size),
]
subprocess.run(command, check=True)
if __name__ == "__main__":
template_path = "./run_dp_template.sh"
if not os.path.exists(template_path):
print(f"Template file {template_path} does not exist.")
sys.exit(1)
processes = []
num_cards = dp_size_local * tp_size
for i in range(dp_size_local):
dp_rank = dp_rank_start + i
vllm_engine_port = vllm_start_port + i
visible_devices = ",".join(
str(x) for x in range(i * tp_size, (i + 1) * tp_size)
)
process = multiprocessing.Process(
target=run_command,
args=(visible_devices, dp_rank, vllm_engine_port),
)
processes.append(process)
process.start()
for process in processes:
process.join()参考:GLM-5 PD 分离 A3 1*2P 1*4D 部署指导。
run_dp_template.sh 脚本需要修改网卡名称及本机 IP。
# cp /path/to/recompute_scheduler.py /usr/local/python3.11.10/lib/python3.11/site-packages/vllm_ascend/core/recompute_scheduler.py
# cp /path/to/deepseek_mtp.py /usr/local/python3.11.10/lib/python3.11/site-packages/vllm/model_executor/models/deepseek_mtp.py
# export PYTHONPATH=/path/to/vllm-ascend:${PYTHONPATH}
export PYTHONPATH=/vllm_ascend/vllm:${PYTHONPATH}
export VLLM_VERSION=0.16.0
export VLLM_ASCEND_ENABLE_FUSED_MC2=1
export VLLM_ASCEND_ENABLE_MLAPO=0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
nic_name="<nic-name>"
local_ip="<p0-local-ip>"
export HCCL_OP_EXPANSION_MODE="AIV"
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 OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_USE_V1=1
export HCCL_BUFFSIZE=256
export ASCEND_AGGREGATE_ENABLE=1
export ASCEND_TRANSPORT_PRINT=1
export ACL_OP_INIT_MODE=1
export ASCEND_A3_ENABLE=1
export VLLM_NIXL_ABORT_REQUEST_TIMEOUT=300000
export ASCEND_RT_VISIBLE_DEVICES=$1
export VLLM_ASCEND_ENABLE_FLASHCOMM1=0
export VLLM_VERSION=0.16.0
vllm serve /path/to/GLM-5-w8a8 \
--host <listen-host> \
--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 \
--speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp"}' \
--profiler-config \
'{"profiler": "torch",
"torch_profiler_dir": "/path/to/profiling",
"torch_profiler_with_stack": false}' \
--seed 1024 \
--served-model-name dsv3 \
--max-model-len 131072 \
--additional-config '{"enable_npugraph_ex": true, "fuse_qknorm_rope": true, "fuse_muls_add": true, "multistream_overlap_shared_expert": true, "recompute_scheduler_enable": true, "rot_path": "/path/to/rot.safetensors"}' \
--max-num-batched-tokens 4096 \
--trust-remote-code \
--max-num-seqs 64 \
--quantization ascend \
--gpu-memory-utilization 0.92 \
--enforce-eager \
--enable-auto-tool-choice \
--tool-call-parser glm47 \
--reasoning-parser glm45 \
--kv-transfer-config \
'{"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_producer",
"kv_port": "30000",
"engine_id": "0",
"kv_connector_extra_config": {
"use_ascend_direct": true,
"prefill": {
"dp_size": 2,
"tp_size": 16
},
"decode": {
"dp_size": 16,
"tp_size": 4
}
}}' 2>&1 | tee glm.logrun_dp_template.sh 脚本与 P0 节点相比,需注意修改以下内容:
nic_namelocal_ipLD_PRELOADkv-transfer-config 中的 kv_portkv-transfer-config 中的 engine_idrun_dp_template.sh 脚本需修改网卡名称及本机 IP。两个 D 节点脚本的区别仅在于 nic_name、local_ip 和 LD_PRELOAD。
# cp /path/to/recompute_scheduler.py /usr/local/python3.11.10/lib/python3.11/site-packages/vllm_ascend/core/recompute_scheduler.py
# cp /path/to/deepseek_mtp.py /usr/local/python3.11.10/lib/python3.11/site-packages/vllm/model_executor/models/deepseek_mtp.py
# export PYTHONPATH=/path/to/vllm-ascend:${PYTHONPATH}
export PYTHONPATH=/vllm_ascend/vllm:${PYTHONPATH}
export VLLM_ASCEND_ENABLE_FUSED_MC2=1
export VLLM_ASCEND_ENABLE_MLAPO=0
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
export VLLM_VERSION=0.16.0
nic_name="<nic-name>"
local_ip="<d-node-local-ip>"
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
# Mooncake
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_USE_V1=1
export HCCL_BUFFSIZE=256
export ASCEND_AGGREGATE_ENABLE=1
export ASCEND_TRANSPORT_PRINT=1
export ACL_OP_INIT_MODE=1
export ASCEND_A3_ENABLE=1
export VLLM_NIXL_ABORT_REQUEST_TIMEOUT=300000
export TASK_QUEUE_ENABLE=1
export ASCEND_RT_VISIBLE_DEVICES=$1
export VLLM_VERSION=0.16.0
vllm serve /path/to/GLM-5-w8a8 \
--host <listen-host> \
--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 \
--speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp"}' \
--profiler-config \
'{"profiler": "torch",
"torch_profiler_dir": "/path/to/profiling",
"torch_profiler_with_stack": false}' \
--seed 1024 \
--served-model-name dsv3 \
--max-model-len 200000 \
--max-num-batched-tokens 32 \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY", "cudagraph_capture_sizes": [4, 8, 12, 16, 20, 24, 28, 32]}' \
--additional-config '{"enable_npugraph_ex": true, "fuse_qknorm_rope": true, "fuse_muls_add": true, "multistream_overlap_shared_expert": true, "recompute_scheduler_enable": true, "rot_path": "/path/to/rot.safetensors"}' \
--trust-remote-code \
--max-num-seqs 8 \
--gpu-memory-utilization 0.92 \
--async-scheduling \
--quantization ascend \
--enable-auto-tool-choice \
--tool-call-parser glm47 \
--reasoning-parser glm45 \
--kv-transfer-config \
'{"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_consumer",
"kv_port": "30100",
"engine_id": "1",
"kv_connector_extra_config": {
"use_ascend_direct": true,
"prefill": {
"dp_size": 2,
"tp_size": 16
},
"decode": {
"dp_size": 16,
"tp_size": 4
}
}}' 2>&1 | tee glm.log可以选择在每个节点创建 server.sh 后执行 bash server.sh,也可以直接在命令行执行。
P0:
python launch_online_dp.py \
--dp-size 2 \
--tp-size 16 \
--dp-size-local 1 \
--dp-rank-start 0 \
--dp-address <p-master-ip> \
--dp-rpc-port 12890 \
--vllm-start-port 9100P1:
python launch_online_dp.py \
--dp-size 2 \
--tp-size 16 \
--dp-size-local 1 \
--dp-rank-start 1 \
--dp-address <p-master-ip> \
--dp-rpc-port 12890 \
--vllm-start-port 9100D0:
python launch_online_dp.py \
--dp-size 8 \
--tp-size 4 \
--dp-size-local 4 \
--dp-rank-start 4 \
--dp-address <d-master-ip> \
--dp-rpc-port 12777 \
--vllm-start-port 9100D1:
python launch_online_dp.py \
--dp-size 8 \
--tp-size 4 \
--dp-size-local 4 \
--dp-rank-start 0 \
--dp-address <d-master-ip> \
--dp-rpc-port 12777 \
--vllm-start-port 9100proxy.sh 脚本port 为自定义服务端口,host 修改为 proxy 部署机器 IP。剩余需要替换 prefill 及 decode 的 IP,IP 个数和每个节点 DP 数相同。
unset http_proxy
unset https_proxy
python load_balance_proxy_server_example.py \
--port 8000 \
--host <proxy-host> \
--prefiller-hosts \
<prefill-host-0> \
<prefill-host-1> \
--prefiller-ports \
9100 \
9100 \
--decoder-hosts \
<decode-host-0> \
<decode-host-0> \
<decode-host-0> \
<decode-host-0> \
<decode-host-1> \
<decode-host-1> \
<decode-host-1> \
<decode-host-1> \
--decoder-ports \
9100 9101 9102 9103 \
9100 9101 9102 9103load_balance_proxy_server_example.py 下载地址:vLLM-Ascend load_balance_proxy_server_example.py
举例:80 并发,dp_size = 16。
max-num-seqs:单个 DP 最大请求个数应大于等于 总并发个数 / dp_size = 80 / 16 = 5,因此可以配置成 8。cudagraph_capture_sizes:应修改为 [MTP + 1] * 单个 DP 域并发个数 的倍数,可以配置成 [4, 8, 12, 16, 20, 24, 28, 32]。max-num-batched-tokens:单次 step 调度所有请求的 token 总数上限,应大于等于 max-num-seqs * [MTP + 1] = 8 * [3 + 1] = 32,才能跑满并发。调优前:
max-num-seqs: 2
max-num-batched-tokens: 8调优后:
max-num-seqs: 8
max-num-batched-tokens: 32待补充图示。
注意:性能数据 A3 1*2P 1*4D 以实测为准,仅供参考。
| 模型 | 数据集 | 精度数据 |
|---|---|---|
| GLM-5-w8a8 | GPQA-Diamond | 84-85,存在波动 |
通过叠加多种优化策略,GLM-5 模型的推理性能得到提升。测试结果显示,经初步性能调优后,基于 A3 实测在 GLM-5-w8a8 模型的单卡吞吐较开箱性能提升了 x 倍以上。