KV Cache Pool(Ascend Store)部署指南¶
1. 环境依赖¶
- 软件:
- CANN >= 8.5.0
- vLLM:main 分支
- vLLM-Ascend:main 分支
- mooncake:>= 0.3.11.post1
KV Pool 参数说明¶
kv_load_failure_policy:KV 加载失败处理策略¶
kv_load_failure_policy 是 kv-transfer-config 中的顶层字段。
recompute:当 KV 加载失败时,vLLM 会将请求回滚到最后一个有效前缀,并重新调度以重新计算失败的 KV 块。混合注意力模型(例如 DeepSeekV4、Qwen 3.5)目前尚不支持。fail:当 KV 加载失败时,受影响的请求会直接以错误终止。
vLLM 中的默认值为 fail。如果希望请求在 KV 加载失败后回退到重新计算,请将其设置为 recompute。
当使用 MultiConnector 时,应在 MultiConnector 的顶层 kv-transfer-config 上配置 kv_load_failure_policy,而不是在子连接器上配置。
kv_connector_extra_config:池化的其他可配置参数¶
| 参数 | 描述 |
|---|---|
lookup_rpc_port |
池化调度器进程与 Worker 进程之间 RPC 通信的端口:每个实例都需要唯一的端口配置。 |
load_async |
是否启用异步加载。默认值为 false。 |
backend |
设置 kvpool 的存储后端(mooncake、memcache、yuanrong),默认为 mooncake。 |
consumer_is_to_put |
Decode 节点是否将 KV Cache 写入 KV Pool。默认值为 false。 |
consumer_is_to_load |
Decode 节点是否从 KV Pool 加载 KV Cache。默认值为 false。 |
use_layerwise |
启用逐层 KV 保存/加载。仅支持 Prefill 节点,并且需要 memcache 后端。默认值为 false。 |
prefill_pp_size |
Prefill PP 大小,当 Prefill 节点启用 PP 时需要设置。 |
prefill_pp_layer_partition |
Prefill PP 层分区,当 Prefill 节点启用 PP 时需要设置。 |
qos_priority |
KV pool 传输 QoS 优先级,为 [0, 4] 中的整数(值越大,优先级越高)。 |
环境变量配置¶
为保证哈希生成的一致性,启用 KV Pool 时需要在所有节点上同步 PYTHONHASHSEED 环境变量。
2. 使用 Mooncake 作为 KV Pool 后端的示例¶
步骤 2.1:软件安装¶
-
软件:
- 检查配置:
确保环境中存在 hccn.conf 文件。如果使用 Docker,请将其挂载到容器中。
对于 950PR&950DT 产品,还需额外挂载:
- 设备:
/dev/ummu、/dev/uburma - 命令:
/usr/bin/urma_admin - 配置:
/lib/route.conf、/etc/hccl_rootinfo.json - 安装 Mooncake
Mooncake 是 Moonshot AI 提供的领先大语言模型服务 Kimi 的服务平台。 Mooncake 的 wheel 包需要 glibc 2.35 或更高版本。安装前请检查已安装的 glibc 版本:
使用 pip 安装 Mooncake:
python3 -m pip install mooncake-transfer-engine-npu==0.3.11.post1 --extra-index-url https://mirrors.aliyun.com/pypi/web/simple当
tenant_id被省略或解析为default时,Mooncake0.3.11.post1仍受支持。非默认租户需要其MooncakeDistributedStore.setup()接受tenant_id的 Mooncake 版本;多租户部署请使用 Mooncake0.3.12或更高版本。
步骤 2.2:运行 Mooncake Master¶
注意: 在继续之前,请查阅以下 Mooncake 指南:
步骤 2.2.1:配置 mooncake.json¶
环境变量 MOONCAKE_CONFIG_PATH 应配置为 mooncake.json 所在位置的完整路径。
{
"metadata_server": "P2PHANDSHAKE",
"protocol": "ascend",
"device_name": "",
"master_server_address": "xx.xx.xx.xx:50088",
"global_segment_size": "1GB" (1024MB/1048576KB/1073741824B/1073741824),
"preferred_segment": false,
"prefer_alloc_in_same_node": true,
"enable_ssd_offload": false, # only required when the SSD offload feature is enabled
"ssd_offload_path": "/nvme/mooncake_offload", # only required when the SSD offload feature is enabled)
"tenant_id": "default"
}
| 参数 | 描述 |
|---|---|
| 参数 | 描述 |
|---|---|
metadata_server |
配置为 P2PHANDSHAKE。 |
protocol |
在 NPU 上必须设置为 ascend。 |
device_name |
保持为空字符串 ""。ascend 协议不使用设备名称。 |
master_server_address |
主服务的 IP 和端口。也可以通过 MOONCAKE_MASTER 环境变量设置,该环境变量优先于此配置项(适用于通过 Kubernetes 注入主服务地址)。 |
global_segment_size |
每张卡向 KV Pool 注册的内存大小。需要与 1GB 对齐。 也可以通过 MOONCAKE_GLOBAL_SEGMENT_SIZE 环境变量设置,该环境变量优先于此配置项。 |
preferred_segment |
在向 KV Pool 写入对象时,是否优先将 KV 存储到本地 segment。默认值为 false。 |
prefer_alloc_in_same_node |
是否优先在同一节点上分配 KV。默认值为 true。 |
enable_ssd_offload |
设置为 true 以启用 SSD 卸载。不支持环境变量。 |
ssd_offload_path |
当 enable_ssd_offload 为 true 时必填。 Mooncake 存储卸载 KV 数据的本地目录的绝对路径(例如 /nvme/mooncake_offload)。该目录必须存在,并且 vLLM 进程可写入;请在启动前创建它(mkdir -p <path>)。Mooncake 会拒绝相对路径、符号链接以及包含 .. 的路径。 |
tenant_id |
可选的 Mooncake 租户命名空间。缺失、null、空值或仅包含空白字符的值将使用 default;会去除首尾空白。所有共享 KV 条目的 Prefill、Decode、scheduler 和 replica 实例必须使用相同的租户 ID。非默认租户需要 Mooncake 0.3.12 或更高版本。 |
步骤 2.2.2:启动 mooncake_master¶
作为独立进程,master 服务只需在一个节点上启动。
在 mooncake 目录下:
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
| 字段 | 描述 |
|---|---|
eviction_high_watermark_ratio |
决定 Mooncake Store 执行驱逐的水位。 |
eviction_ratio |
决定将被驱逐的已存储对象的比例。 |
| 字段 | 描述 |
|---|---|
default_kv_lease_ttl |
控制 KV 对象的默认租约 TTL(毫秒)。请保持其大于 ASCEND_CONNECT_TIMEOUT 和 ASCEND_TRANSFER_TIMEOUT。 |
enable_offload |
设置为 true 可在 Mooncake master 中启用 SSD offload。请保持 master 端口与 mooncake.json 中的 master_server_address 一致。仅在启用 SSD offload 时需要设置。 |
client_ttl |
客户端在最后一次 Ping 之后保持存活的秒数。CLI 默认值为 10;参见 启用 SSD offload 时的 SEGMENT_NOT_FOUND。仅在启用 SSD offload 时需要设置。 |
步骤 2.2.3:启用严格多租户模式¶
在严格多租户模式禁用期间,对象放置会忽略租户 ID,并且对象保留在 default 命名空间中。若要启用隔离命名空间和按租户的内存配额准入,请以严格多租户模式和策略连接器启动 Mooncake master:
mooncake_master \
--port 50088 \
--enable_multi_tenants=true \
--tenant_quota_connector_type=file \
--tenant_quota_connector_uri=/etc/mooncake/tenant_quotas.yaml
例如,/etc/mooncake/tenant_quotas.yaml 可以包含:
version: 1
tenants:
- name: tenant-a
quota: 200GB
- name: tenant-b
quota: 200GB
- name: default
quota: 100GB
当 Mooncake 使用 STORE_USE_ETCD=ON 构建时,文件连接器可以替换为 etcd;在这种情况下,将 tenant_quota_connector_uri 设置为 etcd 端点。严格模式会拒绝未注册租户的写入,包括 default,因此 vLLM-Ascend 使用的每个租户都必须出现在策略中。
Mooncake 通过 master 指标 HTTP 端口(默认 9003)暴露租户配额快照:
curl -s http://<master_host>:9003/api/v1/tenant_quotas
curl -s "http://<master_host>:9003/api/v1/tenant_quotas?tenant_id=tenant-a"
tenant_id 是实例级命名空间和配额标识,而不是认证机制。能够访问 Mooncake 的客户端仍然可以声明租户 ID。即使启用了租户隔离,也应将不兼容的模型、模型版本、量化格式和 KV 布局放在不同的模型或发布命名空间中。
步骤 2.3:PD 分离场景¶
步骤 2.3.1:运行 prefill 节点和 decode 节点¶
使用 MultiConnector 同时利用 MooncakeConnectorV1 和 AscendStoreConnector。MooncakeConnectorV1 执行 kv_transfer,而 AscendStoreConnector 作为前缀缓存节点。
对于 A3 以及 Store/PD 流量分离,请在 prefill 和 decode 节点上都设置 ASCEND_GLOBAL_RESOURCE_CONFIG,并使用 CANN >= 9.1.0。顶层资源配置控制 MooncakeConnectorV1 的 PD 流量,store 部分控制 AscendStoreConnector 的 Mooncake Store 流量。
run_prefill.sh/run_decode.sh:
#!/bin/bash
# prefill / decode
ROLE="prefill"
# A2 (800I/800T A2) or A3 (800I/800T A3) or 950PR&950DT Products)
HARDWARE_SERIES="A2"
# Link type: ROCE or HCCS in A3 series.
LINK_TYPE="ROCE"
LOCAL_IP="xx.xx.xx.xx"
NIC_NAME="xxxxxx"
MODEL_PATH="xxxxxxx/Qwen3-32B"
SERVED_MODEL_NAME="qwen3"
DATA_PARALLEL_SIZE=1
TENSOR_PARALLEL_SIZE=8
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
# parameters required for kv pool and mooncake
export PYTHONHASHSEED=0
export MOONCAKE_CONFIG_PATH="/xxxxxx/mooncake.json"
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages/mooncake:$LD_LIBRARY_PATH
if [ "$ROLE" == "prefill" ]; then
KV_ROLE="kv_producer"
KV_PORT="20001"
LOOKUP_RPC_PORT="0"
else
KV_ROLE="kv_consumer"
KV_PORT="20002"
LOOKUP_RPC_PORT="1"
fi
echo "Starting vLLM on Series: $HARDWARE_SERIES, Role: $ROLE"
rm -rf /root/ascend/log/*
rm -rf ./connector.log
# For detailed parameter descriptions, see 5.1 Environment Variables Description
if [ "$HARDWARE_SERIES" == "A2" ] || { [ "$HARDWARE_SERIES" == "A3" ] && [ "$LINK_TYPE" == "ROCE" ]; }; then
echo 200000 > /proc/sys/vm/nr_hugepages
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 HCCL_INTRA_ROCE_ENABLE=1
elif [ "$HARDWARE_SERIES" == "A3" ] && [ "$LINK_TYPE" == "HCCS" ]; then
export ACL_OP_INIT_MODE=1
export ASCEND_ENABLE_USE_FABRIC_MEM=1
elif [ "$HARDWARE_SERIES" == "A5" ]; then
# 950PR&950DT Products UBOE
export ASCEND_GLOBAL_RESOURCE_CONFIG='{"comm_resource_config.protocol_desc":["uboe:device"]}'
# 950PR&950DT Products UB
export ASCEND_LOCAL_COMM_RES='{"version":"1.3"}'
else
echo "Error: Invalid HARDWARE_SERIES. Set to 'A2', 'A3', or 'A5'."
exit 1
fi
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
KV_CONFIG='{
"kv_connector": "MultiConnector",
"kv_role": "'$KV_ROLE'",
"kv_connector_extra_config": {
"connectors": [
{
"kv_connector": "MooncakeConnectorV1",
"kv_role": "'$KV_ROLE'",
"kv_port": "'$KV_PORT'",
"kv_connector_extra_config": {
"prefill": {
"dp_size": '$DATA_PARALLEL_SIZE',
"tp_size": '$TENSOR_PARALLEL_SIZE'
},
"decode": {
"dp_size": '$DATA_PARALLEL_SIZE',
"tp_size": '$TENSOR_PARALLEL_SIZE'
}
}
},
{
"kv_connector": "AscendStoreConnector",
"kv_role": "'$KV_ROLE'",
"kv_connector_extra_config": {
"backend": "mooncake",
"lookup_rpc_port": "'$LOOKUP_RPC_PORT'"
}
}
]
}
}'
CMD_ARGS=(
--model "$MODEL_PATH"
--served-model-name "$SERVED_MODEL_NAME"
--trust-remote-code
--enforce-eager
--data-parallel-size "$DATA_PARALLEL_SIZE"
--tensor-parallel-size "$TENSOR_PARALLEL_SIZE"
--port 30050
--max-num_seqs 20
--max-model-len 32768
--max-num-batched-tokens 16384
--gpu-memory-utilization 0.9
--kv-transfer-config "$KV_CONFIG"
)
python -m vllm.entrypoints.openai.api_server "${CMD_ARGS[@]}" > log_${ROLE}.log 2>&1
echo "vLLM started. Log file: log_${ROLE}.log"
当前,PD 分离中的键值池默认仅存储由 Prefill 节点生成的 kv cache。在使用 MLA 的模型中,现在支持 Decode 节点存储 kv cache 供 Prefill 节点使用,可通过在 AscendStoreConnector 中添加 consumer_is_to_put: true 启用。如果 Prefill 节点启用 PP,还需要设置 prefill_pp_size 或 prefill_pp_layer_partition。示例如下:
{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_consumer",
"kv_load_failure_policy": "recompute",
"kv_connector_extra_config": {
"lookup_rpc_port": "0",
"backend": "mooncake",
"consumer_is_to_put": true,
"prefill_pp_size": 2,
"prefill_pp_layer_partition": "30,31"
}
}
步骤 2.3.2:启动 proxy_server¶
python vllm-ascend/examples/disaggregated_prefill_v1/load_balance_proxy_server_example.py \
--host localhost \
--prefiller-hosts localhost \
--prefiller-ports 8100 \
--decoder-hosts localhost \
--decoder-ports 8200 \
请将 localhost 更改为您的实际 IP 地址。
步骤 2.3.3:运行推理¶
请将命令中的 localhost、端口和模型权重路径配置为您自己的设置。
短问题:
curl -s http://localhost:8000/v1/completions -H "Content-Type: application/json" -d '{ "model": "/xxxxx/Qwen2.5-7B-Instruct", "prompt": "Hello. I have a question. The president of the United States is", "max_completion_tokens": 200, "temperature":0.0 }'
长问题:
curl -s http://localhost:8000/v1/completions -H "Content-Type: application/json" -d '{ "model": "/xxxxx/Qwen2.5-7B-Instruct", "prompt": "Given the accelerating impacts of climate change—including rising sea levels, increasing frequency of extreme weather events, loss of biodiversity, and adverse effects on agriculture and human health—there is an urgent need for a robust, globally coordinated response. However, international efforts are complicated by a range of factors: economic disparities between high-income and low-income countries, differing levels of industrialization, varying access to clean energy technologies, and divergent political systems that influence climate policy implementation. In this context, how can global agreements like the Paris Accord be redesigned or strengthened to not only encourage but effectively enforce emission reduction targets? Furthermore, what mechanisms can be introduced to promote fair and transparent technology transfer, provide adequate financial support for climate adaptation in vulnerable regions, and hold nations accountable without exacerbating existing geopolitical tensions or disproportionately burdening those with historically lower emissions?", "max_completion_tokens": 256, "temperature":0.0 }'
步骤 2.4:PD 混合推理¶
步骤 2.4.1:运行混合部署脚本¶
pd_mix.sh 的内容:
# A2 (800I/800T A2) or A3 (800I/800T A3) or 950PR&950DT Products
HARDWARE_SERIES="A2"
# Link type: ROCE or HCCS in A3 series.
LINK_TYPE="ROCE"
LOCAL_IP="xx.xx.xx.xx"
NIC_NAME="xxxxxx"
MODEL_PATH="xxxxxxx/Qwen3-32B"
SERVED_MODEL_NAME="qwen3"
DATA_PARALLEL_SIZE=1
TENSOR_PARALLEL_SIZE=8
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
# parameters required for kv pool and mooncake
export PYTHONHASHSEED=0
export MOONCAKE_CONFIG_PATH="/xxxxxx/mooncake.json"
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages/mooncake:$LD_LIBRARY_PATH
echo "Starting vLLM on Series: $HARDWARE_SERIES"
rm -rf /root/ascend/log/*
rm -rf ./connector.log
# For detailed parameter descriptions, see 5.1 Environment Variables Description
if [ "$HARDWARE_SERIES" == "A2" ] || { [ "$HARDWARE_SERIES" == "A3" ] && [ "$LINK_TYPE" == "ROCE" ]; }; then
echo 200000 > /proc/sys/vm/nr_hugepages
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 HCCL_INTRA_ROCE_ENABLE=1
elif [ "$HARDWARE_SERIES" == "A3" ] && [ "$LINK_TYPE" == "HCCS" ]; then
export ACL_OP_INIT_MODE=1
export ASCEND_ENABLE_USE_FABRIC_MEM=1
elif [ "$HARDWARE_SERIES" == "A5" ]; then
# 950PR&950DT Products UBOE
export ASCEND_GLOBAL_RESOURCE_CONFIG='{"comm_resource_config.protocol_desc":["uboe:device"]}'
# 950PR&950DT Products UB
export ASCEND_LOCAL_COMM_RES='{"version":"1.3"}'
else
echo "Error: Invalid HARDWARE_SERIES. Set to 'A2', 'A3', or 'A5'."
exit 1
fi
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
KV_CONFIG='{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {
"backend": "mooncake",
"lookup_rpc_port": "0"
}
}'
CMD_ARGS=(
--model "$MODEL_PATH"
--served-model-name "$SERVED_MODEL_NAME"
--trust-remote-code
--enforce-eager
--data-parallel-size "$DATA_PARALLEL_SIZE"
--tensor-parallel-size "$TENSOR_PARALLEL_SIZE"
--port 30050
--max-num_seqs 20
--max-model-len 32768
--max-num-batched-tokens 16384
--gpu-memory-utilization 0.9
--kv-transfer-config "$KV_CONFIG"
)
python -m vllm.entrypoints.openai.api_server "${CMD_ARGS[@]}" > log_mix.log 2>&1
echo "vLLM started. Log file: log_mix.log"
步骤 2.4.2:运行推理¶
请将命令中的 localhost、端口和模型权重路径配置为您自己的设置。发送的请求只会发送到混合部署脚本所在的端口,无需单独启动代理。
短问题:
curl -s http://localhost:8100/v1/completions -H "Content-Type: application/json" -d '{ "model": "/xxxxx/Qwen2.5-7B-Instruct", "prompt": "Hello. I have a question. The president of the United States is", "max_completion_tokens": 200, "temperature":0.0 }'
长问题:
curl -s http://localhost:8100/v1/completions -H "Content-Type: application/json" -d '{ "model": "/xxxxx/Qwen2.5-7B-Instruct", "prompt": "Given the accelerating impacts of climate change—including rising sea levels, increasing frequency of extreme weather events, loss of biodiversity, and adverse effects on agriculture and human health—there is an urgent need for a robust, globally coordinated response. However, international efforts are complicated by a range of factors: economic disparities between high-income and low-income countries, differing levels of industrialization, varying access to clean energy technologies, and divergent political systems that influence climate policy implementation. In this context, how can global agreements like the Paris Accord be redesigned or strengthened to not only encourage but effectively enforce emission reduction targets? Furthermore, what mechanisms can be introduced to promote fair and transparent technology transfer, provide adequate financial support for climate adaptation in vulnerable regions, and hold nations accountable without exacerbating existing geopolitical tensions or disproportionately burdening those with historically lower emissions?", "max_completion_tokens": 256, "temperature":0.0 }'
注意:对于启用 ASCEND_BUFFER_POOL 的 MooncakeStore,建议在运行实际性能基准测试前执行预热阶段。
这是因为当涉及设备到设备通信时,HCCL 单边通信连接会在实例启动后延迟创建。目前,需要在所有设备之间建立全网格连接。建立这些连接会引入一次性时间开销和持续的设备内存消耗(每条连接占用 4 MB 设备内存)。
对于预热,建议发送输入序列长度为 8k、输出序列长度为 1 的请求,请求总数为设备数量(卡/die)的 2–3 倍。
步骤 2.5:使用嵌入式真实客户端模式启用 MooncakeStore SSD 卸载¶
步骤 2.5.1:运行嵌入式真实客户端¶
在模式 A(嵌入式真实客户端)下,Mooncake 嵌入在 vLLM 中。当 vLLM 服务启动时,AscendStoreConnector / MooncakeBackend 会自动使用 mooncake.json 中的配置调用 MooncakeDistributedStore.setup()(启用 SSD 卸载时包括 enable_ssd_offload 和 ssd_offload_path)。无需单独的 mooncake_client 进程。
步骤 2.5.2:SSD 磁盘使用控制¶
以下环境变量用于控制 SSD 卸载(bucket 后端)的磁盘空间使用:
| 环境变量 | 默认值 | 描述 |
|---|---|---|
MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES |
1342177280 (1280 MB) |
每个 rank 的 SSD 读写缓冲区大小(字节)。不能在 mooncake.json 中配置。如果遇到 BUFFER_OVERFLOW,请增大该值——参见 调整 MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES 的大小。在 A3 且 ASCEND_ENABLE_USE_FABRIC_MEM=1 时,必须对齐到 1GB,并计入每个 rank 的 fabric 内存配额(参见 Fabric 内存大小对齐)。 |
MOONCAKE_OFFLOAD_BUCKET_MAX_TOTAL_SIZE |
0 |
驱逐阈值(字节)。当设置为 0 时,后端使用 物理磁盘容量的 90% 作为配额。设置显式值可精确控制磁盘使用。 |
MOONCAKE_OFFLOAD_BUCKET_EVICTION_POLICY |
none |
驱逐策略:none(写满时写入失败)、fifo 或 lru。 |
MOONCAKE_OFFLOAD_TOTAL_SIZE_LIMIT_BYTES |
2199023255552 (2 TB) |
每个 rank 上报给 Mooncake master 的最大磁盘使用量。Master 会跨客户端聚合该值(SSD Storage 总量中大约为 2 TB × rank 数量)。始终覆盖该值以匹配实际磁盘容量——默认值通常超过可用空间。 |
MOONCAKE_OFFLOAD_TOTAL_SIZE_LIMIT_BYTES 风险:如果保持 2 TB 默认值,master 显示的 SSD 总配额会远大于物理磁盘(例如 16 个 rank → 在 1 TB NVMe 上显示约 32 TB)。当磁盘写满时,卸载仍会失败,而监控看起来正常。在生产使用前,请将其设置为实际的每个 rank 预算。
由于每个 TP rank 都在 ssd_offload_path 下使用独立的 SSD 子目录(rank_0/、rank_1/、...),所有 rank 共享同一块物理磁盘。为防止单个 rank 占用过多空间,请设置显式的每个 rank 配额。例如,对于 800 GB 磁盘和 8 个 TP rank:
# 800 GB total disk, 8 ranks, ~100 GB per rank
export MOONCAKE_OFFLOAD_TOTAL_SIZE_LIMIT_BYTES=$((100 * 1024 * 1024 * 1024))
export MOONCAKE_OFFLOAD_BUCKET_MAX_TOTAL_SIZE=$((100 * 1024 * 1024 * 1024))
export MOONCAKE_OFFLOAD_BUCKET_EVICTION_POLICY=lru
export MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES=1073741824 # 1 GB
3. 使用 Memcache 作为 KV Pool 后端的示例¶
步骤 3.1:前提条件¶
在安装和配置 Memcache 之前,请执行必要的环境检查,包括内存检查 5.2.1、A3 可用内存扫描 5.2.2、950PR&950DT 产品签名验证/容器挂载,参见 5.2.3。如果还想启用 SSD 功能,请参见 5.2.4。
步骤 3.2:软件安装¶
MemCache 依赖于 MemFabric。因此,必须先安装 MemFabric。应在 memfabric 安装完成后再安装 memcache。
启用 Memcache SSD Cache 需要 memcache_hybrid >= 1.2.0。
步骤 3.3:配置 memcache 配置文件¶
运行 pip show memcache_hybrid,并在输出中找到 Location 值。将该值用作下面的 {INSTALL_PATH}。
配置文件位于 {INSTALL_PATH}/memcache_hybrid/config。
mmc-meta.conf:
ock.mmc.meta_service_url = tcp://xx.xx.xx.xx:5000
ock.mmc.meta_service.config_store_url = tcp://xx.xx.xx.xx:6000
ock.mmc.meta_service.metrics_url = http://xx.xx.xx.xx:8000
ock.mmc.log_level = info
# If SSD is enabled, modify the following parameters to improve SSD cache hit rate
ock.mmc.evict_threshold_high = 70
ock.mmc.evict_threshold_low = 60
ock.mmc.rewarm.dram_watermark = 95
mmc-local.conf:
ock.mmc.meta_service_url = tcp://xx.xx.xx.xx:5000
ock.mmc.local_service.config_store_url = tcp://xx.xx.xx.xx: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 = 1GB
ock.mmc.local_service.max.dram.size = 1024GB
# SSD feature related parameters below
ock.mmc.local_service.storage.enabled = false # Set to true to enable SSD storage
ubsio.disk.path = /dev/nvmexn1:/dev/nvmexn2p1:/dev/loopX
ubsio.mem.size_in_gb = 10
ubsio.standalone.device_count = 8
ubsio.standalone.force_new_disk = true
重点关注:
| 参数 | 描述 |
|---|---|
ock.mmc.meta_service_url |
P 节点和 D 节点应配置相同的 MetaService 端点。 |
ock.mmc.local_service.config_store_url |
其值必须与 mmc-meta.conf 中的 ock.mmc.meta_service.config_store_url 相同。 |
ock.mmc.local_service.world_size |
支持的 LocalService 最大数量,包括未来将添加的服务。 |
ock.mmc.local_service.protocol |
推荐协议为 device_rdma(设备上的 RDMA,当设备 RoCE 可用时支持 A2 和 A3,推荐用于 A2)和 device_sdma(设备上的 SDMA,当 HCCS 可用时支持 A3,推荐用于 A3)。对于 950PR&950DT 产品 UB 场景,设置为 device_urma。对于 950PR&950DT 产品 UBOE 场景,设置为 device_uboe。有关其他支持协议的详细信息,请参阅 MemCache LocalService 配置文件。 |
ock.mmc.local_service.dram.size |
每个 die 分配的 DRAM 大小。例如,在 A3 上,若要分配 640GB 作为 KV 池,此参数应设置为 640/16=40GB。当 HCCS 可用时,A3 应设置为 0GB。 |
ock.mmc.local_service.max.dram.size |
所有本地进程中 ock.mmc.local_service.dram.size 的最大值,如果各 rank 贡献的 DRAM 大小不同,则必须设置。 |
| 参数 | 描述 |
|---|---|
ock.mmc.local_service.storage.enabled |
设置为 true 以启用 SSD 缓存。 |
ubsio.disk.path |
启用 SSD 缓存时必填。直接指定目标 SSD 块设备、分区或循环设备。配置的设备必须专用于 UBS IO,且不得有任何挂载点。 多个路径使用冒号(:)分隔。不推荐 /dev/sdx。 |
ubsio.mem.size_in_gb |
每个进程的 UBS IO 内存池大小(GB)。推荐值为 10。支持范围为 0 到 3072 的整数;SSD 缓存要求每个进程至少 5 GB。总分配量不得超过为操作系统、vLLM 和 Memcache DRAM 池预留内存后节点可用的内存。 |
ubsio.standalone.device_count |
其 ock.mmc.local_service.dram.size 不为 0 的本地服务数量。 |
ubsio.standalone.force_new_disk |
控制 UBS IO 是将配置的 SSD 设备初始化为新磁盘,还是恢复其现有元数据。由于当前版本不支持故障恢复,请设置为 true。 |
步骤 3.4:运行 Memcache MetaService¶
作为独立进程,MetaService 只需在一个节点上启动。
启动 MetaService 服务。
export MMC_META_CONFIG_PATH={INSTALL_PATH}/memcache_hybrid/config/mmc-meta.conf
python -c "from memcache_hybrid import MetaService; MetaService.main()"
步骤 3.5:PD 分离场景¶
运行 prefill 节点和 decode 节点¶
使用 MultiConnector 同时利用 MooncakeConnectorV1 和 AscendStoreConnector。MooncakeConnectorV1 执行 kv_transfer,而 AscendStoreConnector 启用 KV Cache Pool。
Atlas A2 产品/Atlas A3 产品/950PR&950DT 产品¶
run_prefill.sh/run_decode.sh:
#!/bin/bash
# prefill / decode
ROLE="prefill"
# A2 (800I/800T A2) or A3 (800I/800T A3) or 950PR&950DT Products
HARDWARE_SERIES="A2"
# Link type: ROCE or HCCS in A3 series.
LINK_TYPE="ROCE"
LOCAL_IP="xx.xx.xx.xx"
NIC_NAME="xxxxxx"
MODEL_PATH="xxxxxxx/Qwen3-32B"
SERVED_MODEL_NAME="qwen3"
DATA_PARALLEL_SIZE=1
TENSOR_PARALLEL_SIZE=8
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
# parameters required for kv pool and memcache
export PYTHONHASHSEED=0
export MMC_LOCAL_CONFIG_PATH={INSTALL_PATH}/memcache_hybrid/config/mmc-local.conf
export LD_LIBRARY_PATH={INSTALL_PATH}/memcache_hybrid/lib:${PYTHON_LIB_DIR}:${LD_LIBRARY_PATH}
if [ "$ROLE" == "prefill" ]; then
KV_ROLE="kv_producer"
KV_PORT="20001"
LOOKUP_RPC_PORT="0"
else
KV_ROLE="kv_consumer"
KV_PORT="20002"
LOOKUP_RPC_PORT="1"
fi
echo "Starting vLLM on Series: $HARDWARE_SERIES, Role: $ROLE"
rm -rf /root/ascend/log/*
rm -rf ./connector.log
# For detailed parameter descriptions, see 5.1 Environment Variables Description
if [ "$HARDWARE_SERIES" == "A2" ] || { [ "$HARDWARE_SERIES" == "A3" ] && [ "$LINK_TYPE" == "ROCE" ]; }; then
echo 200000 > /proc/sys/vm/nr_hugepages
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 HCCL_INTRA_ROCE_ENABLE=1
elif [ "$HARDWARE_SERIES" == "A3" ] && [ "$LINK_TYPE" == "HCCS" ]; then
export ACL_OP_INIT_MODE=1
export ASCEND_ENABLE_USE_FABRIC_MEM=1
elif [ "$HARDWARE_SERIES" == "A5" ]; then
# 950PR&950DT Products UBOE
export ASCEND_GLOBAL_RESOURCE_CONFIG='{"comm_resource_config.protocol_desc":["uboe:device"]}'
# 950PR&950DT Products UB
export ASCEND_LOCAL_COMM_RES='{"version":"1.3"}'
else
echo "Error: Invalid HARDWARE_SERIES. Set to 'A2', 'A3', or 'A5'."
exit 1
fi
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
KV_CONFIG='{
"kv_connector": "MultiConnector",
"kv_role": "'$KV_ROLE'",
"kv_connector_extra_config": {
"connectors": [
{
"kv_connector": "MooncakeConnectorV1",
"kv_role": "'$KV_ROLE'",
"kv_port": "'$KV_PORT'",
"kv_connector_extra_config": {
"prefill": {
"dp_size": '$DATA_PARALLEL_SIZE',
"tp_size": '$TENSOR_PARALLEL_SIZE'
},
"decode": {
"dp_size": '$DATA_PARALLEL_SIZE',
"tp_size": '$TENSOR_PARALLEL_SIZE'
}
}
},
{
"kv_connector": "AscendStoreConnector",
"kv_role": "'$KV_ROLE'",
"kv_connector_extra_config": {
"backend": "memcache",
"lookup_rpc_port": "'$LOOKUP_RPC_PORT'",
"use_layerwise":false # Set to true only on the Prefill node to enable layerwise
}
}
]
}
}'
CMD_ARGS=(
--model "$MODEL_PATH"
--served-model-name "$SERVED_MODEL_NAME"
--trust-remote-code
--enforce-eager
--data-parallel-size "$DATA_PARALLEL_SIZE"
--tensor-parallel-size "$TENSOR_PARALLEL_SIZE"
--port 30050
--max-num_seqs 20
--max-model-len 32768
--max-num-batched-tokens 16384
--gpu-memory-utilization 0.9
--kv-transfer-config "$KV_CONFIG"
)
python -m vllm.entrypoints.openai.api_server "${CMD_ARGS[@]}" > log_${ROLE}.log 2>&1
echo "vLLM started. Log file: log_${ROLE}.log"
步骤 3.5.2:启动 proxy_server¶
请参阅 MooncakeStore 部署章节中的 启动 proxy_server。
步骤 3.5.3:运行推理¶
请参阅 MooncakeStore 部署章节中的 运行推理。
步骤 3.6:PD 混合场景¶
步骤 3.6.1:运行混合部署脚本¶
Atlas A2 产品/Atlas A3 产品/950PR&950DT 产品¶
Run_pd_mix.sh:
#!/bin/bash
# Atlas A2 Products or Atlas A3 Products or 950PR&950DT Products
HARDWARE_SERIES="A2"
# Link type: ROCE or HCCS in A3 series.
LINK_TYPE="ROCE"
LOCAL_IP="xx.xx.xx.xx"
NIC_NAME="xxxxxx"
MODEL_PATH="xxxxxxx/Qwen3-32B"
SERVED_MODEL_NAME="qwen3"
DATA_PARALLEL_SIZE=1
TENSOR_PARALLEL_SIZE=8
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
# parameters required for kv pool and memcache
export PYTHONHASHSEED=0
export MMC_LOCAL_CONFIG_PATH={INSTALL_PATH}/memcache_hybrid/config/mmc-local.conf
export LD_LIBRARY_PATH={INSTALL_PATH}/memcache_hybrid/lib:${PYTHON_LIB_DIR}:${LD_LIBRARY_PATH}
echo "Starting vLLM on Series: $HARDWARE_SERIES"
rm -rf /root/ascend/log/*
rm -rf ./connector.log
# For detailed parameter descriptions, see 5.1 Environment Variables Description
if [ "$HARDWARE_SERIES" == "A2" ] || { [ "$HARDWARE_SERIES" == "A3" ] && [ "$LINK_TYPE" == "ROCE" ]; }; then
echo 200000 > /proc/sys/vm/nr_hugepages
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 HCCL_INTRA_ROCE_ENABLE=1
elif [ "$HARDWARE_SERIES" == "A3" ] && [ "$LINK_TYPE" == "HCCS" ]; then
export ACL_OP_INIT_MODE=1
export ASCEND_ENABLE_USE_FABRIC_MEM=1
elif [ "$HARDWARE_SERIES" == "A5" ]; then
# 950PR&950DT Products UBOE
export ASCEND_GLOBAL_RESOURCE_CONFIG='{"comm_resource_config.protocol_desc":["uboe:device"]}'
# 950PR&950DT Products UB
export ASCEND_LOCAL_COMM_RES='{"version":"1.3"}'
else
echo "Error: Invalid HARDWARE_SERIES. Set to 'A2', 'A3', or 'A5'."
exit 1
fi
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
KV_CONFIG='{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {
"backend": "memcache",
"lookup_rpc_port": "0",
"use_layerwise":false # Set to true to enable layerwise
}
}'
CMD_ARGS=(
--model "$MODEL_PATH"
--served-model-name "$SERVED_MODEL_NAME"
--trust-remote-code
--enforce-eager
--data-parallel-size "$DATA_PARALLEL_SIZE"
--tensor-parallel-size "$TENSOR_PARALLEL_SIZE"
--port 30050
--max-num_seqs 20
--max-model-len 32768
--max-num-batched-tokens 16384
--gpu-memory-utilization 0.9
--kv-transfer-config "$KV_CONFIG"
)
python -m vllm.entrypoints.openai.api_server "${CMD_ARGS[@]}" > log_mix.log 2>&1
echo "vLLM started. Log file: log_mix.log"
步骤 3.6.2:运行推理¶
请参阅 MooncakeStore 部署章节中的 运行推理。
步骤 3.7:MemCache 与 vLLM 分离部署¶
该部署模式将 MemCache 和 vLLM 运行在不同的进程中。它与 vLLM PD 分离部署不同。在默认的共置模式下,vLLM 会在 KV 连接器初始化 MemCache 之前加载模型权重。因此,MemCache 可能无法从剩余可用空间中预留足够的内存。在 vLLM 之前启动独立的 MemCache 进程,可使 MemCache 预留更大的内存池。该模式目前仅支持 A3 HCCS 场景。
准备两个 LocalService 配置文件,其连接和协议设置相同。vLLM 进程使用的配置不提供 DRAM:
# mmc-local.conf used by the vLLM process
ock.mmc.local_service.dram.size = 0GB
ock.mmc.local_service.max.dram.size = 1024GB
独立 MemCache 进程使用的配置指定要提供的 DRAM 量:
# mmc-local-standalone.conf used by the standalone MemCache process
ock.mmc.local_service.dram.size = 600GB
ock.mmc.local_service.max.dram.size = 1024GB
上述大小仅为示例。请根据可用内存进行调整,并将 ock.mmc.local_service.max.dram.size 设置为可容纳 LocalService 进程使用的最大 dram.size。
按以下顺序部署服务:
- 按照上文描述启动 MetaService。
- 在启动 vLLM 之前,在每个节点上使用
mmc-local-standalone.conf启动一个独立的 MemCache 进程。这些进程会将配置的 DRAM 加入内存池。 - 等待每个节点上的独立 MemCache 进程报告初始化成功。
- 将
MMC_LOCAL_CONFIG_PATH设置为mmc-local.conf,然后按照上文描述启动 vLLM 推理进程。vLLM 进程中的 MemCache 会连接到现有内存池,而不会提供额外的 DRAM。
关于独立 MemCache 启动脚本和完整的 A3 部署流程,请参阅 Memcache + vLLM + A3。
步骤 3.8:启用 Memcache SSD 缓存¶
步骤 3.8.1:配置¶
有关详细配置,请参阅 配置 memcache 配置文件,并需查看 5.2.4。
步骤 3.8.2:在 MemCache 与 vLLM 分离部署时启用 SSD¶
参考以下配置:
mmc-local.conf:
ock.mmc.meta_service_url = tcp://xx.xx.xx.xx:5000
ock.mmc.local_service.config_store_url = tcp://xx.xx.xx.xx: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 = 0GB
ock.mmc.local_service.max.dram.size = 1024GB
mmc-local-standalone.conf:
ock.mmc.meta_service_url = tcp://xx.xx.xx.xx:5000
ock.mmc.local_service.config_store_url = tcp://xx.xx.xx.xx: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 = 600GB
ock.mmc.local_service.max.dram.size = 1024GB
# SSD feature related parameters below
ock.mmc.local_service.storage.enabled = true
ubsio.disk.path = /dev/nvmexn1:/dev/nvmexn2p1:/dev/loopX
ubsio.mem.size_in_gb = 50
ubsio.standalone.device_count = 1
ubsio.standalone.force_new_disk = true
步骤 3.8.3:UBS IO 内存池大小¶
在调整推荐值时,通过将可供 UBS IO 使用的节点内存除以启用 DRAM 的本地服务数量,向下取整,并将结果上限设为 3072,来计算每个进程允许的最大值:
maximum ubsio.mem.size_in_gb = min(3072, floor(available node memory for UBS IO (GB) / number of DRAM-enabled local services))
例如,如果可供 UBS IO 使用的内存为 200 GB,并且有四个本地服务启用了 DRAM,则每个进程的上限为 50 GB,因此推荐值 ubsio.mem.size_in_gb = 10 有效。如果计算出的上限小于 5,请释放更多节点内存或减少启用 DRAM 的本地服务数量。
对于 MemCache 独立部署场景,建议为单个进程配置 50 GB。在其他场景中,建议配置 10 GB。如果要使用 L2.5 内存缓存能力,请在上述限制内增大 ubsio.mem.size_in_gb,并相应调整 ubsio.wcache.evict_water_level。
有关磁盘配置、驱逐水位线以及其他 UBS IO 参数,请参阅 DRAM + SSD 多级池化配置指南。
4. 使用 Yuanrong 作为 KV Pool 后端的示例¶
- 软件:
- 在所有节点上安装
openyuanrong-datasystem(yr.datasystem必须可导入)。
- 在所有节点上安装
步骤 4.1:安装 Yuanrong Datasystem¶
pip install openyuanrong-datasystem
python -c "import yr.datasystem; print('Yuanrong Datasystem is ready')"
dscli --version
如果预构建包与您环境中的 CANN 或 Ascend 驱动版本不匹配,请在 vLLM Ascend 镜像中从源码构建 Yuanrong Datasystem。请遵循官方 Yuanrong Datasystem 构建说明: https://atomgit.com/openeuler/yuanrong-datasystem
步骤 4.2:选择服务发现后端¶
Yuanrong Datasystem 支持使用 Coordinator 和 etcd 进行服务发现。 请从以下选项中恰好选择一个。不要在同一 Worker 上同时配置两种后端。
选项 1:启动 Coordinator¶
使用随 Yuanrong Datasystem 提供的 Coordinator 进行服务发现。 这样可以避免安装和维护单独的 etcd 服务。在一个所有 Datasystem Worker 都能访问的地址上启动一个 Coordinator:
COORDINATOR_ADDRESS="<coordinator_ip>:31511"
dscli start -c \
--coordinator_address "${COORDINATOR_ADDRESS}"
将 <coordinator_ip> 替换为运行 Coordinator 的节点的 IP 地址。仅在单节点部署中使用 127.0.0.1。启动成功后会打印 Start coordinator service ... success。
对于最小化的单节点试用,您可以改用一条命令同时启动 Coordinator 和 Worker。如果使用此命令,请跳过下面单独的 Worker 启动步骤,并将 yuanrong.json 中的 worker_addr 设置为 127.0.0.1:31501:
dscli start -a \
--coordinator_address "127.0.0.1:31511" \
--worker_address "127.0.0.1:31501" \
--shared_memory_size_mb 4096
选项 2:启动 etcd¶
以下示例启动一个单节点 etcd 集群:
ETCD_VERSION="v3.5.12"
ETCD_IP="127.0.0.1"
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/
etcd \
--name etcd-single \
--data-dir /tmp/etcd-data \
--listen-client-urls http://0.0.0.0:2379 \
--advertise-client-urls http://${ETCD_IP}:2379 \
--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 &
etcdctl --endpoints "${ETCD_IP}:2379" put key "value"
etcdctl --endpoints "${ETCD_IP}:2379" get key
对于多节点部署,请将 ETCD_IP 设置为所有 Worker 都能访问的地址,而不是 127.0.0.1。
对于生产环境,请参阅官方 etcd 集群文档:https://etcd.io/docs/v3.7/op-guide/clustering/
多节点部署¶
在每个节点上安装 Yuanrong Datasystem。每个节点运行一个 Datasystem Worker,并使用唯一且可访问的 worker_address。所有 Worker 必须使用相同的服务发现后端和后端地址。
本节中的命令使用 4 GiB 共享内存作为最小示例。对于高吞吐部署,请改用下一节中经过调优的 Worker 参数;不要在同一地址上启动第二个 Worker。
使用 Coordinator 进行多节点部署¶
在一个所有 Worker 都能访问的节点上启动一个 Coordinator。例如,如果 Coordinator 节点地址为 192.168.1.10:
然后在每个节点上启动一个 Worker。将 WORKER_IP 设置为该节点自身的 IP;在所有节点上保持 COORDINATOR_ADDRESS 相同:
# Run on every Worker node.
WORKER_IP="<this_node_ip>"
COORDINATOR_ADDRESS="192.168.1.10:31511"
dscli start -w \
--worker_address "${WORKER_IP}:31501" \
--coordinator_address "${COORDINATOR_ADDRESS}" \
--shared_memory_size_mb 4096
本示例使用一个 Coordinator,不提供 Coordinator 高可用。对于生产控制平面高可用,请部署多个 Coordinator,使用静态 Raft 对等节点,为每个 Coordinator 配置唯一的 coordinator_address 和 coordinator_raft_data_dir,并使用相同的 coordinator_raft_initial_peers 列表。请参阅 Yuanrong Datasystem dscli 文档。
使用 etcd 进行多节点部署¶
按照上一节的说明,启动一个所有工作节点都能访问的 etcd 服务或集群。然后在每个节点上启动一个工作节点。将 WORKER_IP 设置为该节点自身的 IP,并在所有节点上保持 ETCD_ADDRESS 相同:
# Run on every Worker node.
WORKER_IP="<this_node_ip>"
ETCD_ADDRESS="192.168.1.10:2379"
dscli start -w \
--worker_address "${WORKER_IP}:31501" \
--etcd_address "${ETCD_ADDRESS}" \
--shared_memory_size_mb 4096
对于这两种后端:
- 在多节点部署中,不要将
127.0.0.1或0.0.0.0用作工作节点地址。其他工作节点必须能够连接到所通告的 IP。 - 允许网络访问 Coordinator 端口(
31511)或 etcd 客户端端口(2379),以及每个工作节点端口(本示例中为31501)。 - 在每个节点上,将
yuanrong.json中的worker_addr设置为该节点本地的WORKER_IP:31501。因此,配置文件因节点而异。 - 在所有 vLLM 实例中保持
PYTHONHASHSEED相同。
步骤 4.3:启动 Datasystem 工作节点¶
使用 dscli 在每个节点上启动一个 Datasystem 工作节点。以下配置是高吞吐量 KV Pool 工作负载的推荐起点:
本指南中的工作节点示例使用 Coordinator。若要改用 etcd,请在每个工作节点命令中将 --coordinator_address "${COORDINATOR_ADDRESS}" 替换为 --etcd_address "${ETCD_ADDRESS}"。
COORDINATOR_ADDRESS="<coordinator_ip>:31511"
ETCD_ADDRESS="<etcd_ip>:2379"
WORKER_IP="<worker_ip>"
WORKER_LOG_DIR="/var/log/yuanrong/worker"
sudo mkdir -p "${WORKER_LOG_DIR}"
sudo chown "$(id -u):$(id -g)" "${WORKER_LOG_DIR}"
dscli start -w \
--worker_address "${WORKER_IP}:31501" \
--coordinator_address "${COORDINATOR_ADDRESS}" \
--log_dir "${WORKER_LOG_DIR}" \
--shared_memory_size_mb 40960 \
--arena_per_tenant 1 \
--enable_huge_tlb true \
--enable_fallocate false \
--rpc_thread_num 64 \
--oc_thread_num 64 \
--enable_worker_worker_batch_get true \
--sc_regular_socket_num 0 \
--sc_stream_socket_num 0
--worker_address 的值稍后会作为 yuanrong.json 中的 worker_addr 使用,因此在同一节点上请保持主机和端口相同。每个工作节点只配置一个协调后端。使用 Coordinator 时,不要同时设置 etcd_address 或 metastore_address。
上述调优参数具有以下作用:
| 参数 | 说明 |
|---|---|
log_dir |
设置 Datasystem 工作节点日志目录。启动前创建该目录并授予工作节点进程写入权限。 |
arena_per_tenant=1 |
每个租户使用一个共享内存 arena,作为内存和文件描述符使用的保守起点。 |
enable_huge_tlb=true |
使用 HugeTLB 页作为工作节点共享内存的后端。在启动工作节点前预留足够的 2 MiB 大页。 |
enable_fallocate=false |
禁用共享内存文件的 fallocate;请配合上述 HugeTLB 配置使用此设置。 |
rpc_thread_num=64 |
设置 RPC/ZMQ 服务并发数。 |
oc_thread_num=64 |
设置 Object Cache 业务线程池大小。 |
enable_worker_worker_batch_get=true |
启用 Datasystem 工作节点之间的批量 Object Cache 读取。 |
sc_regular_socket_num=0, sc_stream_socket_num=0 |
禁用 Stream Cache 服务。要启用该服务,两个值都必须大于零;当 KV Pool 不使用 Stream Cache 时,请保持为零。 |
对于 shared_memory_size_mb=40960,请至少预留 20480 个 2 MiB 大页,并在启动工作节点前确认它们可用:
工作节点日志(包括基础名称通常为 datasystem_worker 的文件)会写入 --log_dir 目录。请使用绝对路径,使日志位置不依赖于工作节点进程的当前目录。
这些线程数只是调优起点,而非通用默认值。请根据可用 CPU 核心数和实测请求吞吐量进行调整。由于 -w 会消耗剩余的命令行参数,请将 dscli start 的任意选项(例如 --timeout)放在 -w 之前。
如需了解更多参数,请参阅 Yuanrong Datasystem 官方网站上的 dscli 使用文档:
https://atomgit.com/openeuler/yuanrong-datasystem
当不再需要工作节点时,停止该工作节点。仅在所有工作节点停止后,再停止所选的服务发现后端。对于独立的 etcd 集群,请遵循其常规集群维护流程。
dscli stop --worker_address "${WORKER_IP}:31501"
# Coordinator option only:
dscli stop --coordinator_address "${COORDINATOR_ADDRESS}"
步骤 4.4:环境变量配置¶
在启动 vLLM 之前,请在每个节点上设置以下环境变量:
| 变量 | 是否必需 | 默认值 | 说明 |
| 变量 | 是否必需 | 默认值 | 描述 |
|---|---|---|---|
| :--------------------------------- | :------- | :--------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- |
PYTHONHASHSEED |
是 | 0 |
必须在所有节点上保持一致,以保证哈希生成的一致性。 |
DS_WORKER_ADDR |
是 | N/A | Datasystem worker 地址,格式为 <host>:<port>。此值必须与本地 dscli start --worker_address 的值一致。 |
DATASYSTEM_CLIENT_LOG_DIR |
否 | ~/.datasystem/logs |
vLLM 进程创建的 Yuanrong 客户端 SDK 日志目录。请使用与 worker 日志不同的目录。 |
DS_ENABLE_EXCLUSIVE_CONNECTION |
否 | 0 |
传递给 Yuanrong HeteroClient.enable_exclusive_connection。当部署需要独占连接模式时,使用 1 启用该模式。 |
DS_ENABLE_REMOTE_H2D |
否 | 0 |
传递给 Yuanrong HeteroClient.enable_remote_h2d。仅在满足下文 Remote H2D 要求后,才使用 1。 |
export PYTHONHASHSEED=0
export DS_WORKER_ADDR="${WORKER_IP}:31501"
export DATASYSTEM_CLIENT_LOG_DIR="/var/log/yuanrong/client"
export DS_ENABLE_EXCLUSIVE_CONNECTION=0
export DS_ENABLE_REMOTE_H2D=0
mkdir -p "${DATASYSTEM_CLIENT_LOG_DIR}"
在启动 vLLM 之前设置 DATASYSTEM_CLIENT_LOG_DIR,因为 Yuanrong
客户端会在日志初始化期间读取它。客户端 SDK 日志(其基础名称通常为
ds_client)将写入此目录。
步骤 4.4.1:Yuanrong 客户端配置(yuanrong.json)¶
YR_CONFIG_PATH 指向的 yuanrong.json 文件承载 Yuanrong
客户端连接选项:
{
"worker_addr": "1.2.3.4:31501",
"connect_timeout_ms": 9000,
"request_timeout_ms": 0,
"get_sub_timeout_ms": 0,
"enable_remote_h2d": false,
"remote_h2d_transport_backend": "HIXL",
"enable_fabric_mem": false,
"enable_dev_mem_pregister": false,
"use_layerwise": false
}
worker_addr:Datasystem worker 地址,格式为 <host>:<port>。此值必须与本地 dscli start --worker_address 的值一致。
connect_timeout_ms:Yuanrong 客户端建立连接的最大时间(毫秒)。Yuanrong 要求该值为大于或等于 500 的整数。默认值为 9000。
request_timeout_ms:Yuanrong 客户端请求的超时时间(毫秒)。默认值为 0,这会保留 Yuanrong SDK 使用 connect_timeout_ms 作为请求超时的行为。设置一个正值可独立控制请求超时。
get_sub_timeout_ms:每个 mget_h2d_from_multi_buffers 请求等待对象就绪的最大时间(毫秒)。0 表示不允许等待。默认值为 0。Yuanrong 会在 Get 请求运行时校验该值。它可以大于 request_timeout_ms;Yuanrong Get 路径会扩展该调用的 RPC 超时,以适应配置的对象就绪等待。
enable_remote_h2d:传递给 Yuanrong HeteroClient.enable_remote_h2d。仅在满足下文 Remote H2D 要求后,才使用 true。默认值为 false。
remote_h2d_transport_backend:vLLM 侧传输名称,供 Yuanrong 后端决定是否预注册设备内存。HIXL(默认)用于 HIXL HCCS(涵盖 buffer-pool、HIXL RoCE direct 和 FabricMem 子模式);P2P_TRANSFER 用于基于 RoCE 的 Datasystem P2P-Transfer。必须与 worker 侧 --remote_h2d_link_type 对应(有关 HIXL ↔ HCCS / P2P_TRANSFER ↔ ROCE 映射,请参见下文 Remote H2D 链路参数 表)。在 HIXL 下,除非 enable_fabric_mem 为 true,否则后端会预注册设备内存;在 P2P_TRANSFER 下,它会跳过预注册。
enable_fabric_mem:选择 HIXL FabricMem 模式。在该模式下,HIXL OPTION_ENABLE_USE_FABRIC_MEM 会自动处理 Fabric 可共享句柄交换,并且后端会跳过客户端侧 pre_register_device_memory。仅当 remote_h2d_transport_backend="HIXL" 时有意义。默认值为 false。FabricMem 需要 Datasystem 侧支持(HIXL FabricMem 构建以及对应的 Datasystem 环境变量);启用此标志前,请查阅 Datasystem 文档。
enable_dev_mem_pregister:客户端侧设备内存预注册(pre_register_device_memory)的主开关。默认值为 false,因此后端默认不预注册设备缓冲区指针。若要实际预注册,此标志必须为 true,并且必须满足自动条件:enable_remote_h2d=true、remote_h2d_transport_backend="HIXL" 和 enable_fabric_mem=false。在 P2P_TRANSFER 或 FabricMem 模式下,无论此开关如何,预注册始终会被跳过。对于需要客户端侧设备内存注册的 HIXL HCCS Remote H2D 部署,请将其设置为 true。
use_layerwise:必须与 kv_connector_extra_config.use_layerwise 一致。默认值为 false。当为 false 时,调度器侧的 Yuanrong store 会跳过初始化,因为非分层查找会委托给 TP0 worker。当为 true 时,调度器会初始化一个仅包含元数据的 Yuanrong 客户端,并禁用 Remote H2D,因此它不会创建 HIXL 引擎。
步骤 4.4.2:Remote H2D 要求¶
仅当 Remote Host-to-Device 传输已在 Yuanrong Datasystem 部署中启用并验证时,才将 enable_remote_h2d 设置为 true:
- 在启动 worker 之前,预留足够的 2 MiB HugeTLB 页面。对于 40 GiB 共享内存,至少预留 20480 个 2 MiB 大页。
- 启动每个 Datasystem worker 时启用 Remote H2D。worker 启动命令必须包含
--remote_h2d_device_ids、--enable_huge_tlb true、--arena_per_tenant 1和--enable_fallocate false。建议使用多个可用的 NPU 设备 ID,例如在 8-NPU 节点上使用"0,1,2,3,4,5,6,7"。
dscli start -w \
--worker_address "${WORKER_IP}:31501" \
--coordinator_address "${COORDINATOR_ADDRESS}" \
--log_dir "/var/log/yuanrong/worker" \
--shared_memory_size_mb 40960 \
--arena_per_tenant 1 \
--enable_huge_tlb true \
--enable_fallocate false \
--rpc_thread_num 64 \
--oc_thread_num 64 \
--enable_worker_worker_batch_get true \
--sc_regular_socket_num 0 \
--sc_stream_socket_num 0 \
--remote_h2d_device_ids "0,1,2,3,4,5,6,7"
对于 HIXL HCCS 链路(Atlas A3 且 HCCS 可达),设置
--remote_h2d_link_type "HCCS" 以及 HIXL 缓冲池参数。--worker_address
中的 IP 也会用作 HIXL 端点 IP,因此请使用可达地址,而不是
127.0.0.1 或 0.0.0.0。HIXL RoCE 直连模式是 HCCS 的子模式,通过在两端设置
HCCL_INTRA_ROCE_ENABLE=1 选择,并且还需要可达的 RoCE 链路:
dscli start --interleave 0-7 -w \
--worker_address "${WORKER_IP}:31501" \
--coordinator_address "${COORDINATOR_ADDRESS}" \
--log_dir "/var/log/yuanrong/worker" \
--shared_memory_size_mb 40960 \
--arena_per_tenant 1 \
--enable_huge_tlb true \
--enable_fallocate false \
--rpc_thread_num 64 \
--oc_thread_num 64 \
--enable_worker_worker_batch_get true \
--sc_regular_socket_num 0 \
--sc_stream_socket_num 0 \
--remote_h2d_device_ids "0,1,2,3,4,5,6,7" \
--remote_h2d_link_type "HCCS" \
--remote_h2d_hccs_buffer_pool "4:8"
远程 H2D 链路参数¶
| 参数 | 默认值 | 描述 |
|---|---|---|
remote_h2d_device_ids |
空 | 非空值启用 worker 侧 RH2D。逗号分隔的设备 ID,例如 "0,1,2,3,4,5,6,7"。 |
remote_h2d_link_type |
ROCE |
链路类型,区分大小写。ROCE 表示基于 RoCE 的 P2P-Transfer;HCCS 表示 HIXL HCCS(涵盖缓冲池、HIXL RoCE 直连和 FabricMem 子模式)。必须与 yuanrong.json 中客户端的 remote_h2d_transport_backend 对应(ROCE ↔ P2P_TRANSFER,HCCS ↔ HIXL)。对于 HCCS,客户端进程在启动 vLLM 之前还必须导出 DS_RH2D_LINK_TYPE=HCCS(后端不会自动导出);ROCE 是 Datasystem 默认值,无需环境变量。 |
remote_h2d_hccs_buffer_pool |
4:8 |
HIXL 缓冲池参数 <count>:<size>,仅在 remote_h2d_link_type=HCCS 时使用。在 HIXL RoCE 直连模式(HCCL_INTRA_ROCE_ENABLE=1)下会被忽略。 |
- 确保 Yuanrong Remote H2D 所需的 NPU 驱动、固件和 CANN 工具包已安装,并且对 worker 进程可见。在容器中,
挂载 Ascend 驱动路径、
npu-smi、hccn_tool、/etc/hccn.conf、/etc/ascend_install.info以及所需的/dev/davinci*设备。 - 在启用客户端标志之前,验证 NPU 和 RoCE 环境:
# Check the current 2 MiB HugeTLB page size, total count, and free count.
grep -E "HugePages_Total|HugePages_Free|Hugepagesize" /proc/meminfo
# Optional: check 2 MiB HugeTLB pages on each NUMA node.
for node in /sys/devices/system/node/node*/hugepages/hugepages-2048kB; do
echo "$node total=$(cat "$node/nr_hugepages") free=$(cat "$node/free_hugepages")"
done
# Check that NPU devices and the driver are visible to the worker environment.
npu-smi info
# Check that the NPU topology is visible.
npu-smi info -t topo
# Check optical module detection on the selected local NPU.
hccn_tool -i <local_npu_id> -optical -g
# Check RoCE physical link status. The expected link status is UP.
for i in {0..7}; do hccn_tool -i $i -link -g; done
# Check the selected NPU IP address and reachability to the remote NPU.
hccn_tool -i <local_npu_id> -ip -g
hccn_tool -i <local_npu_id> -ping -g address <remote_npu_ip>
如果这些检查失败,请保持 DS_ENABLE_REMOTE_H2D=0,并使用默认的
Datasystem 传输路径。
步骤 4.5:使用 Yuanrong 后端运行 AscendStoreConnector¶
使用 AscendStoreConnector 并将 backend 设置为 "yuanrong":
python3 -m vllm.entrypoints.openai.api_server \
--model /xxxxx/Qwen2.5-7B-Instruct \
--port 8100 \
--trust-remote-code \
--enforce-eager \
--no-enable-prefix-caching \
--tensor-parallel-size 1 \
--data-parallel-size 1 \
--max-model-len 10000 \
--block-size 128 \
--max-num-batched-tokens 4096 \
--kv-transfer-config \
'{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_both",
"kv_load_failure_policy": "recompute",
"kv_connector_extra_config": {
"lookup_rpc_port": "1",
"backend": "yuanrong",
"use_layerwise": false
}
}'
lookup_rpc_port 是 pooling scheduler 进程与 worker 进程之间使用的 RPC 端口。每个实例必须使用唯一的端口值。
注意事项¶
- Yuanrong 后端在调用 Datasystem 之前会对 KV 键进行规范化。最多 1024 字节的受支持 ASCII 键会被保留。更长的键或包含不受支持字符的键会被重写为最多 1024 个字符并附加哈希后缀,因此在调试后端存储时不要依赖原始键字符串。
- Yuanrong 无需额外的缓冲区预注册步骤。该后端在构建 blob 列表时直接使用设备指针。
5. 附录和常见问题¶
5.1. 环境变量说明¶
本节介绍 Mooncake 和 Memcache 两个后端所需的硬件相关环境变量。
| 硬件 | 依赖 | 导出命令 | 说明 |
|---|---|---|---|
| 950PR&950DT 产品 | HDK >=25.6 with mooncake >= v0.3.11CANN >= 9.1.0 | # UBOEexport ASCEND_GLOBAL_RESOURCE_CONFIG='{"comm_resource_config.protocol_desc":["uboe:device"]}' # UBexport ASCEND_LOCAL_COMM_RES='{"version":"1.3"}' |
根据所使用的通信协议配置所需的环境变量。 |
| 800 I/T A3 系列 | HDK >= 26.0or HDK >= 25.5 with mooncake >= v0.3.11CANN >= 9.0.0LingQu Computing Network >= 1.5 | export ASCEND_ENABLE_USE_FABRIC_MEM=1 |
推荐。启用统一内存地址直传方案。若使用 SSD 卸载,请参见 Fabric 内存大小对齐 — 内存大小必须按 1GB 对齐。 |
| 800 I/T A2 系列 | 建议 HDK >= 25.5 | export HCCL_INTRA_ROCE_ENABLE=1 |
800 I/T A2 系列上直传方案需要该变量。 |
5.2. Memcache 前提条件¶
5.2.1. 检查内存¶
使用 free -h 检查内存。如果缓存过多影响 KV 缓存池大小,请清理缓存并对内存进行碎片整理:
# 释放 pagecache/dentry/inode 以释放连续的物理内存
echo 3 > /proc/sys/vm/drop_caches
# 触发内存压缩以减少碎片
echo 1 > /proc/sys/vm/compact_memory
5.2.2. (仅 A3)扫描可用内存¶
通过运行脚本扫描环境中的可用内存。脚本地址:mem_scan.py。执行命令:
MemFabric 使用 2MB 和 1GB 的大页。默认情况下,脚本按 1GB 规格扫描。要扫描 2MB 大页的可用内存,请运行:
5.2.3. (仅 950PR&950DT 产品)禁用签名验证 + 在容器中挂载关键路径 + 安装内核包¶
步骤 1: 在裸机上禁用 HDK 签名验证(每台机器只需执行一次):
for i in {0..7}; do npu-smi set -t custom-op-secverify-enable -i $i -d 1; done;
for i in {0..7}; do npu-smi set -t custom-op-secverify-mode -i $i -d 0; done;
步骤 2: 参考以下 docker run 命令启动容器。确保 /usr/bin/urma_admin、/lib/route.conf、/etc/hccl_rootinfo.json 已挂载到容器中:
docker run -u root -it -d --name ${NAME} --net=host --privileged=true \
--device=/dev/davinci_manager --device=/dev/hisi_hdc --device=/dev/ummu --device=/dev/uburma \
--device=/dev/davinci0 \
--device=/dev/davinci1 \
--device=/dev/davinci2 \
--device=/dev/davinci3 \
--device=/dev/davinci4 \
--device=/dev/davinci5 \
--device=/dev/davinci6 \
--device=/dev/davinci7 \
-v /usr/bin/urma_admin:/usr/bin/urma_admin \
-v /lib/route.conf:/lib/route.conf \
-v /root/host:/root/host \
-v /usr/local/sbin/npu-smi:/usr/local/sbin/npu-smi \
-v /usr/local/sbin:/usr/local/sbin \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /var/log/npu/:/usr/slog \
-v /mnt:/mnt \
-v /etc/hccn.conf:/etc/hccn.conf \
-v /usr/lib64:/usr/lib64 \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/sbin/npu-smi:/usr/local/sbin/npu-smi \
-v /etc/hccl_rootinfo.json:/etc/hccl_rootinfo.json \
-v /home/:/home/ \
-v /etc/hixlep:/etc/hixlep \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-w /home \
${IMAGES_ID} \
bash
步骤 3: 在容器内更新 /lib/route.conf。
5.2.4. 启用 SSD 前的检查¶
使用 lsblk 检查磁盘状态。以 nvme1n1 为例,确保磁盘没有分区、没有挂载点,也没有文件系统签名:
lsblk /dev/nvme1n1 # No partitions expected
mount | grep nvme1n1 # No mount points expected
blkid /dev/nvme1n1 # No filesystem signature expected
如果没有可用的物理磁盘,可以使用 loop 设备模拟磁盘。参考以下命令:
# Create a 640GB image file (adjust count as needed)
dd if=/dev/zero of=/data/boostio_disk.img bs=1G count=640 status=progress
# Mount the loop device with direct_io enabled; the command outputs the actual device path
LOOP_DEV=$(losetup --find --show --direct-io=on /data/boostio_disk.img)
echo "${LOOP_DEV}"
# Example output: /dev/loop3, where /dev/loop3 is the simulated disk
5.3. Mooncake 常见问题¶
5.3.1. put/get 键操作失败¶
当 vLLM 报告 put 或 get 操作失败时,首先检查该错误是否由 Mooncake 自身报告。
- 如果错误由 Mooncake 报告:
- 对于
put失败,检查 Mooncake 日志中是否包含NO_AVAILABLE_HANDLE或BatchPut failed ... due to insufficient space。这通常表示驱逐后剩余空间不足以容纳一次BatchPut请求。请确保驱逐策略保留的空间(例如由1 - eviction_ratio隐含的容量)能够容纳一次批量 put,或者考虑增加可用容量、增加驱逐余量,或减小批量大小。 - 对于
get失败,检查 Mooncake 日志中是否包含lease_expired_before_data_transfer_completed key=...,或是否返回LEASE_EXPIRED。这表示 KV 对象租约在数据传输完成之前已过期。如有需要,请增大mooncake_master的--default_kv_lease_ttl,并保持其大于ASCEND_CONNECT_TIMEOUT和ASCEND_TRANSFER_TIMEOUT。
- 对于
- 如果错误不是由 Mooncake 报告,则很可能是 HIXL(ascend_direct)传输层问题。请收集
/root/ascend/log/debug/plog下的 plog 文件,并检查该问题是否匹配已知的 HIXL 问题。
关于 HIXL(ascend_direct)的常见故障排查和问题定位指导,请参见: https://gitcode.com/cann/hixl/wiki/HIXL%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%AE%9A%E4%BD%8D%E6%89%8B%E5%86%8C.md
5.3.2. SSD 常见问题¶
5.3.2.1. SSD offload 时出现 SEGMENT_NOT_FOUND¶
如果客户端日志显示 OffloadObjectHeartbeat failed, error code is SEGMENT_NOT_FOUND,则 Master 已卸载该 rank 的 LOCAL_DISK 段(通常发生在 Ping 停止刷新 TTL 后的 client_expired 之后)。该 rank 上的 SSD offload 会停止,直到该段重新注册。
典型触发条件(在 enable_cpu_binding=true 时): Mooncake 在初始化期间启动 Ping,随后 vLLM-Ascend 的 bind_cpus() 执行 migratepages/IRQ 绑定;Ping 线程未被固定,在默认 client_ttl=10 下可能错过心跳。
| 缓解措施 | 说明 |
|---|---|
| 临时措施: 提高 Master TTL | 例如 mooncake_master ... --client_ttl=120。请根据初始化/预热窗口进行调整(通常 60–120 即可)。这不会修复根本原因。 |
| 恢复措施: 升级 Mooncake | > v0.3.11 版本(main 分支)可以在 SEGMENT_NOT_FOUND 后重新挂载 LOCAL_DISK 并重新扫描元数据。这可以在清理后恢复;它不会防止元数据丢失期间发生过期或正在处理的请求失败。 |
| 根本修复: Mooncake Ping CPU 亲和性 | 将存储 Ping 线程固定到 release/隔离 CPU(需要 Mooncake 侧修改)。可选地由 vLLM-Ascend 配合,按 rank 传递 release CPU。 |
调试重启时,也请同时重启 Master 和 vLLM,以避免陈旧的 segment_already_exists 状态。
5.3.2.2. Fabric 内存大小对齐(A3 + ASCEND_ENABLE_USE_FABRIC_MEM=1)¶
在启用 Fabric 内存的 A3 上,每次 Fabric 内存分配都必须是 1 GB(1073741824 字节)的整数倍。Mooncake 不会自动向上取整大小。
| 参数 | 配置来源 | 对齐要求 |
|---|---|---|
global_segment_size |
mooncake.json 或导出 MOONCAKE_GLOBAL_SEGMENT_SIZE |
每个 rank 的段大小必须对齐到 1GB(例如 "1GB"、"20GB")。 |
| 参数 | 配置来源 | 对齐 |
|---|---|---|
MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES |
export MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES(仅在 enable_ssd_offload=true 时) |
必须对齐到 1GB。默认值为 1280 MB(1.25 GB),未对齐,且对于长上下文 SSD 加载来说过小——请按照 设置 MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES 大小 进行设置。 |
mooncake.json 中的 local_buffer_size 在 fabric mem 下不使用(vLLM-Ascend 会向 setup() 传递 0)。
未对齐的风险: adxl MallocMem / aclrtMapMem 会因 Invalid_Argument 失败。启用 SSD offload 时,MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES 分配失败可能在 FileStorage 初始化期间导致段错误,并中止 vLLM 启动。避免使用诸如 "1280MB"、"512MB" 或 "1.5GB" 的值。
Fabric mem 配额: global_segment_size 和 MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES 都是每个 rank 独立的 fabric mem 分配。它们的大小会累加到通过 ASCEND_GLOBAL_RESOURCE_CONFIG 配置的 HIXL fabric mem 限制上(例如 "fabric_memory.max_capacity":32,单位为每进程 GB——参见 HIXL 文档)。每个 rank 的大致预算:
fabric_memory.max_capacity ≥ global_segment_size + MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES (+ headroom)
配额过低的风险: 某些 rank 会在 global_segment_size 成功但 MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES 分配失败后,以 Memory_Allocation_Failure(EL0004) 失败。请增大 fabric_memory.max_capacity,减小 global_segment_size 或 MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES,或确保节点拥有足够的主机内存。
示例(在启用 SSD offload 时,将其添加到 vLLM 启动脚本中):
export ASCEND_ENABLE_USE_FABRIC_MEM=1
export MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES=1073741824 # 1 GB, fabric-mem aligned
仅在 fabric mem 过低时设置 ASCEND_GLOBAL_RESOURCE_CONFIG。
# Per-rank fabric mem budget: 20 GB segment + 1 GB MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES → set max_capacity ≥ 22 (GB)
export ASCEND_GLOBAL_RESOURCE_CONFIG='{"fabric_memory.max_capacity":32}'
5.3.2.3. 设置 MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES 大小¶
当 enable_ssd_offload=true 时,Mooncake 会分配一个独立的、每个 rank 的 SSD 读写缓冲区,其大小由 MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES 决定。该缓冲区与 mooncake.json 中的 global_segment_size 相互独立——增大 segment 并不能修复由过小的 MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES 导致的 BUFFER_OVERFLOW。
如果缓冲区过小,SSD 读取会在 FileStorage::AllocateBatch 期间以 BUFFER_OVERFLOW(error_code=-10)失败,并且当 kv_load_failure_policy=fail 时 vLLM 可能会失败。
如果在使用过程中遇到 BUFFER_OVERFLOW,请尝试增大 MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES。不要将其设置为高于 vLLM worker 日志中显示的 Available KV cache memory 值:
示例:
仅使用字节字面量(10737418240)。10G / 10GB 会被忽略,并回退到 1280 MB 默认值。
说明
--max-num-batched-tokens仅对 prefill 计算进行分块;它不会减少MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES所需的内存。
主机内存预算(单节点)¶
MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES 是每个 rank 分配的,此外还有 global_segment_size:
host_memory_for_mooncake ≈ TP × (global_segment_size + MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES + local_buffer_size)
确保主机上 free -h 的 available 值超过该总和加上 vLLM 开销。MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES 不需要容纳在 global_segment_size 内部。
调优后验证¶
- 启动时:每个 rank 会记录
AlignedClientBufferAllocator: allocated <N> bytes,其中<N>为你配置的大小。 - 负载下:没有
BUFFER_OVERFLOW/Failed to get ... keys out of ... error_codes=[-10]。 - 如果使用较大缓冲区后失败仍然存在,请检查重叠加载(
load_async)。
5.4. Memcache 常见问题¶
- 预操作步骤:
- 有关 Memcache 故障排查,请参见: https://gitcode.com/Ascend/memcache/wiki/FAQ.md
5.5. DSv4 已知问题(临时)¶
有关临时的 DSv4 已知问题,请参见: https://github.com/vllm-project/vllm-ascend/issues/9975
5.6. ASCEND_GLOBAL_RESOURCE_CONFIG¶
ASCEND_GLOBAL_RESOURCE_CONFIG 是传递给 HIXL 的 JSON 字符串。常见字段如下:
| 字段 | 描述 |
|---|---|
| 字段 | 描述 |
|---|---|
comm_resource_config.protocol_desc |
顶层 Mooncake 传输引擎的协议描述符。在 PD 分离中,它控制 MooncakeConnectorV1 PD 传输路径。示例值包括 ["hccs:device"] 和 ["roce:device"]。 |
store.comm_resource_config.protocol_desc |
AscendStoreConnector 使用的 Mooncake Store 流量的协议描述符。在 A3 上,可将其设置为 ["roce:device"],同时 PD 传输使用 HCCS。 |
comm_resource_config.listen_port |
单边通信监听端口。HIXL 默认值为 16666;对于独立的 mooncake_client 进程,请使用其他端口,以避免与内嵌客户端发生冲突。 |
fabric_memory.max_capacity |
每个进程的 Fabric 内存配额,单位为 GB。仅在 Fabric 内存预算过小时使用;参见 Fabric 内存大小对齐。 |
Store/PD 流量分离要求 CANN >= 9.1.0。该功能面向 A3 和 950PR&950DT Products 部署,在这些部署中,PD 传输流量可使用 HCCS,Mooncake Store 流量可使用 ROCE,从而避免两类流量在同一物理链路上竞争。有关更多 HIXL 部署模式,请参阅 Mooncake + HIXL 池化方案总览。
5.7. QoS 配置¶
Mooncake 和 Memcache 后端均支持配置传输 QoS。有效范围为 0-4(仅限整数),未配置时 默认值为 0。数值越大,传输优先级越高。无效值(非整数、超出范围)会导致启动快速失败,并产生验证错误。
可通过 kv_connector_extra_config 配置 QoS,它会在 store 初始化前自动注入到后端特定配置中:
--kv-transfer-config \
'{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {
"qos_priority": 1,
"lookup_rpc_port": "1",
"backend": "mooncake",
"use_layerwise": false
}
}'
说明¶
kv_connector_extra_config的值优先于环境中已设置的值;当它覆盖不同的现有值时,会记录一条警告。- 对于 Mooncake,
qos_priority字段会合并到现有的ASCEND_GLOBAL_RESOURCE_CONFIG中(其他字段(如protocol_desc)会保留)。如果未设置ASCEND_GLOBAL_RESOURCE_CONFIG,配置qos_priority会创建该配置,同时选择独立于 store 的传输引擎路径(参见 5.6)。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 vl/vllm-ascend