基于 openYuanrong 的 GLM-5 W4A8 单实例部署¶
概述¶
本指南提供在 Atlas 800I A2 服务器(双机)或 Atlas 800I A3 / Atlas 800T A3 服务器(单机)上部署 GLM-5 W4A8 模型并使用 openYuanrong Datasystem 作为 KV Pool 后端的详细步骤。
GLM-5 是采用混合专家架构的高效推理模型,专为复杂系统工程和长时序智能体任务设计。使用 openYuanrong 作为 KV Pool 后端可以实现高效的 KV Cache 存储和请求间的复用。
部署全景流程:
环境要求确认
准备模型权重
拉取镜像与创建容器
容器内环境配置(升级依赖 + 打补丁,若vllm-ascend版本>= 0.20则跳过)
安装 openYuanrong Datasystem
启动 openYuanrong Worker
启动VLLM推理服务
功能验证
环境准备¶
硬件要求¶
A3 单机:1 × Atlas 800I A3 或 Atlas 800T A3 服务器,配备 8 张 NPU 卡(每张 128G 显存)
A2 双机:2 × Atlas 800I A2 服务器,每台配备 8 张 NPU 卡(每张 64G 显存)
已配置 RoCE 或灵衢网络以获得最佳性能
软件要求¶
采用模型配套的Docker镜像,软件版本与 Docker 镜像内置版本保持一致,确保hdk、固件等软件在配套范围内。 此外:CANN版本要求至少高于8.5.0,HDK版本要求至少高于25.2.3(启用 RH2D,版本需要 25.5.0 以上)。
执行npu-smi info查看
(base) xx@A800T-03:~$ npu-smi info
+------------------------------------------------------------------------------------------------+ | npu-smi 25.5.0 Version: 25.5.0 | +---------------------------+---------------+----------------------------------------------------+
模型权重¶
下载 GLM-5 W4A8 模型权重并放置到指定目录,如 /home/models/GLM-5-w4a8/。
模型下载地址:魔搭社区
使用 Docker 运行¶
本教程使用的 Docker 镜像版本为 vllm-ascend:0.18.0rc1。如本地尚未下载,可先按机器类型执行以下命令:
# A2 双机
docker pull quay.io/ascend/vllm-ascend:0.18.0rc1
# A3 单机
docker pull quay.io/ascend/vllm-ascend:0.18.0rc1-a3
如果下载较慢,可将 quay.io 替换为 m.daocloud.io/quay.io 或 quay.nju.edu.cn 以加速拉取。更多镜像说明可参考安装文档。
运行容器¶
A3 单机¶
可参考以下脚本启动 A3 容器。先将下面内容保存为 start-docker.sh:
#!/bin/bash
IMAGES_ID="$1"
NAME="$2"
# 检查参数数量(需要 2 个:镜像 ID 和容器名)
if [ $# -ne 2 ]; then
echo "error: 需要传入2个参数,格式:$0 <镜像ID> <容器名>"
exit 1
fi
# 检查镜像是否存在
if ! docker images --format "{{.ID}}" | grep -q "^${IMAGES_ID:0:12}$"; then
echo "error: 镜像ID $IMAGES_ID 不存在"
exit 1
fi
docker run --name "${NAME}" -it -d --net=host --shm-size=500g \
--privileged=true \
-w /home \
--device=/dev/davinci_manager \
--device=/dev/hisi_hdc \
--device=/dev/devmm_svm \
--entrypoint=bash \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /usr/local/sbin:/usr/local/sbin \
-v /etc/hccn.conf:/etc/hccn.conf \
-v /home:/home \
-v /mnt:/mnt \
-v /tmp:/tmp \
-v /data:/data \
-v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime \
-e http_proxy="$http_proxy" \
-e https_proxy="$https_proxy" \
"${IMAGES_ID}"
拉取镜像后,可先通过以下命令查看镜像 ID:
docker images | grep vllm-ascend
然后执行以下命令创建容器:
bash start-docker.sh ac1c767e5aa2 glm5-v0.18.0rc1-a3
创建完成后进入容器:
docker exec -it glm5-v0.18.0rc1-a3 bash
A2 双机¶
A2 双机场景也可采用与 A3 类似的脚本方式。在两个节点分别保存同一份 start-docker.sh,内容如下:
#!/bin/bash
IMAGES_ID="$1"
NAME="$2"
# 检查参数数量(需要 2 个:镜像 ID 和容器名)
if [ $# -ne 2 ]; then
echo "error: 需要传入2个参数,格式:$0 <镜像ID> <容器名>"
exit 1
fi
# 检查镜像是否存在
if ! docker images --format "{{.ID}}" | grep -q "^${IMAGES_ID:0:12}$"; then
echo "error: 镜像ID $IMAGES_ID 不存在"
exit 1
fi
docker run --name "${NAME}" -it -d --net=host --shm-size=500g \
--privileged=true \
-w /home \
--device=/dev/davinci_manager \
--device=/dev/hisi_hdc \
--device=/dev/devmm_svm \
--entrypoint=bash \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /usr/local/sbin:/usr/local/sbin \
-v /etc/hccn.conf:/etc/hccn.conf \
-v /home:/home \
-v /mnt:/mnt \
-v /tmp:/tmp \
-v /data:/data \
-v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime \
-e http_proxy="$http_proxy" \
-e https_proxy="$https_proxy" \
"${IMAGES_ID}"
两个节点都先执行以下命令查看各自本机的镜像 ID:
docker images | grep vllm-ascend
然后分别创建容器,例如:
# 节点 0
bash start-docker.sh ac1c767e5aa2 glm5-v0.18.0rc1-a2-node0
# 节点 1
bash start-docker.sh ac1c767e5aa2 glm5-v0.18.0rc1-a2-node1
创建完成后分别进入容器:
# 节点 0
docker exec -it glm5-v0.18.0rc1-a2-node0 bash
# 节点 1
docker exec -it glm5-v0.18.0rc1-a2-node1 bash
容器内环境配置¶
以下操作均在容器内执行,若vllm-ascend版本>= 0.20则跳过
升级 transformers 版本¶
GLM-5 模型要求较高版本的 transformers,进入容器后需先升级:
pip install transformers==5.2.0 --no-deps --force-reinstall
pip install huggingface_hub==1.5.0 --no-deps --force-reinstall
应用补丁¶
使用 openYuanrong 多级缓存前,需要根据镜像版本打对应的补丁。建议先将补丁文件上传到容器内固定目录 /workspace/yuanrong_patches/,然后按版本执行。
准备工作(所有版本通用):
mkdir -p /workspace/yuanrong_patches
git config --global user.email "deploy@local"
git config --global user.name "deploy"
vllm-ascend:0.18.0 补丁¶
补丁文件 |
目标仓库 |
用途 |
|---|---|---|
|
|
修复 |
|
|
补充 openYuanrong backend 支持 |
|
|
修复超过10000个对象时分批传输问题 |
执行步骤
# vllm patch
cd /vllm-workspace/vllm
git am /workspace/yuanrong_patches/0001-Bugfix-Fix-negative-local_cache_hit-in-P-D-disaggreg.patch
# vllm-ascend patches
cd /vllm-workspace/vllm-ascend
git am /workspace/yuanrong_patches/0001-Implement-yuanrong-backend.patch
git am /workspace/yuanrong_patches/0001-fix-kv-pool-update-yuanrong-backend-handling.patch
vllm-ascend:0.18.0rc1 补丁¶
注意:0.18.0rc1 版本的补丁与 0.18.0 正式版不同,请使用对应版本的补丁文件。若环境中已包含这些补丁的改动,可跳过此步骤。
补丁文件 |
目标仓库 |
用途 |
|---|---|---|
|
|
修复 |
|
|
补充 openYuanrong backend 支持 |
|
|
修复 vLLM v0.18.0 在 speculative decoding 场景下 KV Pool 未正确执行 KV Cache put / finalize 的问题,并规避后续 vLLM metrics 统计相关报错 |
执行步骤
# vllm patch
cd /vllm-workspace/vllm
git am /workspace/yuanrong_patches/0001-Bugfix-Fix-negative-local_cache_hit-in-P-D-disaggreg.patch
# vllm-ascend patches
cd /vllm-workspace/vllm-ascend
git am /workspace/yuanrong_patches/0001-Implement-yuanrong-backend.patch
git am /workspace/yuanrong_patches/0001-BugFix-0.18.0-KV-Pool-Fix-KV-Pool-not-putting-kv-cac.patch
安装 openYuanrong Datasystem¶
检查页大小¶
openYuanrong 默认提供的是面向 4 KB 内存页大小机器的安装包。如果目标机器使用 64 KB 页大小,则需要使用额外编译的安装包,默认包可能无法正常安装或运行。
查看页大小:
getconf PAGE_SIZE
如果输出为 65536,请使用针对 64 KB 页大小单独编译的 openYuanrong 安装包。
在线安装¶
pip install openyuanrong-datasystem
离线安装¶
如果目标环境无外网权限,可以从以下地址下载 whl 包进行离线安装:
# 下载 whl 包
wget https://gitcode.com/openeuler/yuanrong-datasystem/releases/download/v0.7.6.rc1/openyuanrong_datasystem-0.7.6rc1-cp311-cp311-manylinux_2_35_aarch64.whl
# 安装
pip install openyuanrong_datasystem-0.7.6rc1-cp311-cp311-manylinux_2_35_aarch64.whl
验证安装:
python -c "import yr.datasystem; print('Yuanrong Datasystem 安装成功')"
安装 etcd¶
后续 openYuanrong 服务启动脚本依赖 etcd 和 etcdctl。请在需要启动 etcd 的节点或容器中先完成安装:
A3 单机场景安装一次即可。
A2 双机场景至少在节点 0 安装。
ETCD_VERSION="v3.5.12"
if [ "$(uname -m)" = "aarch64" ]; then
ETCD_ARCH="linux-arm64"
else
ETCD_ARCH="linux-amd64"
fi
wget https://github.com/etcd-io/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-${ETCD_ARCH}.tar.gz
tar -xvf etcd-${ETCD_VERSION}-${ETCD_ARCH}.tar.gz
cd etcd-${ETCD_VERSION}-${ETCD_ARCH}
sudo cp etcd etcdctl /usr/local/bin/
如果当前容器以 root 用户运行且未安装 sudo,可以直接执行:
cp etcd etcdctl /usr/local/bin/
验证安装:
etcd --version
etcdctl version
启动 openYuanrong 服务¶
A3 单机¶
A3 单机部署只需在一个节点启动 etcd 和 Datasystem Worker。
创建启动脚本 run_yr_a3.sh:
#!/bin/bash
# 配置参数
export HOST_IP="<您的节点IP地址>"
export ETCD_IP="${HOST_IP}"
export WORKER_PORT=18481
export ETCD_PORT=2379
export SHM_SIZE=512000
export NODE_TIMEOUT=30
export NODE_DEAD_TIMEOUT=60
export LIVENESS_PATH=/workspace/liveness
# 启动 etcd(单实例模式)
etcd \
--name etcd-single \
--data-dir /tmp/etcd-data \
--listen-client-urls http://<IP_ADDRESS>:2379 \
--advertise-client-urls http://${ETCD_IP}:2379 \
--listen-peer-urls http://<IP_ADDRESS>:2380 \
--initial-advertise-peer-urls http://${ETCD_IP}:2380 \
--initial-cluster etcd-single=http://${ETCD_IP}:2380 \
> /tmp/etcd.log 2>&1 &
# 等待 etcd 启动
sleep 3
# 验证 etcd 是否正常运行
etcdctl --endpoints "${ETCD_IP}:2379" put key "value"
etcdctl --endpoints "${ETCD_IP}:2379" get key
# 启动 Datasystem Worker
dscli start -w \
--worker_address ${HOST_IP}:${WORKER_PORT} \
--etcd_address ${ETCD_IP}:${ETCD_PORT} \
--shared_memory_size_mb ${SHM_SIZE} \
--node_timeout_s ${NODE_TIMEOUT} \
--node_dead_timeout_s ${NODE_DEAD_TIMEOUT} \
--liveness_check_path ${LIVENESS_PATH}
echo "Yuanrong 服务启动完成"
echo "etcd 日志: /tmp/etcd.log"
运行脚本:
bash run_yr_a3.sh
A2 双机¶
A2 双机部署需要在两个节点都启动 Datasystem Worker,并连接同一个 etcd。
节点 0 创建启动脚本 run_yr_a2_node0.sh(启动 etcd 和 Worker):
#!/bin/bash
# 配置参数
export HOST_IP="<IP_ADDRESS>"
export ETCD_IP="${HOST_IP}"
export WORKER_PORT=18481
export ETCD_PORT=2379
export SHM_SIZE=512000
export NODE_TIMEOUT=30
export NODE_DEAD_TIMEOUT=60
export LIVENESS_PATH=/workspace/liveness
# 启动 etcd(单实例模式)
etcd \
--name etcd-single \
--data-dir /tmp/etcd-data \
--listen-client-urls http://<IP_ADDRESS>:2379 \
--advertise-client-urls http://${ETCD_IP}:2379 \
--listen-peer-urls http://<IP_ADDRESS>:2380 \
--initial-advertise-peer-urls http://${ETCD_IP}:2380 \
--initial-cluster etcd-single=http://${ETCD_IP}:2380 \
> /tmp/etcd.log 2>&1 &
# 等待 etcd 启动
sleep 3
# 验证 etcd 是否正常运行
etcdctl --endpoints "${ETCD_IP}:2379" put key "value"
etcdctl --endpoints "${ETCD_IP}:2379" get key
# 启动 Datasystem Worker
dscli start -w \
--worker_address ${HOST_IP}:${WORKER_PORT} \
--etcd_address ${ETCD_IP}:${ETCD_PORT} \
--shared_memory_size_mb ${SHM_SIZE} \
--node_timeout_s ${NODE_TIMEOUT} \
--node_dead_timeout_s ${NODE_DEAD_TIMEOUT} \
--liveness_check_path ${LIVENESS_PATH}
echo "节点 0 Yuanrong 服务启动完成"
echo "etcd 日志: /tmp/etcd.log"
节点 1 创建启动脚本 run_yr_a2_node1.sh(只启动 Worker,连接节点 0 的 etcd):
#!/bin/bash
# 配置参数
export HOST_IP="<IP_ADDRESS>"
export ETCD_IP="<IP_ADDRESS>"
export WORKER_PORT=18481
export ETCD_PORT=2379
export SHM_SIZE=512000
export NODE_TIMEOUT=30
export NODE_DEAD_TIMEOUT=60
export LIVENESS_PATH=/workspace/liveness
# 启动 Datasystem Worker(连接节点 0 的 etcd)
dscli start -w \
--worker_address ${HOST_IP}:${WORKER_PORT} \
--etcd_address ${ETCD_IP}:${ETCD_PORT} \
--shared_memory_size_mb ${SHM_SIZE} \
--node_timeout_s ${NODE_TIMEOUT} \
--node_dead_timeout_s ${NODE_DEAD_TIMEOUT} \
--liveness_check_path ${LIVENESS_PATH}
echo "节点 1 Yuanrong 服务启动完成"
运行脚本:
# 节点 0 先启动
bash run_yr_a2_node0.sh
# 节点 1 后启动
bash run_yr_a2_node1.sh
etcd 参数说明¶
参数 |
值 |
说明 |
|---|---|---|
name |
etcd-single |
etcd 节点名称,集群中必须唯一 |
data-dir |
/tmp/etcd-data |
数据存储目录,用于持久化保存 etcd 数据 |
listen-client-urls |
http://<IP_ADDRESS>:2379 |
监听客户端请求的 URL 地址, |
advertise-client-urls |
http://${ETCD_IP}:2379 |
对外广播的客户端 URL,其他节点通过此地址连接 |
listen-peer-urls |
http://<IP_ADDRESS>:2380 |
监听集群节点间通信的 URL 地址 |
initial-advertise-peer-urls |
http://${ETCD_IP}:2380 |
对外广播的集群通信 URL,其他 etcd 节点通过此地址进行数据同步 |
initial-cluster |
etcd-single=http://${ETCD_IP}:2380 |
初始集群配置,格式为 |
参考文档:etcd 官方文档,了解更多参数配置。
生产环境建议:上述示例为单实例部署,适用于测试和开发环境。对于可靠性要求较高的生产环境,建议部署 etcd 集群(通常 3 或 5 个节点)。集群部署请参考 etcd 集群部署指南。
Datasystem Worker 参数说明¶
参数 |
值 |
说明 |
|---|---|---|
worker_address |
\({HOST_IP}:\){WORKER_PORT} |
Worker 服务地址和端口 |
etcd_address |
\({ETCD_IP}:\){ETCD_PORT} |
etcd 服务发现地址 |
shared_memory_size_mb |
${SHM_SIZE} (512000) |
共享内存大小(500 GB) |
node_timeout_s |
${NODE_TIMEOUT} (30) |
节点超时时间(秒) |
node_dead_timeout_s |
${NODE_DEAD_TIMEOUT} (60) |
节点死亡超时时间(秒) |
liveness_check_path |
${LIVENESS_PATH} |
存活检查路径 |
参考文档:openYuanrong Datasystem 文档,了解更多 worker 参数和环境变量配置。
停止 Worker:
dscli stop --worker_address ${HOST_IP}:${WORKER_PORT}
部署 GLM-5 W4A8 与 openYuanrong KV Pool¶
A3 单机部署¶
创建启动脚本 run_glm5_w4a8_yuanrong_a3.sh。下面示例参考你给出的单机 A3 启动参数,并补充 openYuanrong 相关配置:
#!/bin/bash
# NPU 性能优化配置
export HCCL_OP_EXPANSION_MODE="AIV"
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export HCCL_BUFFSIZE=256
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_ASCEND_BALANCE_SCHEDULING=1
# vLLM 配置
export VLLM_USE_V1=1
export VLLM_ENGINE_READY_TIMEOUT_S=1800
export PYTHONHASHSEED=0
# openYuanrong Datasystem 配置
export DS_WORKER_ADDR="<节点IP>:18481"
export DS_H2D_MEMCPY_POLICY="direct"
export DS_D2H_MEMCPY_POLICY="direct"
unset GOOGLE_LOGTOSTDERR GOOGLE_ALSOLOGTOSTDERR
MODEL_PATH="/data/GLM-5-w4a8"
vllm serve $MODEL_PATH \
--host <IP_ADDRESS> \
--port 8077 \
--data-parallel-size 2 \
--tensor-parallel-size 8 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name glm-5 \
--max-num-seqs 48 \
--max-model-len 202752 \
--max-num-batched-tokens 8192 \
--trust-remote-code \
--gpu-memory-utilization 0.92 \
--quantization ascend \
--enable-chunked-prefill \
--enable-prefix-caching \
--async-scheduling \
--enable-auto-tool-choice \
--tool-call-parser glm47 \
--reasoning-parser glm45 \
--additional-config '{"enable_npugraph_ex": 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"}' \
--kv-transfer-config '{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {
"lookup_rpc_port": "0",
"backend": "yuanrong"
}
}' 2>&1 | tee ./glm-5_yuanrong_a3.log
A2 双机部署¶
在两个节点上分别创建启动脚本。下面示例参考实际可用配置,使用前请根据 ifconfig 输出、模型目录和日志命名习惯修改。
节点 0 创建 run_glm5_w4a8_yuanrong_a2_node0.sh:
#!/bin/bash
# 通过 ifconfig 获取
# nic_name 为当前节点 local_ip 对应的网卡名称
nic_name="bond0"
local_ip="<IP_ADDRESS>"
# node0_ip 必须与节点 0(主节点)脚本中的 local_ip 保持一致
node0_ip="<IP_ADDRESS>"
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
# NPU 性能优化配置
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export HCCL_BUFFSIZE=256
export VLLM_ASCEND_BALANCE_SCHEDULING=1
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# vLLM 配置
export VLLM_USE_V1=1
export VLLM_ENGINE_READY_TIMEOUT_S=1800
export PYTHONHASHSEED=0
# openYuanrong Datasystem 配置
export DS_WORKER_ADDR="${local_ip}:18481"
export DS_H2D_MEMCPY_POLICY="direct"
export DS_D2H_MEMCPY_POLICY="direct"
unset GOOGLE_LOGTOSTDERR GOOGLE_ALSOLOGTOSTDERR
MODEL_PATH="/home/models/GLM-5-w4a8"
vllm serve $MODEL_PATH \
--host <IP_ADDRESS> \
--port 1025 \
--data-parallel-size 2 \
--data-parallel-size-local 1 \
--data-parallel-address $node0_ip \
--data-parallel-rpc-port 12890 \
--tensor-parallel-size 8 \
--quantization ascend \
--seed 1024 \
--served-model-name glm-5 \
--enable-expert-parallel \
--max-num-seqs 40 \
--max-model-len 202752 \
--max-num-batched-tokens 4096 \
--trust-remote-code \
--gpu-memory-utilization 0.92 \
--enable-chunked-prefill \
--enable-prefix-caching \
--async-scheduling \
--enable-auto-tool-choice \
--tool-call-parser glm47 \
--reasoning-parser glm45 \
--additional-config '{"multistream_overlap_shared_expert":true, "fuse_qknorm_rope": false, "fuse_muls_add": true, "enable_npugraph_ex": true}' \
--compilation-config '{"cudagraph_capture_sizes": [1,4,8,12,16,20,24,28,32,36,40,48,56,64,80,96], "cudagraph_mode": "FULL_DECODE_ONLY"}' \
--speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp"}' \
--kv-transfer-config '{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {
"lookup_rpc_port": "0",
"backend": "yuanrong"
}
}' 2>&1 | tee ./glm-5_yuanrong_a2_node0.log
节点 1 创建 run_glm5_w4a8_yuanrong_a2_node1.sh:
#!/bin/bash
# 通过 ifconfig 获取
# nic_name 为当前节点 local_ip 对应的网卡名称
nic_name="enp61s0f2"
local_ip="<IP_ADDRESS>"
# node0_ip 必须与节点 0(主节点)脚本中的 local_ip 保持一致
node0_ip="<IP_ADDRESS>"
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
# NPU 性能优化配置
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export HCCL_BUFFSIZE=256
export VLLM_ASCEND_BALANCE_SCHEDULING=1
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# vLLM 配置
export VLLM_USE_V1=1
export VLLM_ENGINE_READY_TIMEOUT_S=1800
export PYTHONHASHSEED=0
# openYuanrong Datasystem 配置
export DS_WORKER_ADDR="${local_ip}:18481"
export DS_H2D_MEMCPY_POLICY="direct"
export DS_D2H_MEMCPY_POLICY="direct"
unset GOOGLE_LOGTOSTDERR GOOGLE_ALSOLOGTOSTDERR
MODEL_PATH="/home/models/GLM-5-w4a8"
vllm serve $MODEL_PATH \
--host <IP_ADDRESS> \
--port 1026 \
--headless \
--data-parallel-size 2 \
--data-parallel-size-local 1 \
--data-parallel-start-rank 1 \
--data-parallel-address $node0_ip \
--data-parallel-rpc-port 12890 \
--tensor-parallel-size 8 \
--quantization ascend \
--seed 1024 \
--served-model-name glm-5 \
--enable-expert-parallel \
--max-num-seqs 40 \
--max-model-len 202752 \
--max-num-batched-tokens 4096 \
--trust-remote-code \
--gpu-memory-utilization 0.92 \
--enable-chunked-prefill \
--enable-prefix-caching \
--async-scheduling \
--enable-auto-tool-choice \
--tool-call-parser glm47 \
--reasoning-parser glm45 \
--additional-config '{"multistream_overlap_shared_expert":true, "fuse_qknorm_rope": false, "fuse_muls_add": true, "enable_npugraph_ex": true}' \
--compilation-config '{"cudagraph_capture_sizes": [1,4,8,12,16,20,24,28,32,36,40,48,56,64,80,96], "cudagraph_mode": "FULL_DECODE_ONLY"}' \
--speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp"}' \
--kv-transfer-config '{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {
"lookup_rpc_port": "1",
"backend": "yuanrong"
}
}' 2>&1 | tee ./glm-5_yuanrong_a2_node1.log
配置参数说明¶
A3 单机参数¶
参数 |
值 |
说明 |
|---|---|---|
tensor-parallel-size |
8 |
单实例使用 8 路张量并行 |
data-parallel-size |
2 |
单机内数据并行大小 |
max-model-len |
202752 |
最大上下文长度 |
max-num-batched-tokens |
8192 |
最大批处理 token 数 |
max-num-seqs |
48 |
最大并发序列数 |
gpu-memory-utilization |
0.92 |
GPU 显存利用率 |
quantization |
ascend |
使用 Ascend 量化 |
enable-expert-parallel |
(标志) |
启用 MoE 专家并行 |
enable-chunked-prefill |
(标志) |
启用分块预填充 |
enable-prefix-caching |
(标志) |
启用前缀缓存 |
async-scheduling |
(标志) |
启用异步调度 |
enable-auto-tool-choice |
(标志) |
启用自动工具选择 |
tool-call-parser |
glm47 |
工具调用解析器 |
reasoning-parser |
glm45 |
reasoning 解析器 |
kv_connector |
AscendStoreConnector |
使用 AscendStoreConnector |
kv_role |
kv_both |
同时支持生产和消费 |
backend |
yuanrong |
使用 openYuanrong 后端 |
lookup_rpc_port |
0 |
RPC 查找端口 |
A2 双机参数¶
参数 |
值 |
说明 |
|---|---|---|
tensor-parallel-size |
8 |
每节点使用 8 张 NPU 卡 |
data-parallel-size |
2 |
数据并行大小(2 节点) |
data-parallel-size-local |
1 |
本地数据并行大小 |
max-model-len |
202752 |
最大上下文长度 |
max-num-batched-tokens |
4096 |
最大批处理 token 数 |
max-num-seqs |
40 |
最大并发序列数 |
gpu-memory-utilization |
0.92 |
GPU 显存利用率 |
quantization |
ascend |
使用 Ascend 量化 |
enable-expert-parallel |
(标志) |
启用 MoE 专家并行 |
enable-auto-tool-choice |
(标志) |
启用自动工具选择 |
tool-call-parser |
glm47 |
工具调用解析器 |
reasoning-parser |
glm45 |
reasoning 解析器 |
lookup_rpc_port (node0) |
0 |
节点 0 RPC 查找端口 |
lookup_rpc_port (node1) |
1 |
节点 1 RPC 查找端口 |
环境变量说明¶
环境变量 |
值 |
说明 |
|---|---|---|
|
AIV |
HCCL 算子扩展模式(AI Vector 优化) |
|
false |
OpenMP 线程绑定配置 |
|
示例中为 10 |
OpenMP 线程数 |
|
示例中为 256 |
HCCL 缓冲区大小 |
|
expandable_segments:True |
NPU 显存分配策略(减少碎片) |
|
1 |
启用平衡调度 |
|
1 |
启用 vLLM v1 架构 |
|
1800 |
引擎就绪超时时间(秒) |
|
0 |
Python 哈希种子,确保 KV Cache 键一致性 |
|
|
openYuanrong Worker 地址,必须与当前节点 |
|
direct |
Host-to-Device 内存拷贝策略 |
|
direct |
Device-to-Host 内存拷贝策略 |
功能验证¶
服务启动后,验证部署是否成功。可先按部署场景设置服务端口:
# A3 单机示例
SERVICE_PORT=8077
# A2 双机通常验证节点 0
# SERVICE_PORT=1025
测试推理¶
curl -H "Accept: application/json" \
-H "Content-type: application/json" \
-X POST \
-d '{
"model": "glm-5",
"messages": [{
"role": "user",
"content": "你好,请介绍一下人工智能的未来发展趋势。"
}],
"stream": false,
"ignore_eos": false,
"temperature": 0,
"max_tokens": 200
}' http://localhost:$SERVICE_PORT/v1/chat/completions
缓存命中率监控¶
查看 vLLM 日志¶
日志文件命名格式:
A3 单机:
glm-5_yuanrong_a3.logA2 双机节点 0:
glm-5_yuanrong_a2_node0.logA2 双机节点 1:
glm-5_yuanrong_a2_node1.log
# A3 可设为 glm-5_yuanrong_a3.log
# A2 节点 0 / 节点 1 分别设为 glm-5_yuanrong_a2_node0.log / glm-5_yuanrong_a2_node1.log
LOG_FILE=glm-5_yuanrong_a3.log
# 查看最新日志
tail -f $LOG_FILE
# 实时监控命中率相关日志
tail -f $LOG_FILE | grep -E "Prefix cache hit rate|External prefix cache hit rate|num_computed_tokens"
使用脚本持续监控命中率¶
如果当前环境包含 vllm-ascend 仓库源码,也可以直接使用仓库自带脚本持续观测命中率:
# 在 vllm-ascend 仓库根目录执行
bash tools/watch_cache_hit_rate.sh -u http://localhost:$SERVICE_PORT/metrics -i 10
# 如需将结果同时保存到文件
bash tools/watch_cache_hit_rate.sh \
-u http://localhost:$SERVICE_PORT/metrics \
-i 10 \
-o cache_hit_rate.log
脚本会同时输出每个 engine 以及汇总行 all 的命中率,常用字段如下:
local_win:vLLM 本地 Prefix Cache 的窗口命中率local_total:vLLM 本地 Prefix Cache 的累计命中率ext_win:openYuanrong 外部 KV Cache 的窗口命中率ext_total:openYuanrong 外部 KV Cache 的累计命中率eff_total:综合本地和外部缓存后的端到端有效命中率
缓存命中率指标说明¶
指标 |
说明 |
统计方式 |
|---|---|---|
Prefix cache hit rate |
**HBM(本地显存)**命中率 |
滑动窗口:最近 1000 个请求 |
External prefix cache hit rate |
**openYuanrong(外部 KV Cache)**命中率 |
累计统计:从服务启动到当前时刻 |
TTFT (Time to First Token) |
首个 token 延迟 |
单次请求指标,命中率高时 TTFT 显著降低 |
统计周期说明:
Prefix cache hit rate:对应 HBM / 本地 Prefix Cache 命中率,来自 vLLM 上游CachingMetrics模块,使用滑动窗口统计最近 1000 个请求External prefix cache hit rate:对应 openYuanrong 外部 KV Cache 命中率,来自 Prometheus Counter 指标,累计统计从服务启动到当前时刻的总命中数和查询数日志每 10 秒 输出一次 HBM 命中率
HBM 命中率计算公式:
hit_rate = window_hits / window_queriesopenYuanrong 命中率计算公式:
hit_rate = total_hits / total_queries
查看 openYuanrong 外部缓存命中率:
# 通过 Prometheus metrics 查看外部缓存统计
curl http://localhost:$SERVICE_PORT/metrics | grep external_prefix_cache
# 输出示例:
# vllm:external_prefix_cache_queries_total{...} 10000
# vllm:external_prefix_cache_hits_total{...} 8500
# 命中率 = hits / queries = 85%
注意:外部缓存指标为 Prometheus Counter 类型,表示从服务启动以来的累计值。
如何查看单次请求是否命中:
# 查看单个请求的缓存命中情况
grep "num_computed_tokens" $LOG_FILE
# 如果 num_computed_tokens > 0,表示该请求命中了缓存
# num_computed_tokens 表示从缓存中复用的 token 数量
性能测试¶
选项一:快速测试¶
使用 vllm bench serve 对已启动的 OpenAI 兼容服务进行快速压测。下面示例默认以本机服务为目标:
BENCH_HOST=<IP_ADDRESS>
BENCH_PORT=1025
TOKENIZER_PATH=/home/models/GLM-5-w4a8
vllm bench serve \
--backend openai-chat \
--endpoint /v1/chat/completions \
--dataset-name prefix_repetition \
--prefix-repetition-prefix-len 31744 \
--prefix-repetition-suffix-len 1024 \
--prefix-repetition-output-len 2048 \
--num-prompts 100 \
--prefix-repetition-num-prefixes 5 \
--ignore-eos \
--model glm-5 \
--tokenizer $TOKENIZER_PATH \
--seed 1000 \
--host $BENCH_HOST \
--port $BENCH_PORT \
--max-concurrency 10
参数含义如下:
参数 |
含义 |
|---|---|
|
按 OpenAI Chat Completions 接口格式发请求 |
|
指定压测目标接口路径 |
|
使用前缀重复数据集,便于观察缓存收益 |
|
共享前缀长度 |
|
每条请求的独立后缀长度 |
|
生成输出长度 |
|
总请求数 |
|
共享前缀模板数量 |
|
忽略 EOS,尽量生成到目标长度 |
|
请求时使用的模型名,需要与服务端 |
|
tokenizer 路径,需指向本地 GLM-5 W4A8 模型目录 |
|
固定随机种子,便于复现 |
|
压测目标地址 |
|
压测目标端口;A2 示例通常为 |
|
最大并发请求数 |
选项二:深度测试¶
使用 AISBench 进行深度性能测试:
ais_bench --models vllm_api_stream_chat \
--datasets gsm8k_gen_0_shot_cot_str_perf \
--debug --summarizer default_perf --mode perf
故障排除¶
常见问题¶
etcd 连接失败
确保 etcd 正在运行且可访问:
etcdctl --endpoints "${ETCD_IP}:2379" endpoint health
Worker 注册失败
检查 Worker 地址是否正确配置:
netstat -tlnp | grep 18481
KV Cache 未找到
验证
PYTHONHASHSEED设置一致:
echo $PYTHONHASHSEED
yr.datasystem 导入错误
确保
openyuanrong-datasystem已安装:
pip install openyuanrong-datasystem
python -c "from yr.datasystem.hetero_client import HeteroClient; print('OK')"
64 KB 页大小机器无法直接使用默认 openYuanrong 安装包
openYuanrong 默认提供的是面向 4 KB 内存页大小机器的安装包。如果目标机器使用 64 KB 页大小,则需要使用额外编译的安装包,默认包可能无法正常安装或运行。
可先检查页大小:
getconf PAGE_SIZE
如果输出为 65536,请使用针对 64 KB 页大小单独编译的 openYuanrong 安装包。
引擎启动超时
增加
VLLM_ENGINE_READY_TIMEOUT_S的值:
export VLLM_ENGINE_READY_TIMEOUT_S=3600
双机节点时间不一致
A2 双机场景下,建议两个节点的系统时间保持一致,否则可能影响日志对齐、问题定位以及部分依赖时间戳的排障判断。
可分别在两个节点检查时间:
date
timedatectl
日志查看¶
查看 vLLM 日志以获取详细错误信息:
tail -f $LOG_FILE