MoRIIOConnector 사용 가이드

MoRIIOConnector 사용 가이드 (MoRIIOConnector Usage Guide)

MoRIIOConnector 는 PD 분리 배포에서 KV 캐시 전송에 사용되는 고성능 KV 커넥터로, ROCm의 MoRI-IO 통신 라이브러리 위에 구축되어 초저오버헤드 point-to-point 통신을 제공해요.

출처: 문서

본문

사전 준비 (Prerequisites)

설치 (Installation)

Docker: MoRI는 공식 ROCm vLLM 이미지 vllm/vllm-openai-rocm:nightly 에 포함되어 있습니다.

수동 설치: MoRI wheel은 다음으로 설치할 수 있어요.

pip install amd_mori

자세한 내용은 Dockerfile.rocm_base 또는 MoRI를 소스에서 빌드하는 방법은 공식 MoRI 저장소 를 참고하세요.

적절한 NIC userspace 라이브러리 설치에 대한 지침은 NIC userspace 라이브러리 설치 를 참고하세요.

기본 사용법 (단일 호스트)

먼저 프록시를 시작하세요. 프로듀서와 컨슈머 인스턴스는 프록시에 도달할 수 있을 때까지 등록을 재시도합니다.

프로듀서 (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"
    }
  }'

프록시 서버 (Proxy server)

프록시는 프로듀서와 컨슈머 인스턴스 앞에서 들어오는 요청을 그들에게 라우팅합니다. 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

구성 (Configuration)

커넥터는 애플리케이션 레벨과 전송 레벨의 두 가지 수준으로 구성됩니다.

애플리케이션 레벨 구성 (Application-level configuration)

모드: MoRI는 WRITE와 READ의 두 가지 작동 모드가 있습니다.

  • WRITE 모드에서 프로듀서는 매 레이어 이후 계산된 KV 블록을 컨슈머의 메모리로 적극적으로 푸시합니다.
  • READ 모드에서 컨슈머는 블록이 준비되었음을 통지받는 즉시 프로듀서에서 KV 블록을 한 번에 모두 풀합니다.

기본적으로 WRITE 모드가 사용됩니다. READ 모드는 --kv-transfer-config.kv_connector_extra_config.read_mode true 로 구성할 수 있어요.

컨트롤 플레인 구성: MoRI는 RDMA/xGMI로 KV 바이트를 이동하지만, 프로듀서와 컨슈머는 핸드셰이크, 블록 ID 교환, 라이브니스, 완료 신호를 위한 대역 외(out-of-band) TCP 채널도 필요합니다. 이 키들은 kv_connector_extra_config 아래에 있습니다.

  • proxy_ip: prefiller와 decoder 앞에 있는 분리 프록시/라우터의 IP 주소입니다. 각 vLLM 인스턴스는 등록과 하트비트 전송에 이를 사용해 프록시가 들어오는 요청을 어디로 라우팅할지 알게 합니다.
  • proxy_ping_port: 프록시가 인스턴스 하트비트와 등록 메시지를 수신하는 proxy_ip 의 TCP 포트입니다. 죽은 vLLM 인스턴스를 감지하고 라우팅 테이블을 최신으로 유지하는 데 사용됩니다.
  • http_port: 이 vLLM 인스턴스가 OpenAI 호환 API를 노출하는 HTTP 포트입니다. 프록시는 이 포트를 등록하고 인스턴스를 선택한 다음 사용자 요청을 이 포트로 전달합니다.
  • handshake_port: prefiller와 decoder 간의 일회성 MoRI 엔진 핸드셰이크에 사용되는 TCP 포트입니다. 양쪽은 어떤 KV 전송이 일어나기 전에 여기서 RDMA 엔진 디스크립터를 교환합니다.
  • notify_port: prefiller와 decoder 간의 제어 및 동기화 메시지에 사용되는 TCP 포트입니다. 두 모드에서 다르게 사용됩니다.
    • WRITE 모드:
      • 블록 할당(Block allocation): decoder가 prefiller에게 자체 블록 id를 알려 prefiller가 계산된 KV 블록을 decoder 인스턴스의 올바른 위치에 푸시할 수 있게 합니다.
      • 완료(Completion): 모든 블록이 전송되면 prefiller가 decoder에게 블록을 안전하게 사용할 수 있음을 통지합니다.
    • READ 모드:
      • 완료(Completion): decoder가 prefiller에서 모든 블록을 읽으면 prefiller에게 통지해 KV 캐시 블록을 해제하게 합니다.

참고: notify_port기본 포트로 사용됩니다. 인스턴스 내 각 (DP rank, TP rank) 쌍은 notify_port + offset 을 사용하며 offset은 랭크에 기반합니다. notify_port 부터 시작하는 범위가 호스트에서 비어 있는지 확인하세요.

전송 구성 (Transport configuration)

MoRI에는 RDMA와 xGMI 두 가지 전송 백엔드가 있습니다. --kv-transfer-config.kv_connector_extra_config.backend $BACKEND 로 백엔드를 선택할 수 있으며, $BACKENDrdma 또는 xgmi 입니다. RDMA가 기본 백엔드이며 다중 노드 배포에서 사용해야 합니다.

각 백엔드의 구성 옵션은 다음과 같습니다.

RDMA 백엔드

  • qp_per_transfer: 전송당 사용되는 RDMA 큐 페어(QP) 수입니다. QP가 많을수록 단일 전송을 여러 QP에 스트라이핑해 NIC 동시성을 높일 수 있지만 더 많은 RDMA 리소스를 소모합니다.
  • post_batch_size: 하나의 ibv_post_send doorbell에 배치되는 RDMA 워크 리퀘스트(WR) 수입니다. 기본값은 -1로 백엔드 기본값을 의미합니다. 더 큰 배치는 WR당 posting 오버헤드를 줄입니다.
  • num_workers: MoRI가 전송 완료를 post하고 poll하는 데 사용하는 워커 스레드 수입니다.

고급 사용자는 MORI_IO_QP_MAX_SEND_WR, MORI_IO_QP_MAX_CQE 같은 환경 변수로 MoRI 자체도 구성할 수 있습니다. 이들은 MoRI 라이브러리 변수이며 vLLM 자체의 VLLM_MORIIO_* 설정과는 별개입니다. 자세한 내용은 MoRI 저장소 를 참고하세요.

xGMI 백엔드

prefiller와 decoder가 같은 물리 호스트에서 실행될 때 xGMI를 사용하면 전송이 AMD GPU 패브릭을 통해 이루어져 NIC를 완전히 건너뜁니다. 현재 MoRI 전용 환경 변수로만 구성됩니다. MoRI 저장소 를 참고하세요.

다중 노드 배포 (Multi-node deployment)

아래 예시는 두 노드에서 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"
      }
    }'

트러블슈팅 (Troubleshooting)

availDevices.size() > 0 assertion 실패

문제: 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 userspace 라이브러리가 호스트에 설치된 드라이버 및 펌웨어 버전과 일치하지 않습니다. RDMA 커널 모듈과 펌웨어 버전에 해당하는 NIC userspace 라이브러리를 설치해야 합니다. 자세한 내용은 NIC userspace 라이브러리 설치 를 참고하세요.

부록 (Appendix): NIC userspace 라이브러리 설치

RDMA로 MoRI를 실행하려면 환경에 관련 커널 모듈 및 펌웨어 버전과 일치하는 필요한 RDMA userspace 라이브러리가 설치되어 있어야 합니다.

공식 이미지 vllm/vllm-openai-rocm:nightly 에는 다음 NIC 및 커널 모듈 버전에 대한 userspace 라이브러리가 사전 설치되어 있습니다.

  • AINIC (AMD Pensando Pollara): 버전 1.117.5-a-77, libionic1=54.0-187-1 을 포함하며 ionic-dkms=26.03.3.001 로 테스트됨.
  • Thor2 (Broadcom): 버전 235.2.86.0, bnxt-en-dkms=1.10.3.235.2.86.0, bnxt-re-dkms=235.2.86.0 로 테스트됨.

자세한 내용은 Dockerfile.rocm 을 참고하세요. 위에 나열된 것과 다른 NIC, 커널 모듈, 및/또는 FW를 사용하는 사용자는 공급업체의 자체 설치 지침을 참조하세요.

추가 자료 (Further reading)

더 알아보기 (Learn more)