KV Cache Pool (Ascend Store) Deployment Guide¶
Contents¶
- Environmental Dependencies
- Example of using Mooncake as a KV Pool backend
- Example of using Memcache as a KV Pool backend
- Example of using Yuanrong as a KV Pool backend
- FAQ
Environmental Dependencies¶
- Software:
- CANN >= 8.5.0
- vLLM: main branch
- vLLM-Ascend: main branch
- mooncake: >= 0.3.11.post1
KV Pool Parameter Description¶
kv_load_failure_policy: KV Load Failure Handling Policy¶
kv_load_failure_policy is a top-level field in kv-transfer-config.
recompute: When KV loading fails, vLLM rolls the request back to the last valid prefix and reschedules it to recompute the failed KV blocks. Hybrid attention models (e.g. DeepSeekV4, Qwen 3.5) are not supported yet.fail: When KV loading fails, the affected request is terminated directly with an error.
The default value in vLLM is fail. If you want the request to fall back to recomputation after a KV load failure, set it to recompute.
When MultiConnector is used, configure kv_load_failure_policy on the MultiConnector top-level kv-transfer-config instead of the child connectors.
kv_connector_extra_config: Additional Configurable Parameters for Pooling¶
| Parameter | Description |
|---|---|
lookup_rpc_port |
Port for RPC Communication Between Pooling Scheduler Process and Worker Process: Each Instance Requires a Unique Port Configuration. |
load_async |
Whether to Enable Asynchronous Loading. The default value is false. |
backend |
Set the storage backend for kvpool (mooncake, memcache, yuanrong), with the default being mooncake. |
consumer_is_to_put |
Whether Decode node put KV Cache into KV Pool. The default value is false. |
consumer_is_to_load |
Whether Decode node load KV cache from KV Pool. The default value is false. |
use_layerwise |
Enable layer-by-layer KV save/load. Only supported on the Prefill node and requires the memcache backend. The default value is false. |
prefill_pp_size |
Prefill PP size, needs to be set when Prefill node enables PP. |
prefill_pp_layer_partition |
Prefill PP layer partition, needs to be set when Prefill node enables PP. |
Environment Variable Configuration¶
To guarantee uniform hash generation, it is required to synchronize the PYTHONHASHSEED environment variable across all nodes upon enabling KV Pool.
Example of using Mooncake as a KV Pool backend¶
-
Software:
-
Check Configuration:
Ensure that the hccn.conf file exists in the environment. If using Docker, mount it into the container.
For Ascend 950 Products, additionally mount: * devices:
/dev/ummu,/dev/uburma* commands:/usr/bin/urma_admin* configurations:/lib/route.conf,/etc/hccl_rootinfo.json -
Install Mooncake
Mooncake is the serving platform for Kimi, a leading LLM service provided by Moonshot AI. The Mooncake wheel requires glibc 2.35 or later. Check the installed glibc version before installation:
Install Mooncake with pip:
-
Environment Variables Description¶
| Hardware | Dependencies | Export Command | Description |
|---|---|---|---|
| Ascend 950 Products | HDK >=25.6 with mooncake >= v0.3.11 CANN >= 9.1.0 |
# UBOEexport ASCEND_GLOBAL_RESOURCE_CONFIG='{"comm_resource_config.protocol_desc":["uboe:device"]}' # UB export ASCEND_LOCAL_COMM_RES='{"version":"1.3"}' |
Configure the required environment variables based on the communication protocol to use. |
| 800 I/T A3 series | HDK >= 26.0 or HDK >= 25.5 with mooncake >= v0.3.11 CANN >= 9.0.0 LingQu Computing Network >= 1.5 |
export ASCEND_ENABLE_USE_FABRIC_MEM=1 |
Recommended. Enables unified memory address direct transmission scheme. With SSD offload, see Fabric memory size alignment — memory sizes must be aligned to 1GB. |
| 800 I/T A3 series | RoCE-based deployment | export HCCL_INTRA_ROCE_ENABLE=1 |
Required when the deployment uses the RoCE path. |
| 800 I/T A2 series | HDK >= 25.5 is recommended | export HCCL_INTRA_ROCE_ENABLE=1 |
Required by direct transmission scheme on 800 I/T A2 series |
Note:
ASCEND_BUFFER_POOLhas been removed. UseASCEND_ENABLE_USE_FABRIC_MEM=1for A3 HCCS scenarios orHCCL_INTRA_ROCE_ENABLE=1for A2/A3 RoCE scenarios instead.
Run Mooncake Master¶
Note: Before proceeding, review the following Mooncake guides:
1. Configure mooncake.json¶
The environment variable MOONCAKE_CONFIG_PATH is configured to the full path where mooncake.json is located.
{
"metadata_server": "P2PHANDSHAKE",
"protocol": "ascend",
"device_name": "",
"master_server_address": "xx.xx.xx.xx:50088",
"global_segment_size": "1GB" (1024MB/1048576KB/1073741824Byte/1073741824),
"preferred_segment": false,
"prefer_alloc_in_same_node": true
}
metadata_server: Configured as P2PHANDSHAKE. protocol: Must be set to 'Ascend' on the NPU. device_name: "" master_server_address: Configured with the IP and port of the master service. It can also be set via the MOONCAKE_MASTER environment variable, which takes precedence over this configuration item (useful for injecting the master address through Kubernetes). global_segment_size: Registered memory size per card to the KV Pool. Needs to be aligned to 1GB. It can also be set via the MOONCAKE_GLOBAL_SEGMENT_SIZE environment variable, which takes precedence over this configuration item. preferred_segment: Whether to prefer storing KV on the local segment when putting objects to the KV Pool. Defaults to false. prefer_alloc_in_same_node: Whether to prefer allocating KV on the same node. Defaults to true.
2. Start mooncake_master¶
Under the mooncake folder:
mooncake_master --port 50088 --eviction_high_watermark_ratio 0.9 --eviction_ratio 0.1 --default_kv_lease_ttl 11000
eviction_high_watermark_ratio determines the watermark where Mooncake Store will perform eviction, and eviction_ratio determines the portion of stored objects that would be evicted.
default_kv_lease_ttl controls the default lease TTL for KV objects (milliseconds); configure it via --default_kv_lease_ttl and keep it larger than ASCEND_CONNECT_TIMEOUT and ASCEND_TRANSFER_TIMEOUT.
PD Disaggregation Scenario¶
1. Run prefill Node and decode Node¶
Using MultiConnector to simultaneously utilize both MooncakeConnectorV1 and AscendStoreConnector. MooncakeConnectorV1 performs kv_transfer, while AscendStoreConnector serves as the prefix-cache node.
prefill Node:
The content of the multi_producer.sh script:
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:$LD_LIBRARY_PATH
export PYTHONHASHSEED=0
export PYTHONPATH=$PYTHONPATH:/xxxxx/vllm
export MOONCAKE_CONFIG_PATH="/xxxxxx/mooncake.json"
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3
export ACL_OP_INIT_MODE=1
#A3
export ASCEND_ENABLE_USE_FABRIC_MEM=1
#A2
#export HCCL_INTRA_ROCE_ENABLE=1
#Ascend 950 Products UBOE
#export ASCEND_GLOBAL_RESOURCE_CONFIG='{"comm_resource_config.protocol_desc":["uboe:device"]}'
#Ascend 950 Products UB
#export ASCEND_LOCAL_COMM_RES='{"version":"1.3"}'
#Minimum retransmission timeout of the RDMA, equals 4.096 μs * 2 ^ timeout.
#Needs to satisfy the equation: ASCEND_TRANSFER_TIMEOUT > RDMA_TIMEOUT * 7, where 7 is the default number of retry for RDMA transfer.
#HCCL_RDMA_TIMEOUT also affects collective communication behavior and should be configured carefully.
export HCCL_RDMA_TIMEOUT=17
# Unit: ms. The timeout for one-sided communication connection establishment is set to 10 seconds by default (see PR: https://github.com/kvcache-ai/Mooncake/pull/1039). Users can adjust this value based on their specific setup.
# The recommended formula is: ASCEND_CONNECT_TIMEOUT = connection_time_per_card (typically within 500ms) × total_number_of_Decode_cards.
# This ensures that even in the worst-case scenario—where all Decode cards simultaneously attempt to connect to the same Prefill card the connection will not time out.
export ASCEND_CONNECT_TIMEOUT=10000
# Unit: ms. The timeout for one-sided communication transfer is set to 10 seconds by default (see PR: https://github.com/kvcache-ai/Mooncake/pull/1039).
export ASCEND_TRANSFER_TIMEOUT=10000
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 32768 \
--block-size 128 \
--max-num-batched-tokens 16384 \
--kv-transfer-config \
'{
"kv_connector": "MultiConnector",
"kv_role": "kv_producer",
"kv_load_failure_policy": "recompute",
"kv_connector_extra_config": {
"connectors": [
{
"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_producer",
"kv_port": "20001",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 1,
"tp_size": 1
},
"decode": {
"dp_size": 1,
"tp_size": 1
}
}
},
{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_producer",
"kv_connector_extra_config": {
"lookup_rpc_port":"0",
"backend": "mooncake"
}
}
]
}
}'
decode Node:
The content of multi_consumer.sh:
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:$LD_LIBRARY_PATH
export PYTHONPATH=$PYTHONPATH:/xxxxx/vllm
export PYTHONHASHSEED=0
export MOONCAKE_CONFIG_PATH="/xxxxx/mooncake.json"
export ASCEND_RT_VISIBLE_DEVICES=4,5,6,7
export ACL_OP_INIT_MODE=1
#A3
export ASCEND_ENABLE_USE_FABRIC_MEM=1
#A2
#export HCCL_INTRA_ROCE_ENABLE=1
#Ascend 950 Products UBOE
#export ASCEND_GLOBAL_RESOURCE_CONFIG='{"comm_resource_config.protocol_desc":["uboe:device"]}'
#Ascend 950 Products UB
#export ASCEND_LOCAL_COMM_RES='{"version":"1.3"}'
export HCCL_RDMA_TIMEOUT=17
export ASCEND_CONNECT_TIMEOUT=10000
export ASCEND_TRANSFER_TIMEOUT=10000
python3 -m vllm.entrypoints.openai.api_server \
--model /xxxxx/Qwen2.5-7B-Instruct \
--port 8200 \
--trust-remote-code \
--enforce-eager \
--no-enable-prefix-caching \
--tensor-parallel-size 1 \
--data-parallel-size 1 \
--max-model-len 32768 \
--block-size 128 \
--max-num-batched-tokens 16384 \
--kv-transfer-config \
'{
"kv_connector": "MultiConnector",
"kv_role": "kv_consumer",
"kv_load_failure_policy": "recompute",
"kv_connector_extra_config": {
"connectors": [
{
"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_consumer",
"kv_port": "20002",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 1,
"tp_size": 1
},
"decode": {
"dp_size": 1,
"tp_size": 1
}
}
},
{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_consumer",
"kv_connector_extra_config": {
"lookup_rpc_port":"0",
"backend": "mooncake"
}
}
]
}
}'
Currently, the key-value pool in PD Disaggregate only stores the kv cache generated by the Prefill node by default. In models using MLA, it is now supported that the Decode node stores the kv cache for use by the Prefill node, enabled by adding consumer_is_to_put: true to the AscendStoreConnector. If the Prefill node enables PP, prefill_pp_size or prefill_pp_layer_partition also needs to be set. Example as follows:
{
"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. Start 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
Change localhost to your actual IP address.
3. Run Inference¶
Configure the localhost, port, and model weight path in the command to your own settings.
Short question:
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 }'
Long question:
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 }'
PD-Mixed Inference¶
1. Run Mixed Deployment Script¶
Content of pd_mix.sh:
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages:$LD_LIBRARY_PATH
export PYTHONPATH=$PYTHONPATH:/xxxxx/vllm
export MOONCAKE_CONFIG_PATH="/xxxxxx/mooncake.json"
export ASCEND_RT_VISIBLE_DEVICES=0,1,2,3
export PYTHONHASHSEED=0
export ACL_OP_INIT_MODE=1
#A3
export ASCEND_ENABLE_USE_FABRIC_MEM=1
#A2
#export HCCL_INTRA_ROCE_ENABLE=1
#Ascend 950 Products UBOE
#export ASCEND_GLOBAL_RESOURCE_CONFIG='{"comm_resource_config.protocol_desc":["uboe:device"]}'
#Ascend 950 Products UB
#export ASCEND_LOCAL_COMM_RES='{"version":"1.3"}'
export HCCL_RDMA_TIMEOUT=17
export ASCEND_CONNECT_TIMEOUT=10000
export ASCEND_TRANSFER_TIMEOUT=10000
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 32768 \
--block-size 128 \
--max-num-batched-tokens 16384 \
--kv-transfer-config \
'{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_both",
"kv_load_failure_policy": "recompute",
"kv_connector_extra_config": {
"lookup_rpc_port":"1",
"backend": "mooncake"
}
}' > mix.log 2>&1
2. Run Inference¶
Configure the localhost, port, and model weight path in the command to your own settings. The requests sent will only go to the port where the mixed deployment script is located, and there is no need to start a separate proxy.
Short question:
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 }'
Long question:
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 }'
Note: For MooncakeStore with RoCE-based Device-to-Device communication enabled, it is recommended to perform a warm-up phase before running actual performance benchmarks.
This is because HCCL one-sided communication connections are created lazily after the instance is launched when Device-to-Device communication is involved. Currently, full-mesh connections between all devices are required. Establishing these connections introduces a one-time time overhead and persistent device memory consumption (4MB of device memory per connection).
For warm-up, it is recommended to issue requests with an input sequence length of 8K and an output sequence length of 1, with the total number of requests being 2–3× the number of devices (cards/dies).
Enable MooncakeStore SSD Offload with Embedded Real Client Mode¶
- Requires mooncake >= v0.3.11.
Start the master¶
Start Mooncake master as described in Run Mooncake Master. To enable SSD offload, add --enable_offload=true to the same master startup command. For example:
mooncake_master --port 50088 --eviction_high_watermark_ratio 0.9 --eviction_ratio 0.1 --default_kv_lease_ttl 11000 --enable_offload=true --client_ttl=120
| Field | Description |
|---|---|
enable_offload |
Set to true to enable SSD offload in Mooncake master. Keep the master port aligned with master_server_address in mooncake.json. |
client_ttl |
Seconds a client stays alive after the last Ping. CLI default is 10; see SEGMENT_NOT_FOUND with SSD offload. |
Configuration¶
Starting from the mooncake.json configured in Run Mooncake Master, add the following SSD offload fields:
| Field | Description |
|---|---|
enable_ssd_offload |
Set to true to enable SSD offload. Environment variables are not supported. |
ssd_offload_path |
Required when enable_ssd_offload is true. Absolute path to a local directory where Mooncake stores offloaded KV data (for example, /nvme/mooncake_offload). The directory must exist and be writable by the vLLM process; create it before startup (mkdir -p <path>). Relative paths, symbolic links, and paths containing .. are rejected by Mooncake. Passed to MooncakeDistributedStore.setup() as the SSD storage root (equivalent to MOONCAKE_OFFLOAD_FILE_STORAGE_PATH in standalone clients). Configure this field in mooncake.json only; environment variables are not supported. |
Running the Embedded Real Client¶
With Mode A (Embedded Real Client), Mooncake is embedded in vLLM. When the vLLM service starts, AscendStoreConnector / MooncakeBackend automatically calls MooncakeDistributedStore.setup() using the settings in mooncake.json (including enable_ssd_offload and ssd_offload_path when SSD offload is enabled). No separate mooncake_client process is required.
SSD Disk Usage Control¶
The following environment variables control disk space usage for SSD offload (bucket backend):
| Environment Variable | Default | Description |
|---|---|---|
MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES |
1342177280 (1280MB) |
Per-rank SSD read/write buffer size in bytes. Not configurable in mooncake.json. If you hit BUFFER_OVERFLOW, increase this value — see Sizing MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES. On A3 with ASCEND_ENABLE_USE_FABRIC_MEM=1, must be aligned to 1GB and counts toward per-rank fabric mem quota (see Fabric memory size alignment). |
MOONCAKE_OFFLOAD_BUCKET_MAX_TOTAL_SIZE |
0 |
Eviction threshold in bytes. When set to 0, the backend uses 90% of the physical disk capacity as the quota. Set an explicit value to control disk usage precisely. |
MOONCAKE_OFFLOAD_BUCKET_EVICTION_POLICY |
none |
Eviction policy: none (writes fail when full), fifo, or lru. |
MOONCAKE_OFFLOAD_TOTAL_SIZE_LIMIT_BYTES |
2199023255552 (2 TB) |
Per-rank maximum disk usage reported to Mooncake master. Master aggregates this across clients (roughly 2 TB × rank count in the SSD Storage total). Always override to match real disk capacity — the default often exceeds available space. |
MOONCAKE_OFFLOAD_TOTAL_SIZE_LIMIT_BYTES risk: If left at the 2 TB default, master shows a total SSD quota far larger than the physical disk (e.g. 16 ranks → ~32 TB displayed on a 1 TB NVMe). Offload still fails when the disk fills, while monitoring looks healthy. Set this to your actual per-rank budget before production use.
Since each TP rank uses an independent SSD subdirectory (rank_0/, rank_1/, ...) under ssd_offload_path, all ranks share the same physical disk. To prevent a single rank from consuming excessive space, set an explicit per-rank quota. For example, with an 800 GB disk and 8 TP ranks:
# 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 # 1GB
Example of using Memcache as a KV Pool backend¶
Installing Memcache¶
Memcache depends on MemFabric. Therefore, MemFabric must be installed. Installing the memcache after the MemFabric is installed.
Configuring the memcache Config File¶
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.log_level = error
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 = error
ock.mmc.local_service.world_size = 256
ock.mmc.local_service.protocol = device_sdma
ock.mmc.local_service.dram.size = 1GB
Key Focuses:
| Parameter | Description |
|---|---|
ock.mmc.meta_service_url |
Configure the endpoint of MetaService. The P node and D node should be configured with the same MetaService endpoint. |
ock.mmc.meta_service.config_store_url |
Configure the Config Store endpoint used by MetaService. |
ock.mmc.local_service.config_store_url |
Configure the Config Store endpoint used by LocalService. Its value must be the same as ock.mmc.meta_service.config_store_url in mmc-meta.conf. |
ock.mmc.local_service.world_size |
Maximum number of supported LocalService, including services that will be added in the future. |
ock.mmc.local_service.protocol |
The recommended protocols are device_rdma (RDMA over device, supported for A2 and A3 when device RoCE is available, recommended for A2) and device_sdma (SDMA over device, supported for A3 when HCCS is available, recommended for A3). For details about other supported protocols, see the MemCache LocalService configuration file. |
ock.mmc.local_service.dram.size |
Sets the DRAM capacity provided by the current LocalService. |
Run Memcache MetaService¶
Starting the MetaService service.
Run pip show memcache_hybrid and find the Location value in the output. Use that value as {INSTALL_PATH} below.
export MMC_META_CONFIG_PATH={INSTALL_PATH}/memcache_hybrid/config/mmc-meta.conf
python -c "from memcache_hybrid import MetaService; MetaService.main()"
PD Disaggregation Scenario¶
1. Run prefill Node and decode Node¶
Using MultiConnector to simultaneously utilize both MooncakeConnectorV1 and AscendStoreConnector. MooncakeConnectorV1 performs kv_transfer, while AscendStoreConnector enables KV Cache Pool
800I A2/800T A2/800I A3/800T A3 Series¶
run_prefill.sh/run_decode.sh:
#!/bin/bash
ROLE="prefill" # prefill / decode
HARDWARE_SERIES="A2" # A2 (800I/800T A2) or A3 (800I/800T A3)
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
export MMC_LOCAL_CONFIG_PATH=/home/memcache/mmc-local.conf
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
if [ "$HARDWARE_SERIES" == "A2" ]; 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
elif [ "$HARDWARE_SERIES" == "A3" ]; then
export ACL_OP_INIT_MODE=1
else
echo "Error: Invalid HARDWARE_SERIES. Set to 'A2' or 'A3'."
exit 1
fi
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
export PYTHONHASHSEED=0
export HCCL_BUFFSIZE=1024
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_USE_V1=1
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'"
}
}
]
}
}'
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"
2. Start proxy_server¶
Refer to Start proxy_server in the MooncakeStore deployment section.
3. Run Inference¶
Refer to Run Inference in the MooncakeStore deployment section.
PD-Mixed Scenario¶
1. Run Mixed Deployment Script¶
800I A2/800T A2/800I A3/800T A3 Series¶
Run_pd_mix.sh:
#!/bin/bash
HARDWARE_SERIES="A2" # A2 (800I/800T A2) or A3 (800I/800T A3)
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
export MMC_LOCAL_CONFIG_PATH=/home/memcache/mmc-local.conf
echo "Starting vLLM on Series: $HARDWARE_SERIES"
rm -rf /root/ascend/log/*
rm -rf ./connector.log
if [ "$HARDWARE_SERIES" == "A2" ]; 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
elif [ "$HARDWARE_SERIES" == "A3" ]; then
export ACL_OP_INIT_MODE=1
else
echo "Error: Invalid HARDWARE_SERIES. Set to 'A2' or 'A3'."
exit 1
fi
source /usr/local/Ascend/ascend-toolkit/set_env.sh
source /usr/local/Ascend/nnal/atb/set_env.sh
export PYTHONHASHSEED=0
export HCCL_BUFFSIZE=1024
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export VLLM_USE_V1=1
KV_CONFIG='{
"kv_connector": "AscendStoreConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {
"backend": "memcache",
"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. Run Inference¶
Enable Memcache SSD Cache¶
- Requires
memcache_hybrid >= 1.2.0. - Requires UBS IO. Starting from
memcache_hybrid 1.2.0, UBS IO is built into Memcache and does not need to be installed separately.
Configuration¶
Starting from the mmc-local.conf configured in Configuring the memcache Config File, add the following SSD cache fields:
ock.mmc.local_service.storage.enabled = true
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
| Field | Description |
|---|---|
ock.mmc.local_service.storage.enabled |
Set to true to enable SSD caching. |
ubsio.disk.path |
Required when SSD caching is enabled. Specify the target SSD block devices, partitions, or loop devices directly. The configured devices must be exclusively used by UBS IO and must not have any mount points. Separate multiple paths with colons (:). |
ubsio.mem.size_in_gb |
Per-process UBS IO memory pool size in GB. The recommended value is 10. The supported range is an integer from 0 to 3072; SSD caching requires at least 5 GB per process. The total allocation must not exceed the node memory available after reserving memory for the operating system, vLLM, and the Memcache DRAM pool. |
ubsio.standalone.device_count |
Number of local services whose ock.mmc.local_service.dram.size is not 0. |
ubsio.standalone.force_new_disk |
Controls whether UBS IO initializes the configured SSD devices as new disks instead of recovering their existing metadata. Set to true because the current version does not support fault recovery. |
When adjusting the recommended value, calculate the maximum permitted per-process value by dividing the node memory available to UBS IO by the number of DRAM-enabled local services, rounding down, and capping the result at 3072:
maximum ubsio.mem.size_in_gb = min(3072, floor(available node memory for UBS IO (GB) / number of DRAM-enabled local services))
For example, if 200 GB is available to UBS IO and four local services have DRAM enabled, the upper limit is 50 GB per process, so the recommended value ubsio.mem.size_in_gb = 10 is valid. If the calculated upper limit is less than 5, free more node memory or reduce the number of DRAM-enabled local services.
For SSD caching, 10 GB per process is generally sufficient and does not need to be configured much larger. If you want to use the L2.5 memory caching capability, increase ubsio.mem.size_in_gb within the limits above and adjust ubsio.wcache.evict_water_level accordingly.
For disk config, eviction watermarks, and other UBS IO parameters, see the DRAM + SSD Multi-level Pooling Configuration Guide.
Separated Deployment of MemCache and vLLM¶
This deployment mode runs MemCache and vLLM in different processes. It is different from vLLM PD disaggregation. In the default co-located mode, vLLM loads the model weights before the KV connector initializes MemCache. As a result, MemCache may not be able to reserve sufficient memory from the remaining available space. Starting a standalone MemCache process before vLLM allows MemCache to reserve a larger memory pool.
Prepare two LocalService configuration files with the same connection and protocol settings. The configuration used by the vLLM process does not contribute DRAM:
# mmc-local.conf used by the vLLM process
ock.mmc.local_service.dram.size = 0GB
ock.mmc.local_service.max.dram.size = 1024GB
The configuration used by the standalone MemCache process specifies the amount of DRAM to contribute:
# 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
The preceding sizes are examples. Adjust them according to the available memory, and set ock.mmc.local_service.max.dram.size to accommodate the maximum dram.size used by the LocalService processes.
Deploy the services in the following order:
- Start MetaService as described above.
- Before starting vLLM, start a standalone MemCache process with
mmc-local-standalone.confon every node. These processes contribute the configured DRAM to the memory pool. - Wait until the standalone MemCache process reports successful initialization on every node.
- Set
MMC_LOCAL_CONFIG_PATHtommc-local.conf, and then start the vLLM inference processes as described above. MemCache in the vLLM processes connects to the existing memory pool without contributing additional DRAM.
For the standalone MemCache startup script and the complete A3 deployment procedure, see https://gitcode.com/Ascend/memcache/wiki/MemCache+vLLM+A3%E5%88%86%E7%A6%BB%E9%83%A8%E7%BD%B2%E6%A1%88%E4%BE%8B.md.
Example of using Yuanrong as a KV Pool backend¶
- Software:
- Install
openyuanrong-datasystemon all nodes (yr.datasystemmust be importable).
- Install
Install Yuanrong Datasystem¶
If the prebuilt package does not match the CANN or Ascend driver version in your environment, build Yuanrong Datasystem from source in the vLLM Ascend image. Follow the official Yuanrong Datasystem build instructions: https://atomgit.com/openeuler/yuanrong-datasystem
Start etcd¶
Yuanrong Datasystem uses etcd for service discovery. The following example starts a single-node etcd cluster:
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
For production environments, refer to the official etcd clustering documentation: https://etcd.io/docs/v3.7/op-guide/clustering/
Start Datasystem Worker¶
Start a Datasystem worker on each node by using dscli. The following
configuration is a recommended starting point for high-throughput KV Pool
workloads:
WORKER_LOG_DIR="/var/log/yuanrong/worker"
sudo mkdir -p "${WORKER_LOG_DIR}"
sudo chown "$(id -u):$(id -g)" "${WORKER_LOG_DIR}"
dscli start --interleave 0-7 -w \
--worker_address "${WORKER_IP}:31501" \
--etcd_address "${ETCD_IP}:2379" \
--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
The --worker_address value is consumed later as worker_addr in
yuanrong.json, so keep the host and port identical on the same node.
The tuning parameters above have the following effects:
| Parameter | Description |
|---|---|
interleave=0-7 |
Sets the NUMA memory interleaving policy, round-robining page allocations across NUMA nodes 0-7. Spread the large worker shared memory across all NUMA nodes to avoid single-node memory imbalance; adjust the node range to match the host's actual NUMA topology (e.g. 0-3 on a 4-node host, or all). Place this option before -w because -w consumes the remaining arguments. |
log_dir |
Sets the Datasystem worker log directory. Create the directory and grant the worker process write permission before startup. |
arena_per_tenant=1 |
Uses one shared-memory arena per tenant as a conservative starting point for memory and file-descriptor usage. |
enable_huge_tlb=true |
Backs worker shared memory with HugeTLB pages. Reserve enough 2MiB huge pages before starting the worker. |
enable_fallocate=false |
Disables fallocate for the shared-memory file; use this setting with the HugeTLB configuration above. |
rpc_thread_num=64 |
Sets the RPC/ZMQ service concurrency. |
oc_thread_num=64 |
Sets the Object Cache business-thread pool size. |
enable_worker_worker_batch_get=true |
Enables batched Object Cache reads between Datasystem workers. |
sc_regular_socket_num=0, sc_stream_socket_num=0 |
Disables the Stream Cache service. Both values must be greater than zero to enable it; keep them at zero when KV Pool does not use Stream Cache. |
For shared_memory_size_mb=40960, reserve at least 20480 2MiB huge pages and
verify that they are available before starting the worker:
Worker logs, including files whose base name is normally
datasystem_worker, are written under the --log_dir directory. Use an
absolute path so the log location does not depend on the worker process's
current directory.
These thread counts are tuning starting points rather than universal defaults.
Adjust them according to the available CPU cores and measured request
throughput. Because -w consumes the remaining command-line arguments, place
any dscli start options such as --timeout before -w.
For more parameters, refer to the dscli usage documentation on the Yuanrong
Datasystem official site:
https://atomgit.com/openeuler/yuanrong-datasystem
To stop the worker:
Environment Variable Configuration¶
Set the following environment variables on each node before starting vLLM:
| Variable | Required | Default | Description |
|---|---|---|---|
PYTHONHASHSEED |
Yes | 0 |
Must be consistent across all nodes to guarantee uniform hash generation. |
YR_CONFIG_PATH |
Yes | N/A | Full path to the yuanrong.json config file described below. |
DATASYSTEM_CLIENT_LOG_DIR |
No | ~/.datasystem/logs |
Directory for Yuanrong client SDK logs created by the vLLM process. Use a directory separate from the worker logs. |
export PYTHONHASHSEED=0
export YR_CONFIG_PATH="/xxxxxx/yuanrong.json"
export DATASYSTEM_CLIENT_LOG_DIR="/var/log/yuanrong/client"
mkdir -p "${DATASYSTEM_CLIENT_LOG_DIR}"
Set DATASYSTEM_CLIENT_LOG_DIR before starting vLLM because the Yuanrong
client reads it during logging initialization. Client SDK logs, whose base
name is normally ds_client, are written to this directory.
Configure yuanrong.json¶
The yuanrong.json file pointed to by YR_CONFIG_PATH carries the Yuanrong
client connection options:
{
"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
}
worker_addr: Datasystem worker address in <host>:<port> format. This
must match the local dscli start --worker_address value.
connect_timeout_ms: Maximum time in milliseconds for the Yuanrong client
to establish a connection. Yuanrong requires an integer greater than or equal
to 500. Defaults to 9000.
request_timeout_ms: Timeout in milliseconds for Yuanrong client requests.
Defaults to 0, which preserves the Yuanrong SDK behavior of using
connect_timeout_ms as the request timeout. Set a positive value to control
request timeout independently.
get_sub_timeout_ms: Maximum time in milliseconds for each
mget_h2d_from_multi_buffers request to wait for objects to become ready. 0
means that no waiting is allowed. Defaults to 0. Yuanrong validates this
value when the Get request runs. It may be greater than request_timeout_ms;
the Yuanrong Get path expands that call's RPC timeout to accommodate the
configured object-ready wait.
enable_remote_h2d: Passed to Yuanrong HeteroClient.enable_remote_h2d.
Use true only after the Remote H2D requirements below are met. Defaults to
false.
remote_h2d_transport_backend: vLLM-side transport name, used by the
Yuanrong backend to decide whether to pre-register device memory. HIXL
(default) for HIXL HCCS (covers buffer-pool, HIXL RoCE direct, and FabricMem
sub-modes); P2P_TRANSFER for datasystem P2P-Transfer over RoCE. Must
correspond to the worker-side --remote_h2d_link_type (see the
Remote H2D link parameters table below for
the HIXL ↔ HCCS / P2P_TRANSFER ↔ ROCE mapping). Under HIXL the
backend pre-registers device memory unless enable_fabric_mem is true;
under P2P_TRANSFER it skips pre-registration.
enable_fabric_mem: Selects HIXL FabricMem mode, where HIXL
OPTION_ENABLE_USE_FABRIC_MEM handles Fabric shareable handle exchange
automatically and the backend skips client-side pre_register_device_memory.
Only meaningful when remote_h2d_transport_backend="HIXL". Defaults to false.
FabricMem requires datasystem-side support (HIXL FabricMem build and the
corresponding datasystem environment variable); check the datasystem
documentation before enabling this flag.
enable_dev_mem_pregister: Master toggle for client-side device memory
pre-registration (pre_register_device_memory). Defaults to false, so the
backend does not pre-register device buffer pointers by default. To actually
pre-register, this flag must be true and the automatic conditions must
hold: enable_remote_h2d=true, remote_h2d_transport_backend="HIXL", and
enable_fabric_mem=false. Under P2P_TRANSFER or FabricMem mode pre-registration
is always skipped regardless of this toggle. Set this to true for HIXL HCCS
Remote H2D deployments that require client-side device memory registration.
Remote H2D Requirements¶
Set enable_remote_h2d to true only when Remote Host-to-Device transfer is
enabled and verified in the Yuanrong Datasystem deployment:
- Reserve enough 2MiB HugeTLB pages before starting the worker. For 40GiB shared memory, reserve at least 20480 2MiB huge pages.
- Start each Datasystem worker with Remote H2D enabled. The worker start
command must include
--remote_h2d_device_ids,--enable_huge_tlb true,--arena_per_tenant 1, and--enable_fallocate false. Using multiple available NPU device IDs is recommended, for example"0,1,2,3,4,5,6,7"on an 8-NPU node.
dscli start --interleave 0-7 -w \
--worker_address "${WORKER_IP}:31501" \
--etcd_address "${ETCD_IP}:2379" \
--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 "ROCE"
For HIXL HCCS links (Atlas A3 with HCCS reachability), set
--remote_h2d_link_type "HCCS" and the HIXL buffer-pool parameter. The IP in
--worker_address is also used as the HIXL endpoint IP, so use a reachable
address rather than 127.0.0.1 or 0.0.0.0. HIXL RoCE direct mode is a
sub-mode of HCCS selected by HCCL_INTRA_ROCE_ENABLE=1 on both sides and
additionally requires a reachable RoCE link:
dscli start --interleave 0-7 -w \
--worker_address "${WORKER_IP}:31501" \
--etcd_address "${ETCD_IP}:2379" \
--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"
Remote H2D link parameters¶
| Parameter | Default | Description |
|---|---|---|
remote_h2d_device_ids |
empty | Non-empty enables worker-side RH2D. Comma-separated device IDs, e.g. "0,1,2,3,4,5,6,7". |
remote_h2d_link_type |
ROCE |
Link type, case-sensitive. ROCE for P2P-Transfer over RoCE; HCCS for HIXL HCCS (covers buffer-pool, HIXL RoCE direct, and FabricMem sub-modes). Must correspond to the client-side remote_h2d_transport_backend in yuanrong.json (ROCE ↔ P2P_TRANSFER, HCCS ↔ HIXL). For HCCS, the client process must also export DS_RH2D_LINK_TYPE=HCCS before starting vLLM (the backend does not export it automatically); ROCE is the datasystem default and needs no env var. |
remote_h2d_hccs_buffer_pool |
4:8 |
HIXL buffer-pool parameter <count>:<size>, only used when remote_h2d_link_type=HCCS. Ignored under HIXL RoCE direct mode (HCCL_INTRA_ROCE_ENABLE=1). |
- Make sure the NPU driver, firmware, and CANN toolkit required by Yuanrong
Remote H2D are installed and visible to the worker process. In containers,
mount the Ascend driver path,
npu-smi,hccn_tool,/etc/hccn.conf,/etc/ascend_install.info, and the required/dev/davinci*devices. - Verify the NPU environment before enabling the client flag. The RoCE
checks below apply to
P2P_TRANSFERand HIXL RoCE direct mode; HCCS buffer-pool mode does not require a reachable RoCE link:
# Check the current 2MiB HugeTLB page size, total count, and free count.
grep -E "HugePages_Total|HugePages_Free|Hugepagesize" /proc/meminfo
# Optional: check 2MiB 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>
If these checks fail, keep enable_remote_h2d at false in yuanrong.json
and use the default Datasystem transfer path.
Run AscendStoreConnector with Yuanrong backend¶
Use AscendStoreConnector with 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"
}
}'
lookup_rpc_port is the RPC port used between the pooling scheduler process
and the worker process. Each instance must use a unique port value.
Notes¶
- The Yuanrong backend passes KV keys to the Datasystem SDK as-is, without rewriting them. Ensure keys are valid Datasystem keys in production.
- When
enable_remote_h2distrueandremote_h2d_transport_backendisHIXL(withenable_fabric_memfalse), the backend pre-registers device buffer pointers (register_buffer) with the Datasystem worker to enable Remote H2D transfer — but only ifenable_dev_mem_pregisteristrue.enable_dev_mem_pregisterdefaults tofalse, so pre-registration is opt-in. UnderP2P_TRANSFERor FabricMem mode the backend skips pre-registration and uses device pointers directly when building blob lists.
2. Run Inference¶
FAQ¶
1. Mooncake FAQ¶
1.1 failed to put/get key¶
When vLLM reports failed put or get operations, first check whether the error is reported by Mooncake itself.
- If the error is reported by Mooncake:
- For
putfailures, check whether the Mooncake log containsNO_AVAILABLE_HANDLEorBatchPut failed ... due to insufficient space. This usually means the remaining space after eviction is not enough for oneBatchPutrequest. Ensure the space left by the eviction policy (for example, the capacity implied by1 - eviction_ratio) can hold one batch put, or consider increasing the available capacity, increasing eviction headroom, or reducing the batch size. - For
getfailures, check whether the Mooncake log containslease_expired_before_data_transfer_completed key=...or returnsLEASE_EXPIRED. This means the KV object lease expired before the data transfer completed. Increase--default_kv_lease_ttlformooncake_masteras needed, and keep it larger thanASCEND_CONNECT_TIMEOUTandASCEND_TRANSFER_TIMEOUT.
- For
- If the error is not reported by Mooncake, it is likely an HIXL (ascend_direct) transfer-layer issue. Collect plog files under
/root/ascend/log/debug/plogand check whether the issue matches a known HIXL problem.
For common troubleshooting and issue localization guidance for HIXL (ascend_direct), see: 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
1.2 SSD FAQ¶
1.2.1 SEGMENT_NOT_FOUND with SSD offload¶
If client logs show OffloadObjectHeartbeat failed, error code is SEGMENT_NOT_FOUND, Master has unmounted the rank's LOCAL_DISK segment (usually after client_expired when Ping stops refreshing TTL). SSD offload on that rank stops until the segment is registered again.
Typical trigger (with enable_cpu_binding=true): Mooncake starts Ping during init, then vLLM-Ascend bind_cpus() runs migratepages/IRQ binding; the Ping thread is not pinned and can miss beats under the default client_ttl=10.
| Mitigation | Notes |
|---|---|
| Temporary: raise Master TTL | e.g. mooncake_master ... --client_ttl=120. Tune to your init/warmup window (often 60–120 is enough). Does not fix the root cause. |
| Recovery: upgrade Mooncake | Versions > v0.3.11 (main branch) can remount LOCAL_DISK and rescan metadata after SEGMENT_NOT_FOUND. This recovers after cleanup; it does not prevent expiry or in-flight request failures while metadata is gone. |
| Root fix: Mooncake Ping CPU affinity | Pin the storage Ping thread to a release/isolated CPU (Mooncake-side change). Optional vLLM-Ascend cooperation to pass the release CPU per rank. |
Also restart Master together with vLLM to avoid stale segment_already_exists state when debugging restarts.
1.2.2 Fabric memory size alignment (A3 + ASCEND_ENABLE_USE_FABRIC_MEM=1)¶
On A3 with fabric memory enabled, each fabric mem allocation must be an integer multiple of 1GB (1073741824 bytes). Mooncake does not round sizes up automatically.
| Parameter | Config source | Alignment |
|---|---|---|
global_segment_size |
mooncake.json or export MOONCAKE_GLOBAL_SEGMENT_SIZE |
Each rank's segment size must be aligned to 1GB (e.g. "1GB", "20GB"). |
MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES |
export MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES (only when enable_ssd_offload=true) |
Must be aligned to 1GB. Default is 1280MB (1.25GB), which is not aligned and is too small for long-context SSD loads — size with Sizing MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES. |
local_buffer_size in mooncake.json is not used under fabric mem (vLLM-Ascend passes 0 to setup()).
Risk if misaligned: adxl MallocMem / aclrtMapMem fails with Invalid_Argument. With SSD offload enabled, a failed MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES allocation can segfault during FileStorage init and abort vLLM startup. Avoid values such as "1280MB", "512MB", or "1.5GB".
Fabric mem quota: Both global_segment_size and MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES are separate fabric mem allocations per rank. Their sizes add up against the HIXL fabric mem limit configured via ASCEND_GLOBAL_RESOURCE_CONFIG (e.g. "fabric_memory.max_capacity":32, unit GB per process — see HIXL docs). Rough budget per rank:
fabric_memory.max_capacity ≥ global_segment_size + MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES (+ headroom)
Risk if quota is too low: Some ranks fail with Memory_Allocation_Failure(EL0004) after global_segment_size succeeds but MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES allocation fails. Increase fabric_memory.max_capacity, reduce global_segment_size or MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES, or ensure the node has enough host memory.
Example (add to your vLLM startup script when SSD offload is on):
export ASCEND_ENABLE_USE_FABRIC_MEM=1
export MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES=1073741824 # 1GB, fabric-mem aligned
set ASCEND_GLOBAL_RESOURCE_CONFIG only if fabric mem is too low.
# Per-rank fabric mem budget: 20 GB segment + 1GB MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES → set max_capacity ≥ 22 (GB)
export ASCEND_GLOBAL_RESOURCE_CONFIG='{"fabric_memory.max_capacity":32}'
1.2.3 Sizing MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES¶
When enable_ssd_offload=true, Mooncake allocates a separate per-rank SSD read/write buffer sized by MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES. This buffer is independent of global_segment_size in mooncake.json — increasing the segment does not fix BUFFER_OVERFLOW caused by an undersized MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES.
If the buffer is too small, SSD reads fail with BUFFER_OVERFLOW (error_code=-10) during FileStorage::AllocateBatch, and vLLM may fail when kv_load_failure_policy=fail.
If you encounter BUFFER_OVERFLOW during use, try increasing MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES. Do not set it higher than the Available KV cache memory value shown in vLLM worker logs:
Example:
Use byte literals only (10737418240). 10G / 10GB are ignored and fall back to the 1280MB default.
Notes
* `--max-num-batched-tokens` only chunks prefill compute; it does **not** reduce the memory required by `MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES`.Host memory budget (single node)¶
MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES is allocated per rank, in addition to global_segment_size:
host_memory_for_mooncake ≈ TP × (global_segment_size + MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES + local_buffer_size)
Ensure free -h available on the host exceeds this sum plus vLLM overhead. MOONCAKE_OFFLOAD_LOCAL_BUFFER_SIZE_BYTES does not need to fit inside global_segment_size.
Verify after tuning¶
- Startup: each rank logs
AlignedClientBufferAllocator: allocated <N> byteswith your configured size. - Under load: no
BUFFER_OVERFLOW/Failed to get ... keys out of ... error_codes=[-10]. - If failures persist with a large buffer, check overlapping loads (
load_async).
2. Memcache FAQ¶
For Memcache troubleshooting, see: https://gitcode.com/Ascend/memcache/wiki/FAQ.md
3. DSv4 known issue (temporary)¶
For the temporary DSv4 known issue, see: https://github.com/vllm-project/vllm-ascend/issues/9975