拓冰建站拓冰建站
首页 / 资讯中心 / 正文

vLLM MoRIIOConnector 实战指南:基于 MoRI-IO 的高性能 PD 分离 KV Cache 传输

vLLM MoRIIOConnector 实战指南基于 MoRI-IO 的高性能 PD 分离 KV Cache 传输【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllmMoRIIOConnector是 vLLM 中一个面向 PDPrefill-Decode分离部署的高性能 KV 缓存连接器构建于 ROCm 的 MoRI-IO 点对点通信库之上通过 RDMA 或 xGMI 传输 KV 字节并叠加轻量 TCP 控制面完成握手、块号交换与完成信号。读完本文你将掌握 MoRIIOConnector 的安装部署、单机/多机 PD 分离的完整启动流程、全部应用级与传输层配置项的含义以及 RDMA 环境常见故障的定位方法并能结合 vLLM 仓库源码理解其 WRITE/READ 两种传输模式的底层工作机制。一、架构总览MoRIIOConnector 在 vLLM 中的位置在 vLLM 的 KV 连接器工厂注册表中MoRIIOConnector被映射到实现模块见 factory 注册表。其核心实现位于vllm/distributed/kv_transfer/kv_connector/v1/moriio/目录moriio_connector.py连接器主体实现KVConnectorBase_V1接口负责请求级元数据管理、TP rank 对齐、与路由代理的注册/心跳moriio_common.py配置解析MoRIIOConfig、常量、ZMQ 地址编解码moriio_engine.pyMoRI IOEngine 封装MoRIIOWriter实现 WRITE 模式的逐层写入状态机moriio_layout.pyKV 块布局与按层传输几何计算支持 MLA 与标准 Attention 布局。从源码结构看连接器依赖mori.io模块IOEngine、IOEngineConfig、BackendType等若环境未安装 MoRI导入阶段仅会记录错误日志并置MoRIIO_enabled False因此该连接器只在安装了 MoRI 的 ROCm 环境中可用。配套的单元测试位于 tests/v1/kv_connector/unit/覆盖路由公平性、TP ACK、unmap 等场景可作为行为参照。二、前置条件与安装MoRI 有两种安装方式Docker推荐MoRI 随官方 ROCm vLLM 镜像vllm/vllm-openai-rocm:nightly一起提供开箱即用手动安装pip install amd_mori镜像构建细节可参考 Dockerfile.rocm_base从源码构建 MoRI 的方法见 MoRI 官方仓库ROCm 的 mori 项目。若使用 RDMA 后端还需要安装与主机内核模块/固件版本匹配的网卡用户态userspace库具体见文末附录安装 NIC 用户态库。三、单机基本用法启动顺序上建议先启动代理proxyproducer 与 consumer 实例会持续重试注册直到代理可达。以下示例以单机 8 卡、Qwen3-235B-A22B-FP8 模型为例。3.1 ProducerPrefiller配置启动一个生成 KV 缓存的 prefiller 实例GPU 0-3# Prefill instance (GPU 0-3) export VLLM_ROCM_USE_AITER1 export CUDA_VISIBLE_DEVICES0,1,2,3 export HIP_VISIBLE_DEVICES0,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 } }3.2 ConsumerDecoder配置启动消费 KV 缓存的 decoder 实例GPU 4-7# Decode instance (GPU 4-7) export VLLM_ROCM_USE_AITER1 export CUDA_VISIBLE_DEVICES4,5,6,7 export HIP_VISIBLE_DEVICES4,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 } }注意两侧kv_role不同kv_producer/kv_consumer且端口错开以避免冲突。3.3 代理服务代理位于 producer 与 consumer 之前负责接收用户请求并路由到对应实例。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从 moriio_toy_proxy_server.py 的源码可以看到代理与实例之间的注册协议每个 vLLM 实例通过 ZMQ ROUTER 向代理的注册端口发送 msgpack 消息消息需包含http_address、zmq_address格式为host:IP,handshake:PORT,notify:PORT、dp_size、tp_size、transfer_mode等字段代理把两侧实例的 zmq 地址嵌入request_id形如___prefill_addr_{zmq}___decode_addr_{zmq}_{32位hex}由连接器在对端请求中解析出对端连接信息——这一编解码逻辑正是 parse_moriio_zmq_address 所实现的且解析时按第一个冒号切分以兼容 IPv6 地址。该参考代理文件头部的注释也明确它演示的是单节点下的 DP-rank 绑定契约生产多 Pod 部署应使用 llm-d-router、vllm-router 或满足同一kv_transfer_params契约的路由 sidecar。四、配置详解MoRIIOConnector 的配置分为两层应用级角色、控制面端口、传输模式与传输级RDMA / xGMI 后端及其调优参数全部通过--kv-transfer-config.kv_connector_extra_config传入。源码中这些键在 MoRIIOConfig.from_vllm_config 中被逐一解析。4.1 应用级配置传输模式ModeMoRI 提供 WRITE 与 READ 两种工作模式。WRITE 模式默认producer 在每一层计算完成后主动把该层的 KV 块推送到 consumer 的内存中READ 模式consumer 在收到块已就绪通知后一次性从 producer 拉取全部 KV 块。READ 模式通过--kv-transfer-config.kv_connector_extra_config.read_mode true开启。源码侧的解析见 get_moriio_mode仅当值为true或1不区分大小写时进入 READ 模式否则回落到 WRITE。WRITE 模式的逐层写入状态机在 MoRIIOWriter 中有明确注释decoder 先发送目标块分配信息block allocationprefiller 在每层的 CUDA event 之后调度一次写入前向结束后对已调度写入计数做封层seal所有写入完成后再通知 decoder 并释放 producer 侧块。控制面配置MoRI 的 KV 字节流走 RDMA/xGMI但 producer 与 consumer 之间还需要带外的 TCP 通道来完成握手、块号交换、存活探测与完成信号。以下键均位于kv_connector_extra_config之下配置键含义proxy_ipPD 分离代理/路由器的 IP 地址。每个 vLLM 实例用它注册自身并发送心跳让代理知道向哪里路由请求proxy_ping_portproxy_ip上代理监听实例心跳与注册消息的 TCP 端口用于探测死掉的 vLLM 实例、保持路由表新鲜http_port本 vLLM 实例对外暴露 OpenAI 兼容 API 的 HTTP 端口。代理注册该端口在选定实例后把用户请求转发过来handshake_portprefiller 与 decoder 之间一次性 MoRI 引擎握手使用的 TCP 端口两侧在此交换 RDMA 引擎描述符之后才能开始 KV 传输notify_portprefiller 与 decoder 之间控制和同步消息的 TCP 端口两种模式下用途不同见下notify_port在两种模式下的具体职责WRITE 模式块分配decoder 把自身的块 id 通知给 prefillerprefiller 据此把计算好的 KV 块推到 decoder 实例的正确位置完成所有块传输完成后prefiller 通知 decoder 可以安全使用这些块。READ 模式完成decoder 从 prefiller 读走全部块后通知 prefiller 可以释放其 KV 缓存块。注意notify_port是作为**基地址端口base port**使用的。实例内每个 (DP rank, TP rank) 对使用notify_port offset偏移量由 rank 计算。请确保从notify_port起始的一段端口范围在主机上空闲。偏移量计算逻辑见 get_port_offsetoffset dp_rank * tp_size tp_rank并在 from_vllm_config 中以notify_port base_notify_port port_offset的形式生效。此外host_ip键可显式指定实例对外通告的 KV 传输 IP用于 Ray 等框架下get_ip()解析到不可路由地址的场景见 resolve_host_iptransfer_timeout默认 30 秒与defer_timeout默认 60 秒两个超时项分别控制等待传输完成与回收无完成的延迟发送均可在kv_connector_extra_config中覆盖见 MoRIIOConstants。值得一提的是源码中的_DEPRECATED_ENV_VARS表明早期版本曾用VLLM_MORIIO_CONNECTOR_READ_MODE、VLLM_MORIIO_QP_PER_TRANSFER、VLLM_MORIIO_POST_BATCH_SIZE、VLLM_MORIIO_NUM_WORKERS等环境变量传递这些参数现已弃用并会被忽略统一改由kv_connector_extra_config传入。4.2 传输级配置TransportMoRI 有两个传输后端RDMA与xGMI。通过--kv-transfer-config.kv_connector_extra_config.backend $BACKEND选择$BACKEND取rdma或xgmi。源码校验逻辑moriio_common.py对后端名做小写化并严格白名单校验取值非法会直接抛ValueError。RDMA 是默认后端多节点部署应使用 RDMA。RDMA 后端qp_per_transfer每次传输使用的 RDMA 队列对Queue Pair数量默认 1。更多 QP 可让单次传输在多个 QP 上条带化提高网卡并发度代价是占用更多 RDMA 资源post_batch_size一次ibv_post_send门铃doorbell中批处理的 RDMA 工作请求Work Request数量默认 -1即交给 MoRI 后端默认值。更大的批次能降低每个 WR 的提交开销num_workersMoRI 用于提交传输与轮询完成事件completion的后台工作线程数默认 1。高级用户还可以通过MORI_IO_QP_MAX_SEND_WR、MORI_IO_QP_MAX_CQE等环境变量直接配置 MoRI 库本身。这些是 MoRI 库变量与 vLLM 侧的配置项相互独立细节见 MoRI 官方仓库。xGMI 后端当 prefiller 与 decoder 位于同一物理主机时可改用 xGMI 后端传输走 AMD GPU 之间的 xGMI fabric完全绕开网卡。该后端目前只能通过 MoRI 专属的环境变量配置参见 MoRI 官方仓库。注意上文的 RDMA 调优参数qp_per_transfer、post_batch_size、num_workers在 xGMI 后端下会被忽略源码注释明确标注 Knobs for RDMA transfers, ignored if on xgmi backend。五、多节点部署1P1D以下示例展示在两节点上运行 1P1D 部署代理与 prefill 实例部署在同一节点。示例镜像为vllm/vllm-openai-rocm:nightly模型为deepseek-ai/DeepSeek-R1-0528。5.1 两节点通用设置# Set on both nodes before running any command export PREFILL_IPnode1-ip export DECODE_IPnode2-ip5.2 Node 1代理 Prefill 实例先按代理服务一节启动代理然后启动 prefill 实例docker run \ --name moriio-prefill \ --init --network host --ipc host --privileged \ --security-opt seccompunconfined \ --ulimit memlock-1 --ulimit stack67108864 --shm-size 256G \ --group-add video --group-add render \ --device /dev/kfd --device /dev/dri --device /dev/infiniband \ -e VLLM_ROCM_USE_AITER1 \ 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 } }5.3 Node 2Decode 实例docker run \ --name moriio-decode \ --init --network host --ipc host --privileged \ --security-opt seccompunconfined \ --ulimit memlock-1 --ulimit stack67108864 --shm-size 256G \ --group-add video --group-add render \ --device /dev/kfd --device /dev/dri --device /dev/infiniband \ -e VLLM_ROCM_USE_AITER1 \ 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 } }注意容器参数中--device /dev/infiniband暴露 RDMA 设备、--ulimit memlock-1RDMA 注册内存需要无限制锁内存与--privileged等选项是 RDMA 路径的必要前提两侧的handshake_port与notify_port可以相同因为它们绑定在不同的主机上。六、故障排查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 用户态库要让 MoRI 跑在 RDMA 上环境必须安装与内核模块和固件版本匹配的 RDMA 用户态库。官方镜像vllm/vllm-openai-rocm:nightly预装了以下网卡与内核模块版本的配套用户态库详见 Dockerfile.rocmAINICAMD Pensando Pollara版本1.117.3-hydra与ioinic-dkms25.11.1.001测试通过Thor2Broadcom版本235.2.86.0与bnxt-en-dkms1.10.3.235.2.86.0、bnxt-re-dkms235.2.86.0测试通过。如果你的网卡、内核模块或固件不在上述组合之列请遵循相应厂商的安装说明自行安装配套的用户态库。小结MoRIIOConnector 把 PD 分离场景下的 KV 缓存传输拆成了清晰的两个平面数据面由 MoRI-IO 经 RDMA跨节点或 xGMI同主机搬运 KV 字节控制面则用少量 TCP 端口proxy_ping_port、handshake_port、notify_port完成实例注册、引擎握手与块级同步。掌握kv_connector_extra_config中各键的语义——尤其是notify_port的基地址端口 rank 偏移分配规则、WRITE/READ 两种模式在块分配与完成通知上的差异、以及 RDMA 三个调优参数——就能把它部署到从单机 8 卡到跨节点 1P1D 的实际 PD 分离环境中再配合仓库内 moriio_connector.py 与单元测试 test_moriio_connector.py可以进一步验证请求路由、TP rank 对齐与传输确认等行为是否符合预期。【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门