跳到内容

MoRIIOConnector 使用指南

MoRIIOConnector 是一种高性能 KV 连接器,用于 PD 分离部署(PD disaggregated deployments)中的 KV 缓存传输。它基于 ROCm 的 MoRI-IO 通信库构建,可实现极低开销的点对点通信。

先决条件

安装

Docker: MoRI 已随官方 ROCm vLLM 镜像发布:vllm/vllm-openai-rocm:nightly

手动安装: 可以通过以下方式安装 MoRI wheel:

pip install amd_mori

有关更多信息,请参考 Dockerfile.rocm_base,或查看 MoRI 官方仓库了解如何从源代码编译 MoRI。

有关安装合适的 NIC 用户态库的说明,请参见安装 NIC 用户态库

基本用法(单机)

首先启动代理(proxy);生产者和消费者实例将重试注册,直到代理可达。

生产者(Prefiller)配置

启动一个生成 KV 缓存的 prefiller 实例

# Prefill instance (GPU 0-3) 
export VLLM_ROCM_USE_AITER=1
export CUDA_VISIBLE_DEVICES=0,1,2,3
export HIP_VISIBLE_DEVICES=0,1,2,3

vllm serve Qwen/Qwen3-235B-A22B-FP8 \
  -tp 4 \
  --port 20005 \
  --gpu-memory-utilization 0.9 \
  --kv-transfer-config '{
    "kv_connector": "MoRIIOConnector",
    "kv_role": "kv_producer",
    "kv_connector_extra_config": {
      "proxy_ip": "127.0.0.1",
      "proxy_ping_port": "36367",
      "http_port": "20005",
      "handshake_port": "6301",
      "notify_port": "6105"
    }
  }'

消费者(Decoder)配置

启动一个消耗 KV 缓存的 decoder 实例

# Decode instance (GPU 4-7)
export VLLM_ROCM_USE_AITER=1
export CUDA_VISIBLE_DEVICES=4,5,6,7
export HIP_VISIBLE_DEVICES=4,5,6,7

vllm serve Qwen/Qwen3-235B-A22B-FP8 \
  -tp 4 \
  --port 40005 \
  --gpu-memory-utilization 0.9 \
  --kv-transfer-config '{
    "kv_connector": "MoRIIOConnector",
    "kv_role": "kv_consumer",
    "kv_connector_extra_config": {
      "proxy_ip": "127.0.0.1",
      "http_port": "40005",
      "proxy_ping_port": "36367",
      "handshake_port": "7301",
      "notify_port": "7501"
    }
  }'

代理服务器

代理位于生产者和消费者实例前端,负责将传入请求路由给它们。推荐使用 vllm-router 作为代理;它可以手动安装或作为 Docker 容器运行。请注意,下方的端口 36367 是在每个 vLLM 实例上配置的 proxy_ping_port

Docker

docker run \
  --network host \
  vllm/vllm-router:nightly \
  vllm-router \
  --vllm-pd-disaggregation \
  --kv-connector moriio \
  --vllm-discovery-address "0.0.0.0:36367"

手动安装

pip install vllm-router
vllm-router \
  --vllm-pd-disaggregation \
  --kv-connector moriio \
  --vllm-discovery-address "0.0.0.0:36367"

或者,您可以使用 vLLM 附带的参考实现代理

cd <path_to>/vllm
pip install quart aiohttp msgpack
python examples/disaggregated/disaggregated_serving/moriio_toy_proxy_server.py

配置

连接器在两个层面进行配置:应用级和传输层。

应用级配置

模式: MoRI 有两种操作模式:WRITE 模式和 READ 模式。

  • 在 WRITE 模式下,生产者在每一层计算完成后,主动将计算好的 KV 块推送到消费者的内存中。
  • 在 READ 模式下,消费者在收到这些块已就绪的通知后,立即从生产者处一次性拉取所有 KV 块。

默认使用 WRITE 模式。可以通过设置 --kv-transfer-config.kv_connector_extra_config.read_mode true 来配置 READ 模式。

控制平面配置: MoRI 通过 RDMA/xGMI 移动 KV 数据,但生产者和消费者还需要带外 TCP 通道进行握手、块 ID 交换、活跃度检测和完成信号。这些键位于 kv_connector_extra_config 下:

  • proxy_ip:位于 prefiller 和 decoder 前端的解耦代理/路由器的 IP 地址。每个 vLLM 实例都使用它来注册自己并发送心跳,以便代理知道如何路由传入请求。
  • proxy_ping_portproxy_ip 上的 TCP 端口,代理在此监听实例心跳和注册消息。用于检测宕机的 vLLM 实例并保持路由表更新。
  • http_port:此 vLLM 实例暴露其 OpenAI 兼容 API 的 HTTP 端口。代理会注册此端口,并在选定实例后将用户请求转发至该端口。
  • handshake_port:用于 prefiller 和 decoder 之间一次性 MoRI 引擎握手的 TCP 端口。双方在进行任何 KV 传输之前在此交换 RDMA 引擎描述符。
  • notify_port:用于 prefiller 和 decoder 之间控制和同步消息的 TCP 端口。在两种模式下的用法不同:
    • WRITE 模式:块分配: decoder 通知 prefiller 其块 ID,以便 prefiller 可以将计算出的 KV 块推送到 decoder 实例上的正确位置。完成: 一旦所有块传输完成,prefiller 通知 decoder 可以安全使用其块了。
    • READ 模式:完成: 一旦 decoder 从 prefiller 读取了所有块,它会通知 prefiller,以便其释放 KV 缓存块。

注意

notify_port 被用作基础端口:实例内的每个 (DP rank, TP rank) 对使用 notify_port + offset,其中 offset 基于 rank。请确保主机上以 notify_port 开始的端口范围是空闲的。

传输层配置

MoRI 有两个传输后端:RDMA 和 xGMI。您可以使用 --kv-transfer-config.kv_connector_extra_config.backend $BACKEND 选择后端,其中 $BACKENDrdmaxgmi。RDMA 是默认后端,应在多节点部署中使用。

各后端的配置选项如下:

RDMA 后端

  • qp_per_transfer:每次传输使用的 RDMA 队列对 (QP) 数量。更多的 QP 可以让单次传输条带化分布在多个 QP 上,以增加 NIC 并发性,代价是消耗更多 RDMA 资源。
  • post_batch_size:多少个 RDMA 工作请求 (WR) 被批量合并到一个 ibv_post_send 门铃(doorbell)中。默认为 -1,表示使用后端默认值。较大的批次可减少每个 WR 的发布开销。
  • num_workers:MoRI 用于发布和轮询传输完成情况的工作线程数量。

高级用户还可以使用环境变量(如 MORI_IO_QP_MAX_SEND_WRMORI_IO_QP_MAX_CQE 等)配置 MoRI 本身。这些是 MoRI 库变量,与 vLLM 自身的 VLLM_MORIIO_* 设置是分开的。有关更多信息,请参考 MoRI 仓库

xGMI 后端

当 prefiller 和 decoder 运行在同一个物理主机上时,请使用 xGMI,这样传输将通过 AMD GPU fabric 进行,从而完全绕过 NIC。目前仅使用 MoRI 特定的环境变量进行配置;请参见 MoRI 仓库

多节点部署

下面的示例展示了如何在两个节点上运行 1P1D 部署。我们在 prefill 实例所在的节点上运行代理。

在两个节点上

# Set on both nodes before running any command
export PREFILL_IP=<node1-ip>
export DECODE_IP=<node2-ip>

在节点 1 上

按照代理服务器中的说明先启动代理,然后启动 prefill 实例

docker run \
  --name moriio-prefill \
  --init --network host --ipc host --privileged \
  --security-opt seccomp=unconfined \
  --ulimit memlock=-1 --ulimit stack=67108864 --shm-size 256G \
  --group-add video --group-add render \
  --device /dev/kfd --device /dev/dri --device /dev/infiniband \
  -e VLLM_ROCM_USE_AITER=1 \
  vllm/vllm-openai-rocm:nightly \
  deepseek-ai/DeepSeek-R1-0528 \
    --port 8100 \
    --tensor-parallel-size 8 \
    --enable-expert-parallel \
    --gpu-memory-utilization 0.8 \
    --trust-remote-code \
    --kv-transfer-config '{
      "kv_connector": "MoRIIOConnector",
      "kv_role": "kv_producer",
      "kv_connector_extra_config": {
        "proxy_ip": "'"${PREFILL_IP}"'",
        "proxy_ping_port": "36367",
        "http_port": "8100",
        "handshake_port": "6301",
        "notify_port": "61005"
      }
    }'

在节点 2 上

Decode 实例

docker run \
  --name moriio-decode \
  --init --network host --ipc host --privileged \
  --security-opt seccomp=unconfined \
  --ulimit memlock=-1 --ulimit stack=67108864 --shm-size 256G \
  --group-add video --group-add render \
  --device /dev/kfd --device /dev/dri --device /dev/infiniband \
  -e VLLM_ROCM_USE_AITER=1 \
  vllm/vllm-openai-rocm:nightly \
  deepseek-ai/DeepSeek-R1-0528 \
    --port 8200 \
    --tensor-parallel-size 8 \
    --gpu-memory-utilization 0.8 \
    --trust-remote-code \
    --enable-expert-parallel \
    --kv-transfer-config '{
      "kv_connector": "MoRIIOConnector",
      "kv_role": "kv_consumer",
      "kv_connector_extra_config": {
        "proxy_ip": "'"${PREFILL_IP}"'",
        "proxy_ping_port": "36367",
        "http_port": "8200",
        "handshake_port": "6301",
        "notify_port": "61005"
      }
    }'

故障排除

availDevices.size() > 0 断言失败

问题: vLLM 启动失败,日志如下:

libibverbs: Warning: Driver bnxt_re does not support the kernel ABI of 6 (supports 1 to 1) for device /sys/class/infiniband/rdma4
...
ker: /app/mori/src/io/rdma/backend_impl.cpp: mori::io::RdmaManager::RdmaManager(const RdmaBackendConfig, application::RdmaContext *): Assertion `availDevices.size() > 0' failed.

修复: 安装的 RDMA 用户态库与主机上安装的驱动程序和固件版本不匹配。您必须安装与您的 RDMA 内核模块和固件版本相对应的 NIC 用户态库。有关更多信息,请参阅安装 NIC 用户态库

附录:安装 NIC 用户态库

要使用 RDMA 运行 MoRI,您的环境必须安装必要的 RDMA 用户态库,这些库需与相关的内核模块和固件版本相匹配。

官方镜像 vllm/vllm-openai-rocm:nightly 预装了以下 NIC 和内核模块版本的用户态库:

  • AINIC (AMD Pensando Pollara):版本 1.117.3-hydra,已在 ioinic-dkms=25.11.1.001 环境下测试
  • Thor2 (Broadcom):版本 235.2.86.0,已在 bnxt-en-dkms=1.10.3.235.2.86.0bnxt-re-dkms=235.2.86.0 环境下测试

有关更多详情,请参考 Dockerfile.rocm。对于使用上述以外的 NIC、内核模块和/或固件的用户,我们建议参考各厂商自己的安装说明。

延伸阅读