vLLM Ascend使用OpenYuanrong作为多级缓存最佳实践

背景介绍

本指南以 GLM-5 模型部署为例,提供在 Atlas 800T/I A2 服务器(双机)或 Atlas 800T/I A3 服务器(单机)上使用 Yuanrong Datasystem 作为 KV Cache 多级缓存后端的详细部署步骤。

GLM-5 是采用混合专家架构的高效推理模型,专为复杂系统工程和长时序智能体任务设计。使用 Yuanrong 作为 KV Pool 后端可以实现高效的 KV Cache 存储和请求间的复用。 Yuanronng 部署架构图

部署环境准备

GLM-5 单实例部署所需的软硬件环境依赖如下:

软硬件名称

版本/规格

作用

Atlas 800T/I A3(单机)

16张NPU卡(每张64G显存)

运行异构大模型推理的物理硬件,需已配置 RoCE 网络以获得最佳性能

vllm-ascend Docker 镜像

“vllm-ascend:0.18.0rc1”

提供包含 vLLM、CANN 等预配置的容器运行环境

GLM-5 模型

-

智能体应用设计的高效推理模型权重

openYuanrong datasystem

-

提供 KV Cache 外部存储与复用的核心组件

etcd

3.5

Datasystem 集群与节点管理依赖组件

软硬件名称

版本/规格

作用

Atlas 800T/I A2(双机)

8张NPU卡(每张64G显存)

运行异构大模型推理的物理硬件,需已配置 RoCE 网络以获得最佳性能

vllm-ascend Docker 镜像

“vllm-ascend:0.18.0rc1”

提供包含 vLLM、CANN 等预配置的容器运行环境

GLM-5 模型

-

智能体应用设计的高效推理模型权重

openYuanrong datasystem

-

提供 KV Cache 外部存储与复用的核心组件

etcd

3.5

Datasystem 集群与节点管理依赖组件

下面给出以上依赖的获取与环境准备方法。

获取与运行基础环境

1. 准备模型权重

下载 GLM-5 W4A8 模型权重并放置到宿主机指定目录,例如 /home/models/GLM-5-w4a8/。 下载地址:魔搭社区

# 下载命令
pip install modelscope
modelscope download --model Eco-Tech/GLM-5-w4a8 --local_dir /home/models

2. 下载 Docker 镜像

本教程使用的 Docker 镜像版本为 ‘vllm-ascend:0.18.0rc1’。

版本兼容性说明: 请确保vLLM-ascend镜像版本不低于0.18.0rc1。在版本及后续版本中,系统已支持Yuanrong Datasystem作为多级缓存后端。

如本地尚未下载,可按机器类型执行如下命令:

docker pull quay.io/ascend/vllm-ascend:0.18.0rc1
docker pull quay.io/ascend/vllm-ascend:0.18.0rc1-a3

提示:如果下载较慢,可将 quay.io 替换为 m.daocloud.io/quay.io 或 quay.nju.edu.cn 以加速拉取。

3. 启动 Docker 容器

在两个节点上分别启动包含 8 张 NPU 卡的 Docker 容器:

export IMAGE=quay.io/ascend/vllm-ascend:0.18.0rc1
export NAME=vllm-ascend

docker run --rm \
    --name $NAME \
    --shm-size=1g \
    --net=host \
    --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/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

启动包含 16 张 NPU 卡的 Docker 容器:

export IMAGE=quay.io/ascend/vllm-ascend:0.18.0rc1-a3
export NAME=vllm-ascend

docker run --rm \
    --name $NAME \
    --shm-size=1g \
    --net=host \
    --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 \
    -v /root/.cache:/root/.cache \
    -it $IMAGE bash

安装 openYuanrong datasystem

根据部署环境的网络情况,选择在线或离线安装方式。

在线安装

pip install openyuanrong-datasystem

离线安装

离线安装请参考安装指南

验证安装:

python -c "import yr.datasystem; print('Yuanrong Datasystem 安装成功')"

部署openYuanrong datasystem

本教程为单实例部署方式,etcd 和 Datasystem Worker 均在 vLLM-Ascend 容器内启动。

启动 Yuanrong 服务

在每个节点上部署都需要启动 etcd 和 Datasystem Worker,如果是双机部署需要连接同一个etcd。

创建启动脚本 run_yr.sh

#!/bin/bash

# 配置参数
export HOST_IP="<您的节点IP地址>"
export ETCD_IP="${HOST_IP}"
export WORKER_PORT=18481
export ETCD_PORT="${ETCD_PORT}"
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://0.0.0.0:${ETCD_PORT} \
  --advertise-client-urls http://${ETCD_IP}:${ETCD_PORT} \
  --listen-peer-urls http://0.0.0.0: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}:${ETCD_PORT}" put key "value"
etcdctl --endpoints "${ETCD_IP}:${ETCD_PORT}" 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"

如果想要使用多副本模式启动etcd:

运行脚本:

bash run_yr.sh

参考文档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} (600)

节点超时时间(秒)

node_dead_timeout_s

${NODE_DEAD_TIMEOUT} (600000)

节点死亡超时时间(毫秒)

liveness_check_path

${LIVENESS_PATH}

存活检查路径

参考文档Yuanrong Datasystem 文档,了解更多 worker 参数和环境变量配置。

停止 Worker:

dscli stop --worker_address ${HOST_IP}:${WORKER_PORT}

部署 GLM-5 模型

创建启动脚本 run_glm5_w4a8_yuanrong_a3.sh

#!/bin/bash

# NPU 性能优化配置
export HCCL_OP_EXPANSION_MODE="AIV"
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=1
export HCCL_BUFFSIZE=200
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

# Yuanrong 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="/home/models/GLM-5-w4a8"

vllm serve $MODEL_PATH \
  --host 0.0.0.0 \
  --port 1025 \
  --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 200000 \
  --max-num-batched-tokens 4096 \
  --trust-remote-code \
  --gpu-memory-utilization 0.95 \
  --quantization ascend \
  --enable-chunked-prefill \
  --enable-prefix-caching \
  --async-scheduling \
  --additional-config '{"multistream_overlap_shared_expert":true}' \
  --speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp"}' \
  --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
  --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.log

在两个节点上分别创建启动脚本。

节点 0 创建 run_glm5_w4a8_yuanrong_a2_node0.sh

#!/bin/bash

# 网络配置 - 根据实际环境修改
nic_name="bond0"
local_ip="100.100.135.173"
node0_ip="100.100.135.173"

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=1
export HCCL_BUFFSIZE=200
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

# Yuanrong 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 0.0.0.0 \
  --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 2 \
  --max-model-len 131072 \
  --max-num-batched-tokens 4096 \
  --trust-remote-code \
  --gpu-memory-utilization 0.95 \
  --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
  --additional-config '{"multistream_overlap_shared_expert":true}' \
  --speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp"}' \
  --enable-chunked-prefill \
  --enable-prefix-caching \
  --async-scheduling \
  --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.log

节点 1 创建 run_glm5_w4a8_yuanrong_a2_node1.sh

#!/bin/bash

# 网络配置 - 根据实际环境修改
nic_name="enp61s0f2"
local_ip="100.100.135.190"
node0_ip="100.100.135.173"

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=1
export HCCL_BUFFSIZE=200
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

# Yuanrong 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 0.0.0.0 \
  --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 2 \
  --max-model-len 131072 \
  --max-num-batched-tokens 4096 \
  --trust-remote-code \
  --gpu-memory-utilization 0.95 \
  --compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
  --additional-config '{"multistream_overlap_shared_expert":true}' \
  --speculative-config '{"num_speculative_tokens": 3, "method": "deepseek_mtp"}' \
  --enable-chunked-prefill \
  --enable-prefix-caching \
  --async-scheduling \
  --kv-transfer-config '{
      "kv_connector": "AscendStoreConnector",
      "kv_role": "kv_both",
      "kv_connector_extra_config": {
          "lookup_rpc_port": "1",
          "backend": "yuanrong"
      }
  }' 2>&1 | tee -a ./glm-5_yuanrong.log

配置参数说明

参数

说明

tensor-parallel-size

16

使用 16 张 NPU 卡

data-parallel-size

1

数据并行大小

max-model-len

200000

最大上下文长度

max-num-batched-tokens

4096

最大批处理 token 数

max-num-seqs

8

最大并发序列数

gpu-memory-utilization

0.95

GPU 显存利用率

quantization

ascend

使用 Ascend 量化

enable-expert-parallel

(标志)

启用 MoE 专家并行

enable-chunked-prefill

(标志)

启用分块预填充

enable-prefix-caching

(标志)

启用前缀缓存

async-scheduling

(标志)

启用异步调度

kv_connector

AscendStoreConnector

使用 AscendStoreConnector

kv_role

kv_both

同时支持生产和消费

backend

yuanrong

使用 Yuanrong 后端

lookup_rpc_port

0

RPC 查找端口

参数

说明

tensor-parallel-size

8

每节点使用 8 张 NPU 卡

data-parallel-size

2

数据并行大小(2 节点)

data-parallel-size-local

1

本地数据并行大小

max-model-len

131072

最大上下文长度

max-num-batched-tokens

4096

最大批处理 token 数

max-num-seqs

2

最大并发序列数

gpu-memory-utilization

0.95

GPU 显存利用率

quantization

ascend

使用 Ascend 量化

enable-expert-parallel

(标志)

启用 MoE 专家并行

lookup_rpc_port (node0)

0

节点 0 RPC 查找端口

lookup_rpc_port (node1)

1

节点 1 RPC 查找端口

环境变量说明

环境变量

说明

HCCL_OP_EXPANSION_MODE

AIV

HCCL 算子扩展模式(AI Vector 优化)

OMP_PROC_BIND

false

OpenMP 线程绑定配置

OMP_NUM_THREADS

1

OpenMP 线程数

HCCL_BUFFSIZE

200

HCCL 缓冲区大小

PYTORCH_NPU_ALLOC_CONF

expandable_segments:True

NPU 显存分配策略(减少碎片)

VLLM_ASCEND_BALANCE_SCHEDULING

1

启用平衡调度

VLLM_USE_V1

1

启用 vLLM v1 架构

VLLM_ENGINE_READY_TIMEOUT_S

1800

引擎就绪超时时间(秒)

PYTHONHASHSEED

0

Python 哈希种子,确保 KV Cache 键一致性

DS_WORKER_ADDR

${HOST_IP}:18481

Yuanrong Worker 地址,必须与 dscli 启动参数一致

DS_H2D_MEMCPY_POLICY

direct

Host-to-Device 内存拷贝策略

DS_D2H_MEMCPY_POLICY

direct

Device-to-Host 内存拷贝策略

对于 Ascend A2 同节点、大量 KV Block 的本地 H2D,保持 DS_H2D_MEMCPY_POLICY=direct,并将 DS_H2D_PARALLEL_WORKER_NUM 设置为大于 1 可实验性地启用 Direct 描述符并行。该模式保持同步接口语义, 将描述符聚合后交给每 Device 的有界线程池并行执行。相关调优变量如下:

环境变量

默认值

说明

DS_H2D_PARALLEL_WORKER_NUM

1

每 Device H2D Worker 数,范围 [1, 16]1 表示串行

DS_H2D_PARALLEL_AGGREGATE_NUM

512

每个 ACL Batch 的描述符数,范围 [1, 4096]

DS_H2D_PARALLEL_MAX_PENDING_TASK_NUM

2 * worker_num

每 Device 的有界等待队列长度,最大 64

DS_H2D_PARALLEL_MIN_BYTES

25165824

低于该总字节数(24 MiB)时回退为串行 Direct

DS_H2D_PARALLEL_MAX_INFLIGHT_BATCH_NUM

worker_num + 1

Worker 与 caller-runs 合计 ACL 并发上限

只有估算出的 ACL Batch 任务数不少于 Worker 数时才会进入并行路径,任务会按累计字节数尽量均衡切分;否则回退为串行 Direct。该能力默认不启用。需要回滚时将 DS_H2D_PARALLEL_WORKER_NUM 恢复为 1

FFTS/Huge FFTS 也支持实验性的对象级并行。保持 DS_H2D_MEMCPY_POLICY=ffts;启用 HugeTLB 时仍由现有逻辑自动 切换为 Huge FFTS,再通过以下变量开启多个独立 FFTS pipeline:

环境变量

默认值

说明

DS_H2D_FFTS_PARALLEL_WORKER_NUM

4

FFTS H2D Worker 数,范围 [1, 16]1 表示关闭并行

DS_H2D_FFTS_PARALLEL_MIN_BYTES

134217728

低于该总字节数(128 MiB)时使用原串行 FFTS

并行路径按完整对象进行字节均衡分片,每个分片独立持有 dispatcher、stream、notify 和两份 device staging buffer, 不会拆分同一对象的 Blob。进入并行前会校验所有分片的 device staging 总预算;超过 DS_DEVICE_ACL_SIZE 时自动使用 原串行 FFTS,避免并发分配导致 OOM。启用并行 FFTS 后,同一客户端进程中的 FFTS H2D 调用会通过调用级互斥串行进入, 因此最多只有一个调用持有 staging 资源,单次调用最多提交 worker_num 个任务。 需要回滚时将 DS_H2D_FFTS_PARALLEL_WORKER_NUM=1。是否真正进入并行路径,应在客户端性能日志中确认 TOTAL_H2D_PARALLEL_FFTS_MEMCPY,仅出现 ParallelFftsH2DConfig 只能证明配置已加载。

D2H Set 并行拷贝配置

MSetD2H 的 Direct 和 FFTS 路径支持独立的 D2H 并行配置,不与 H2D Get 参数共用。保持 DS_D2H_MEMCPY_POLICY=direct,并将 DS_D2H_PARALLEL_WORKER_NUM 设置为大于 1 可启用 Direct 描述符并行。 参数及默认值如下:

环境变量

默认值

说明

DS_D2H_PARALLEL_WORKER_NUM

1

每个 Device 的 D2H Worker 数,范围 [1, 16]1 表示串行

DS_D2H_PARALLEL_AGGREGATE_NUM

512

每个 ACL Batch 的描述符数,范围 [1, 4096]

DS_D2H_PARALLEL_MAX_PENDING_TASK_NUM

2 * worker_num

有界等待队列长度,最大 64

DS_D2H_PARALLEL_MIN_BYTES

25165824

请求小于该字节数时回退串行 Direct

DS_D2H_PARALLEL_MAX_INFLIGHT_BATCH_NUM

worker_num + 1

Worker 与 caller-runs 的 ACL 并发上限

FFTS/Huge FFTS 保持 DS_D2H_MEMCPY_POLICY=ffts,通过下列变量启用对象级并行:

环境变量

默认值

说明

DS_D2H_FFTS_PARALLEL_WORKER_NUM

4

FFTS D2H Worker 数,范围 [1, 16]1 表示串行

DS_D2H_FFTS_PARALLEL_MIN_BYTES

50331648

请求小于该字节数(48 MiB)时使用串行 FFTS

D2H FFTS 仅按完整对象分片,不拆分同一对象的 Blob。并发分片独占正在使用的 stream、notify、FFTS context 和 staging buffer;调用结束且 stream 同步成功后,dispatcher/context、两条 stream 和四个 notify 作为一个控制资源 bundle 返回每 Device 缓存,staging buffer 按容量独立复用。Huge FFTS 直接写入 目标 HugeTLB Buffer,不提交 callback 或 H2H future。总 device staging 预算超过 DS_DEVICE_ACL_SIZE 时自动使用 串行 FFTS。Direct 并行回滚时将 DS_D2H_PARALLEL_WORKER_NUM=1;FFTS 并行回滚时将 DS_D2H_FFTS_PARALLEL_WORKER_NUM=1。运行时应分别通过 TOTAL_D2H_PARALLEL_MEMCPYTOTAL_D2H_PARALLEL_FFTS_MEMCPY 确认并行路径实际执行。

FFTS staging 内存与显存预算

DS_HOST_ACL_SIZEDS_DEVICE_ACL_SIZE 配置的是当前客户端进程的 FFTS staging 内存池,不包含业务侧原始 Host Buffer,也不包含最终存放 KV Cache 的 NPU Buffer。两个变量的默认值分别为 2684354560 字节(2.5 GiB) 和 104857600 字节(100 MiB)。

设一次请求包含的对象大小为 S[j]。并行分片数 k = min(worker_num, object_count),第 i 个分片中最大对象的大小为 M[i],则单次 FFTS 调用的 staging 预算如下:

资源

串行 FFTS

并行 FFTS

说明

Device 显存池

2 * max(S[j])

2 * sum(M[i]), i=0..k-1

每条 pipeline 有两份 Device staging buffer;并行预算上界为 2 * k * max(S[j])

Host 锁页内存池

sum(S[j])

sum(S[j])

普通 FFTS 为每个完整对象分配一份 Host staging buffer;分片不会重复对象数据

例如 4 个并行分片的最大对象分别为 8 MiB、7 MiB、6 MiB 和 5 MiB,则需要的 Device staging 显存为 2 * (8 + 7 + 6 + 5) = 52 MiB。如果一次请求的所有对象合计为 80 MiB,普通 FFTS 还需要约 80 MiB 的 Host 锁页内存。配置时还需为内存池中的其他并发方向、分配对齐和碎片预留余量;H2D 与 D2H 同时执行时,两边的 staging 占用需要相加。

并行执行前会按实际分片计算 Device staging 预算。预算大于 DS_DEVICE_ACL_SIZE 时自动使用串行 FFTS; 串行路径仍至少需要 2 * max(S[j]) 的 Device staging 显存。普通 FFTS 的 Host staging 分配失败时, D2H 返回 OOM,H2D 会回退 Direct。只有 H2D、D2H 都进入 Huge FFTS 时,才会直接复用调用方的 HugeTLB Host Buffer,此时不分配内部 Host staging 池,DS_HOST_ACL_SIZE 可为 0

功能验证

服务启动后,验证部署是否成功:

检查服务状态

curl http://localhost:1025/health

测试推理

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:1025/v1/chat/completions

测试 KV Cache 复用

发送相同的提示词两次,验证 KV Cache 是否被复用:

# 第一次请求 - 填充 KV Cache
curl -H "Accept: application/json" \
    -H "Content-type: application/json" \
    -X POST \
    -d '{
        "model": "glm-5", 
        "messages": [{ 
            "role": "user", 
            "content": "请详细解释机器学习的概念和基本原理。" 
        }], 
        "stream": false, 
        "temperature": 0, 
        "max_tokens": 100 
    }' http://localhost:1025/v1/chat/completions

# 第二次请求 - 命中 KV Cache(TTFT 更快)
curl -H "Accept: application/json" \
    -H "Content-type: application/json" \
    -X POST \
    -d '{
        "model": "glm-5", 
        "messages": [{ 
            "role": "user", 
            "content": "请详细解释机器学习的概念和基本原理。" 
        }], 
        "stream": false, 
        "temperature": 0, 
        "max_tokens": 100 
    }' http://localhost:1025/v1/chat/completions

缓存命中率监控

查看 vLLM 日志

日志文件命名格式:glm-5_yuanrong.log

# 查看最新日志
tail -f glm-5_yuanrong.log

# 实时监控关键指标
tail -f glm-5_yuanrong.log | grep -E "hit_rate|cache|KV"

查看 Prefix Cache 命中率

vLLM 内置的 prefix cache 命中率统计:

# 方法一:通过日志查看
grep -E "prefix cache hit|cache hit rate" glm-5_yuanrong.log

# 方法二:通过 metrics API 查看(如果启用了)
curl http://localhost:1025/metrics | grep -E "vllm_prefix_cache|cache_hit"

查看 Yuanrong KV Cache 命中率

Yuanrong 后端的缓存命中率通过日志输出:

# 查看 Yuanrong 相关日志
grep -E "yuanrong|YuanrongBackend|kv_cache|hit_rate" glm-5_yuanrong.log

# 查看详细的缓存操作日志
grep -E "get|put|exists|HeteroClient" glm-5_yuanrong.log

缓存命中率指标说明

指标

说明

统计方式

Prefix Cache Hit Rate

**HBM(本地显存)**命中率

滑动窗口:最近 1000 个请求

External Cache Hit Rate

**Yuanrong(外部 KV Cache)**命中率

累计统计:从服务启动到当前时刻

TTFT (Time to First Token)

首个 token 延迟

单次请求指标,命中率高时 TTFT 显著降低

统计周期说明

  • HBM 命中率:来自 vLLM 上游 CachingMetrics 模块,使用滑动窗口统计最近 1000 个请求

  • Yuanrong 命中率:来自 Prometheus Counter 指标,累计统计从服务启动到当前时刻的总命中数和查询数

  • 日志每 10 秒 输出一次 HBM 命中率

  • HBM 命中率计算公式:hit_rate = window_hits / window_queries

  • Yuanrong 命中率计算公式:hit_rate = total_hits / total_queries

查看 Yuanrong 外部缓存命中率

# 通过 Prometheus metrics 查看外部缓存统计
curl http://localhost:1025/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" glm-5_yuanrong.log

# 如果 num_computed_tokens > 0,表示该请求命中了缓存
# num_computed_tokens 表示从缓存中复用的 token 数量

使用 Prometheus 监控(可选)

如果需要持续监控,可以启用 vLLM 的 Prometheus metrics:

# 启动时添加 metrics 端口
vllm serve ... --enable-metrics --metrics-port 8001

然后通过 Prometheus 抓取 http://localhost:8001/metrics

性能测试

选项一:快速测试

使用 vLLM Benchmark 进行快速性能测试:

vllm bench serve \
  --backend vllm \
  --dataset-name prefix_repetition \
  --prefix-repetition-prefix-len 8192 \
  --prefix-repetition-suffix-len 1024 \
  --prefix-repetition-output-len 256 \
  --num-prompts 10 \
  --prefix-repetition-num-prefixes 5 \
  --ignore-eos \
  --model glm-5 \
  --tokenizer /home/models/GLM-5-w4a8 \
  --seed 1000 \
  --host 0.0.0.0 \
  --port 1025 \
  --endpoint /v1/completions \
  --max-concurrency 4 \
  --request-rate 1

选项二:深度测试

使用 AISBench 进行深度性能测试:

ais_bench --models vllm_api_stream_chat \
  --datasets gsm8k_gen_0_shot_cot_str_perf \
  --debug --summarizer default_perf --mode perf

故障排除

常见问题

  1. etcd 连接失败

    确保 etcd 正在运行且可访问:

    etcdctl --endpoints "${ETCD_IP}:2379" endpoint health
    
  2. Worker 注册失败

    检查 Worker 地址是否正确配置:

    netstat -tlnp | grep 18481
    
  3. KV Cache 未找到

    验证 PYTHONHASHSEED 设置一致:

    echo $PYTHONHASHSEED
    
  4. yr.datasystem 导入错误

    确保 openyuanrong-datasystem 已安装:

    pip install openyuanrong-datasystem
    python -c "from yr.datasystem.hetero_client import HeteroClient; print('OK')"
    
  5. 内存不足(OOM)

    降低 --max-num-seqs--max-model-len

    --max-model-len 65536 \
    --max-num-seqs 4
    
  6. FIA 算子性能问题

    执行 FIA 算子替换脚本:

    # A2 系列
    bash tools/install_flash_infer_attention_score_ops_a2.sh
    
    # A3 系列
    bash tools/install_flash_infer_attention_score_ops_a3.sh
    
  7. 多节点通信失败

    检查网络配置:

    # 确认网卡名称和 IP 地址正确
    ifconfig
    
    # 检查 HCCL 通信
    export HCCL_DETERMINISTIC=1
    
  8. 引擎启动超时

    增加 VLLM_ENGINE_READY_TIMEOUT_S 的值:

    export VLLM_ENGINE_READY_TIMEOUT_S=3600
    

日志查看

查看 vLLM 日志以获取详细错误信息:

tail -f glm-5_yuanrong.log

参考资料