跳转至

预填充-解码分离 (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

  1. 单节点验证:

    在每个节点上依次执行以下命令。结果必须全部为 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
    
  2. 检查 NPU HCCN 配置:

    确保环境中存在 hccn.conf 文件。如果使用 Docker,请将其挂载到容器中。

    cat /etc/hccn.conf
    
  3. 获取 NPU IP 地址

    # Get virtual NPU IP.
    for i in {0..15}; do hccn_tool -i $i -vnic -g;done
    
  4. 获取 superpodid 和 SDID

    for i in {0..15}; do npu-smi info -t spod-info -i $i -c 0;npu-smi info -t spod-info -i $i -c 1;done
    
  5. 跨节点 PING 测试

    # Execute on the target node (replace 'x.x.x.x' with virtual NPU IP address).
    for i in {0..15}; do hccn_tool -i $i -hccs_ping -g address x.x.x.x;done
    
  6. 检查 NPU TLS 配置

    # The TLS settings should be consistent across all nodes
    for i in {0..15}; do hccn_tool -i $i -tls -g ; done | grep switch
    
  1. 单节点验证:

    在每个节点上依次执行以下命令。结果必须全部为 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
    
  2. 检查 NPU HCCN 配置:

    确保环境中存在 hccn.conf 文件。如果使用 Docker,请将其挂载到容器中。

    cat /etc/hccn.conf
    
  3. 获取 NPU IP 地址

    for i in {0..7}; do hccn_tool -i $i -ip -g;done
    
  4. 跨节点 PING 测试

    # Execute on the target node (replace 'x.x.x.x' with actual npu ip address)
    for i in {0..7}; do hccn_tool -i $i -ping -g address x.x.x.x;done
    
  5. 检查 NPU TLS 配置

    # The TLS settings should be consistent across all nodes
    for i in {0..7}; do hccn_tool -i $i -tls -g ; done | grep switch
    

使用 Docker 运行

在每个节点上启动一个 Docker 容器。

# Update the vllm-ascend image
export IMAGE=m.daocloud.io/quay.io/ascend/vllm-ascend:v0.22.1rc1
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 是 Moonshot AI 提供的领先 LLM 服务 Kimi 的服务平台。安装与编译指南:https://github.com/kvcache-ai/Mooncake?tab=readme-ov-file#build-and-use-binaries 首先,我们需要获取 Mooncake 项目。请参考以下命令:

git clone -b v0.3.9 --depth 1 https://github.com/kvcache-ai/Mooncake.git

(可选)如果网络状况不佳,请替换 go install 的 URL

cd Mooncake
sed -i 's|https://go.dev/dl/|https://golang.google.cn/dl/|g' dependencies.sh

安装 mpi

apt-get install mpich libmpich-dev -y

安装相关依赖。不需要安装 Go。

bash dependencies.sh -y

编译并安装

mkdir build
cd build
cmake .. -DUSE_ASCEND_DIRECT=ON
make -j
make install

设置环境变量

注意:

  • 根据您的具体 Python 安装调整 Python 路径
  • 确保 /usr/local/lib/usr/local/lib64 位于您的 LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/lib64/python3.12/site-packages/mooncake:$LD_LIBRARY_PATH

预填充器/解码器部署

我们可以运行以下脚本,分别在预填充器/解码器节点上启动服务器。请注意,每个 P/D 节点将占用从 kv_port 到 kv_port + num_chips 范围的端口来初始化套接字监听器。为避免问题,应防止端口冲突。此外,请确保每个节点的 engine_id 唯一分配以避免冲突。

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.shrun_dp_template.sh

分层

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
             }
      }
  }'

```shell 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
             }
      }
  }'

Non-layerwise

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
             }
      }
  }'

```shell 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 代理服务端口
--host 代理服务主机IP
--prefiller-hosts 预填充节点主机
--prefiller-ports 预填充节点端口
--decoder-hosts 解码器节点主机
--decoder-ports 解码器节点端口

您可以在仓库的 examples 中找到代理程序,load_balance_proxy_server_example.py

基准测试

建议使用 aisbench 工具评估性能。aisbench 执行以下命令安装 aisbench

git clone https://github.com/AISBench/benchmark.git
cd benchmark/
pip3 install -e ./

评估性能前,需要取消 http 代理,如下所示

# unset proxy
unset http_proxy
unset https_proxy
  • 可将数据集放置在目录: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 算子的计算需要多轮预热才能达到最佳性能,建议在进行性能测试前,先用一些请求预热服务,以实现最佳端到端吞吐量。

验证

使用代理服务器端点检查服务健康状态。

curl http://192.0.0.1:8080/v1/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "ds_r1",
        "prompt": "Who are you?",
        "max_completion_tokens": 100,
        "temperature": 0
    }'