预填充-解码分离(DeepSeek)¶
快速开始¶
vLLM-Ascend 现已支持带 EP(专家并行)选项的预填充-解码(PD)分离。本指南将逐步在受限资源下验证这些功能。
以 DeepSeek-r1-w8a8 模型为例,使用 4 台 Atlas 800T A3 服务器部署“2P1D”架构。假设预填充服务器的 IP 为 192.0.0.1(预填充 1)和 192.0.0.2(预填充 2),解码服务器为 192.0.0.3(解码 1)和 192.0.0.4(解码 2)。在每台服务器上,使用 8 个 NPU 和 16 个芯片部署一个服务实例。
验证多节点通信环境¶
物理层要求¶
- 物理机器必须位于同一局域网内,并具有网络连接。
- 所有 NPU 必须互连。节点内连接通过 HCCS 实现,节点间连接通过 RDMA 实现。
验证流程¶
依次在每个节点上执行以下命令。所有结果必须为 success,且状态必须为 UP:
-
单节点验证:
依次在每个节点上执行以下命令。所有结果必须为
success,且状态必须为UP:# Check the remote switch ports for i in {0..15}; do hccn_tool -i $i -lldp -g | grep Ifname; done # Get the link status of the Ethernet ports (UP or DOWN) for i in {0..15}; do hccn_tool -i $i -link -g ; done # Check the network health status for i in {0..15}; do hccn_tool -i $i -net_health -g ; done # View the network detected IP configuration for i in {0..15}; do hccn_tool -i $i -netdetect -g ; done # View gateway configuration for i in {0..15}; do hccn_tool -i $i -gateway -g ; done -
检查 NPU HCCN 配置:
确保环境中存在 hccn.conf 文件。如果使用 Docker,请将其挂载到容器中。
-
获取 NPU IP 地址
-
获取 superpodid 和 SDID
-
跨节点 PING 测试
-
检查 NPU TLS 配置
-
单节点验证:
依次在每个节点上执行以下命令。所有结果必须为
success,且状态必须为UP:# Check the remote switch ports for i in {0..7}; do hccn_tool -i $i -lldp -g | grep Ifname; done # Get the link status of the Ethernet ports (UP or DOWN) for i in {0..7}; do hccn_tool -i $i -link -g ; done # Check the network health status for i in {0..7}; do hccn_tool -i $i -net_health -g ; done # View the network detected IP configuration for i in {0..7}; do hccn_tool -i $i -netdetect -g ; done # View gateway configuration for i in {0..7}; do hccn_tool -i $i -gateway -g ; done -
检查 NPU HCCN 配置:
确保环境中存在 hccn.conf 文件。如果使用 Docker,请将其挂载到容器中。
-
获取 NPU IP 地址
-
跨节点 PING 测试
-
检查 NPU TLS 配置
使用 Docker 运行¶
在每个节点上启动一个 Docker 容器。
# Update the vllm-ascend image
export IMAGE=m.daocloud.io/quay.io/ascend/vllm-ascend:v0.23.0
export NAME=vllm-ascend
# Run the container using the defined variables
# Note: If you are running bridge network with Docker, please expose available ports for multiple nodes communication in advance.
docker run --rm \
--name $NAME \
--net=host \
--shm-size=1g \
--device /dev/davinci0 \
--device /dev/davinci1 \
--device /dev/davinci2 \
--device /dev/davinci3 \
--device /dev/davinci4 \
--device /dev/davinci5 \
--device /dev/davinci6 \
--device /dev/davinci7 \
--device /dev/davinci8 \
--device /dev/davinci9 \
--device /dev/davinci10 \
--device /dev/davinci11 \
--device /dev/davinci12 \
--device /dev/davinci13 \
--device /dev/davinci14 \
--device /dev/davinci15 \
--device /dev/davinci_manager \
--device /dev/devmm_svm \
--device /dev/hisi_hdc \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/Ascend/driver/tools/hccn_tool:/usr/local/Ascend/driver/tools/hccn_tool \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /etc/hccn.conf:/etc/hccn.conf \
-v /mnt/sfs_turbo/.cache:/root/.cache \
-it $IMAGE bash
安装 Mooncake¶
Mooncake 是 Kimi 的服务平台,Kimi 是 Moonshot AI 提供的一项领先 LLM 服务。安装和编译指南:https://github.com/kvcache-ai/Mooncake?tab=readme-ov-file#build-and-use-binaries 首先,我们需要获取 Mooncake 项目。请参考以下命令:
(可选) 如果网络状况不佳,请替换 go install 的下载地址。
安装 MPI
安装相关依赖。无需安装 Go。
编译并安装
设置环境变量
注意:
- 根据你具体的 Python 安装调整 Python 路径
- 确保
/usr/local/lib和/usr/local/lib64位于你的LD_LIBRARY_PATH中
Prefiller/Decoder 部署¶
我们可以分别在 prefiller/decoder 节点上运行以下脚本来启动服务器。请注意,每个 P/D 节点将占用从 kv_port 到 kv_port + num_chips 的端口来初始化 socket 监听器。为避免任何问题,应防止端口冲突。此外,请确保每个节点的 engine_id 唯一分配,以避免冲突。
QoS 配置¶
在传输发起方的 kv_connector_extra_config 中设置 qos_priority。MooncakeConnectorV1、MooncakeHybridConnector 和 MooncakeLayerwiseConnector 均支持此选项。默认的 P/D QoS 为 1;可接受的值是 [0, 4] 范围内的整数(不接受布尔值)。
使用 HIXL Client/Server 传输时,发起连接的端点提供通道 QoS。对端使用收到的该值创建其对应的通道:
| 传输模式 | 发起方 | 操作 | 使用的 QoS 配置 |
|---|---|---|---|
| Pull | Decoder (D) | 从 prefiller 读取 KV | D 侧 qos_priority |
| Push | Prefiller (P) | 向 decoder 写入 KV | P 侧 qos_priority |
尽管在两种模式下 KV 数据都从 P 流向 D,但 pull 使用 D 的 QoS,push 使用 P 的 QoS。仅配置被动端点不会覆盖发起方的通道 QoS。两个端点都支持该选项,但连接的生效值来自其发起方。
例如,在现有的并行设置中加入 "qos_priority": 1:
{
"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_consumer",
"kv_connector_extra_config": {
"qos_priority": 1,
"prefill": {"dp_size": 1, "tp_size": 2},
"decode": {"dp_size": 1, "tp_size": 2}
}
}
对 prefiller 使用 kv_producer,并在你的 --kv-transfer-config 中保留其他部署相关字段。
无需手动导出 QoS 环境变量。在初始化传输引擎之前,连接器会将其 QoS 合并到 ASCEND_GLOBAL_RESOURCE_CONFIG 中的字面顶层 JSON 键 "comm_resource_config.qos",并在该环境变量不存在时创建它。其他资源设置和 store 配置会被保留。显式设置的 QoS 值(或在省略时的默认值 1)会替换现有的顶层 QoS。如果 QoS 值无效或资源 JSON 格式错误,则会在环境变量被修改之前失败。
Injected comm_resource_config.qos=... 日志确认本地环境配置已成功写入。但该日志本身并不能证明此值已用于传输通道。在 pull 模式下,被动的 P 侧 HIXL 服务器可能不会打印本地 QoS 解析日志;在 push 模式下,被动的 D 侧也同样如此。请检查发起方的配置和 HIXL 通道日志,以验证通道 QoS。
使用 MultiConnector 时,请在 Mooncake P/D 子连接器的 kv_connector_extra_config 中设置 qos_priority。P/D 注入只会更新顶层 QoS 键;它不会配置或校验 pooling 后端,也不会修改其 store 设置。更改 P/D QoS 后,请重启服务进程。
kv_port 配置指南¶
在 Ascend NPU 上,Mooncake 使用 AscendDirectTransport 进行 RDMA 数据传输,它会在 [20000, 20000 + npu_per_node × 1000) 范围内随机分配端口。如果 kv_port 与该范围重叠,可能会发生间歇性端口冲突。为避免这种情况,请按下表配置 kv_port:
| 每节点 NPU 数量 | 保留端口范围 | 推荐的 kv_port |
|---|---|---|
| 8 | 20000 - 27999 | >= 28000 |
| 16 | 20000 - 35999 | >= 36000 |
Warning
如果在启动过程中偶尔看到 zmq.error.ZMQError: Address already in use,这可能是由于 kv_port 与随机分配的 AscendDirectTransport 端口冲突所致。请增大你的 kv_port 值,以避开保留范围。
launch_online_dp.py¶
使用 launch_online_dp.py 启动外部的 dp vllm 服务器。
launch_online_dp.py
run_dp_template.sh¶
在每个节点上修改 run_dp_template.sh。
run_dp_template.sh
launch_online_dp.py 会启动 dp-size-local 个 vLLM 实例,并向 run_dp_template.sh 传递七个位置参数。下面的示例对应于启动服务。
| 启动器选项 | 模板值 | 含义 | 示例值 | 约束 |
|---|---|---|---|---|
--dp-size |
$3 / --data-parallel-size |
组内 DP rank 总数。 | P:2;D:32 |
正整数;同一组内必须一致。所有 rank 必须覆盖 [0, dp-size) 且不重叠。 |
--tp-size |
$7 / --tensor-parallel-size |
每个实例使用的 NPU 数量。 | P:8;D:1 |
正整数;dp-size-local * tp-size 不得超过节点上可用的 NPU 数量。 |
--dp-size-local |
模板调用次数 | 此节点上的 DP 实例数。 | P:2;D:16 |
如果设为 -1,则默认为 dp-size。否则,1 <= dp-size-local <= dp-size。 |
--dp-rank-start |
$4 / --data-parallel-rank = dp-rank-start + i |
此节点上的第一个 DP rank。 | P:0;D:0 或 16 |
非负整数;分配的 rank 范围必须在 dp-size 内且不重叠。 |
--dp-address |
$5 / --data-parallel-address |
DP 主节点地址。 | P:192.0.0.1 或 192.0.0.2;D:192.0.0.3 |
IP 地址必须可访问,且在同一 DP 组内保持一致。 |
--dp-rpc-port |
$6 / --data-parallel-rpc-port |
DP 主节点 RPC 端口。 | 12321 |
空闲且可访问的端口;同一 DP 组内保持一致。 |
--vllm-start-port |
$2 / --port = vllm-start-port + i |
第一个本地 API 端口。 | 7100,然后 7101,…… |
连续的可用端口;必须与代理配置匹配。 |
| 由启动器计算 | $1 / ASCEND_RT_VISIBLE_DEVICES |
分配给每个实例的 NPU ID。 | P:0,...,7、8,...,15;D:0 到 15 |
ID 必须存在且不重叠;非连续 ID 需要修改启动器。 |
Note
- 启动器仅校验参数类型和必需选项。部署前请检查其余约束条件。
- 如果启用了推测解码,
num_speculative_tokens应满足以下条件之一:- 混合 Mamba 模型(如 Qwen-Next 和 Qwen3.5 系列):
num_speculative_tokens在 P 节点和 D 节点上应相等。 - 其他模型:P 节点上的
num_speculative_tokens应为 1,D 节点上的num_speculative_tokens应大于或等于 1。
- 混合 Mamba 模型(如 Qwen-Next 和 Qwen3.5 系列):
分层¶
nic_name="eth0" # network card name
local_ip="192.0.0.1"
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=256
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"
export VLLM_USE_V1=1
export ASCEND_RT_VISIBLE_DEVICES=$1
vllm serve /path_to_weight/DeepSeek-r1_w8a8_mtp \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name ds_r1 \
--max-model-len 40000 \
--max-num-batched-tokens 16384 \
--max-num-seqs 8 \
--enforce-eager \
--trust-remote-code \
--gpu-memory-utilization 0.9 \
--quantization ascend \
--no-enable-prefix-caching \
--speculative-config '{"num_speculative_tokens": 1, "method":"deepseek_mtp"}' \
--additional-config '{"enable_shared_expert_dp": true}' \
--kv-transfer-config \
'{"kv_connector": "MooncakeLayerwiseConnector",
"kv_role": "kv_producer",
"kv_port": "36000",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 2,
"tp_size": 8
},
"decode": {
"dp_size": 32,
"tp_size": 1
}
}
}'
nic_name="eth0" # network card name
local_ip="192.0.0.2"
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=256
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"
export VLLM_USE_V1=1
export ASCEND_RT_VISIBLE_DEVICES=$1
vllm serve /path_to_weight/DeepSeek-r1_w8a8_mtp \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name ds_r1 \
--max-model-len 40000 \
--max-num-batched-tokens 16384 \
--max-num-seqs 8 \
--enforce-eager \
--trust-remote-code \
--gpu-memory-utilization 0.9 \
--quantization ascend \
--no-enable-prefix-caching \
--speculative-config '{"num_speculative_tokens": 1, "method":"deepseek_mtp"}' \
--additional-config '{"enable_shared_expert_dp": true}' \
--kv-transfer-config \
'{"kv_connector": "MooncakeLayerwiseConnector",
"kv_role": "kv_producer",
"kv_port": "36100",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 2,
"tp_size": 8
},
"decode": {
"dp_size": 32,
"tp_size": 1
}
}
}'
nic_name="eth0" # network card name
local_ip="192.0.0.3"
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=600
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"
export VLLM_USE_V1=1
export ASCEND_RT_VISIBLE_DEVICES=$1
vllm serve /path_to_weight/DeepSeek-r1_w8a8_mtp \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name ds_r1 \
--max-model-len 40000 \
--max-num-batched-tokens 256 \
--max-num-seqs 40 \
--trust-remote-code \
--gpu-memory-utilization 0.94 \
--quantization ascend \
--no-enable-prefix-caching \
--speculative-config '{"num_speculative_tokens": 1, "method":"deepseek_mtp"}' \
--additional-config '{"recompute_scheduler_enable":true,"multistream_overlap_shared_expert": true,"finegrained_tp_config": {"lmhead_tensor_parallel_size":16}}' \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
--kv-transfer-config \
'{"kv_connector": "MooncakeLayerwiseConnector",
"kv_role": "kv_consumer",
"kv_port": "36200",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 2,
"tp_size": 8
},
"decode": {
"dp_size": 32,
"tp_size": 1
}
}
}'
nic_name="eth0" # network card name
local_ip="192.0.0.4"
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=600
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"
export VLLM_USE_V1=1
export ASCEND_RT_VISIBLE_DEVICES=$1
vllm serve /path_to_weight/DeepSeek-r1_w8a8_mtp \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name ds_r1 \
--max-model-len 40000 \
--max-num-batched-tokens 256 \
--max-num-seqs 40 \
--trust-remote-code \
--gpu-memory-utilization 0.94 \
--quantization ascend \
--no-enable-prefix-caching \
--speculative-config '{"num_speculative_tokens": 1, "method":"deepseek_mtp"}' \
--additional-config '{"recompute_scheduler_enable":true,"multistream_overlap_shared_expert": true,"finegrained_tp_config": {"lmhead_tensor_parallel_size":16}}' \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
--kv-transfer-config \
'{"kv_connector": "MooncakeLayerwiseConnector",
"kv_role": "kv_consumer",
"kv_port": "36200",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 2,
"tp_size": 8
},
"decode": {
"dp_size": 32,
"tp_size": 1
}
}
}'
非分层¶
nic_name="eth0" # network card name
local_ip="192.0.0.1"
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=256
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"
export VLLM_USE_V1=1
export ASCEND_RT_VISIBLE_DEVICES=$1
vllm serve /path_to_weight/DeepSeek-r1_w8a8_mtp \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name ds_r1 \
--max-model-len 40000 \
--max-num-batched-tokens 16384 \
--max-num-seqs 8 \
--enforce-eager \
--trust-remote-code \
--gpu-memory-utilization 0.9 \
--quantization ascend \
--no-enable-prefix-caching \
--speculative-config '{"num_speculative_tokens": 1, "method":"deepseek_mtp"}' \
--additional-config '{"enable_shared_expert_dp": true}' \
--kv-transfer-config \
'{"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_producer",
"kv_port": "36000",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 2,
"tp_size": 8
},
"decode": {
"dp_size": 32,
"tp_size": 1
}
}
}'
nic_name="eth0" # network card name
local_ip="192.0.0.2"
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=256
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"
export VLLM_USE_V1=1
export ASCEND_RT_VISIBLE_DEVICES=$1
vllm serve /path_to_weight/DeepSeek-r1_w8a8_mtp \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name ds_r1 \
--max-model-len 40000 \
--max-num-batched-tokens 16384 \
--max-num-seqs 8 \
--enforce-eager \
--trust-remote-code \
--gpu-memory-utilization 0.9 \
--quantization ascend \
--no-enable-prefix-caching \
--speculative-config '{"num_speculative_tokens": 1, "method":"deepseek_mtp"}' \
--additional-config '{"enable_shared_expert_dp": true}' \
--kv-transfer-config \
'{"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_producer",
"kv_port": "36100",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 2,
"tp_size": 8
},
"decode": {
"dp_size": 32,
"tp_size": 1
}
}
}'
nic_name="eth0" # network card name
local_ip="192.0.0.3"
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=600
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"
export VLLM_USE_V1=1
export ASCEND_RT_VISIBLE_DEVICES=$1
vllm serve /path_to_weight/DeepSeek-r1_w8a8_mtp \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name ds_r1 \
--max-model-len 40000 \
--max-num-batched-tokens 256 \
--max-num-seqs 40 \
--trust-remote-code \
--gpu-memory-utilization 0.94 \
--quantization ascend \
--no-enable-prefix-caching \
--speculative-config '{"num_speculative_tokens": 1, "method":"deepseek_mtp"}' \
--additional-config '{"recompute_scheduler_enable":true,"multistream_overlap_shared_expert": true,"finegrained_tp_config": {"lmhead_tensor_parallel_size":16}}' \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
--kv-transfer-config \
'{"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_consumer",
"kv_port": "36200",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 2,
"tp_size": 8
},
"decode": {
"dp_size": 32,
"tp_size": 1
}
}
}'
nic_name="eth0" # network card name
local_ip="192.0.0.4"
export HCCL_IF_IP=$local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export TP_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=10
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export HCCL_BUFFSIZE=600
export TASK_QUEUE_ENABLE=1
export HCCL_OP_EXPANSION_MODE="AIV"
export VLLM_USE_V1=1
export ASCEND_RT_VISIBLE_DEVICES=$1
vllm serve /path_to_weight/DeepSeek-r1_w8a8_mtp \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name ds_r1 \
--max-model-len 40000 \
--max-num-batched-tokens 256 \
--max-num-seqs 40 \
--trust-remote-code \
--gpu-memory-utilization 0.94 \
--quantization ascend \
--no-enable-prefix-caching \
--speculative-config '{"num_speculative_tokens": 1, "method":"deepseek_mtp"}' \
--additional-config '{"recompute_scheduler_enable":true,"multistream_overlap_shared_expert": true,"finegrained_tp_config": {"lmhead_tensor_parallel_size":16}}' \
--compilation-config '{"cudagraph_mode": "FULL_DECODE_ONLY"}' \
--kv-transfer-config \
'{"kv_connector": "MooncakeConnectorV1",
"kv_role": "kv_consumer",
"kv_port": "36200",
"kv_connector_extra_config": {
"prefill": {
"dp_size": 2,
"tp_size": 8
},
"decode": {
"dp_size": 32,
"tp_size": 1
}
}
}'
启动服务¶
# on 192.0.0.1
python launch_online_dp.py --dp-size 2 --tp-size 8 --dp-size-local 2 --dp-rank-start 0 --dp-address 192.0.0.1 --dp-rpc-port 12321 --vllm-start-port 7100
# on 192.0.0.2
python launch_online_dp.py --dp-size 2 --tp-size 8 --dp-size-local 2 --dp-rank-start 0 --dp-address 192.0.0.2 --dp-rpc-port 12321 --vllm-start-port 7100
# on 192.0.0.3
python launch_online_dp.py --dp-size 32 --tp-size 1 --dp-size-local 16 --dp-rank-start 0 --dp-address 192.0.0.3 --dp-rpc-port 12321 --vllm-start-port 7100
# on 192.0.0.4
python launch_online_dp.py --dp-size 32 --tp-size 1 --dp-size-local 16 --dp-rank-start 16 --dp-address 192.0.0.3 --dp-rpc-port 12321 --vllm-start-port 7100
部署示例代理¶
在部署预填充服务实例的同一节点上运行代理服务器。您可以在仓库的 examples 目录中找到代理实现。
我们提供两种请求路由行为不同的代理实现:
-
load_balance_proxy_layerwise_server_example.py:请求首先路由到 D 节点,然后按需转发到 P 节点。该代理专为配合 MooncakeLayerwiseConnector 使用而设计。load_balance_proxy_layerwise_server_example.py -
load_balance_proxy_server_example.py:请求首先路由到 P 节点,然后转发到 D 节点进行后续处理。该代理专为配合 MooncakeConnector 使用而设计。load_balance_proxy_server_example.py
python load_balance_proxy_layerwise_server_example.py \
--port 1999 \
--host 192.0.0.1 \
--prefiller-hosts \
192.0.0.1 \
192.0.0.1 \
192.0.0.2 \
192.0.0.2 \
--prefiller-ports \
7100 7101 7100 7101 \
--decoder-hosts \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
--decoder-ports \
7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115\
7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115
python load_balance_proxy_server_example.py \
--port 1999 \
--host 192.0.0.1 \
--prefiller-hosts \
192.0.0.1 \
192.0.0.1 \
192.0.0.2 \
192.0.0.2 \
--prefiller-ports \
7100 7101 7100 7101 \
--decoder-hosts \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.3 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
192.0.0.4 \
--decoder-ports \
7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115\
7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115
两个代理共享以下后端选项。
| 参数 | 适用范围 | 默认值 | 示例值 | 含义与约束 |
|---|---|---|---|---|
--port |
两者 | 8000 |
1999 |
代理监听端口。必须空闲、可达,且在 1 到 65535 之间。 |
--host |
两者 | localhost |
192.0.0.1 |
代理监听地址。Layerwise 模式需要一个非通配符地址,且 D 节点可访问。 |
--prefiller-hosts |
两者 | localhost |
192.0.0.1 192.0.0.1 192.0.0.2 192.0.0.2 |
P 实例主机。数量必须与 --prefiller-ports 的数量一致。 |
--prefiller-ports |
两者 | 8001 |
7100 7101 7100 7101 |
P 实例端口。每个主机-端口对必须唯一且可达。 |
--decoder-hosts |
两者 | localhost |
十六个 192.0.0.3,然后是十六个 192.0.0.4 |
D 实例主机。数量必须与 --decoder-ports 的数量一致。 |
--decoder-ports |
两者 | 8002 |
对于每个 D 主机:7100-7115 |
D 实例端口。每个主机-端口对必须唯一且可达。 |
Note
代理脚本会验证每个主机列表与对应的端口列表长度是否相同。
你可以从仓库的 examples 目录中获取代理程序:load_balance_proxy_server_example.py
基准测试¶
我们建议使用 aisbench 工具评估性能。aisbench 执行以下命令安装 aisbench
在评估性能之前,你需要取消 http 代理,如下所示:
- 你可以将数据集放在目录:
benchmark/ais_bench/datasets - 你可以在目录
benchmark/ais_bench/benchmark/configs/models/vllm_api中修改配置。以vllm_api_stream_chat.py为例
models = [
dict(
attr="service",
type=VLLMCustomAPIChatStream,
abbr='vllm-api-stream-chat',
path="/root/.cache/ds_r1",
model="dsr1",
request_rate = 14,
retry = 2,
host_ip = "192.0.0.1", # Proxy service host IP
host_port = 8000, # Proxy service Port
max_out_len = 10,
batch_size=768,
trust_remote_code=True,
generation_kwargs = dict(
temperature = 0,
seed = 1024,
ignore_eos=False,
)
)
]
- 以 gsm8k 数据集为例,执行以下命令评估性能。
ais_bench --models vllm_api_stream_chat --datasets gsm8k_gen_0_shot_cot_str_perf --debug --mode perf
- 有关 aisbench 命令和参数的更多详情,请参阅 aisbench
常见问题¶
1. Prefiller 节点需要预热¶
由于某些 NPU 算子的计算需要多轮预热才能达到最佳性能,我们建议在进行性能测试之前,先用一些请求预热服务,以获得最佳端到端吞吐量。
验证¶
使用代理服务器端点检查服务健康状态。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 vl/vllm-ascend