NixlConnector 사용 가이드

NixlConnector 사용 가이드 (NixlConnector Usage Guide)

NixlConnector는 vLLM의 분리형 프리필링(disaggregated prefilling) 기능을 위한 고성능 KV 캐시 전송 커넥터예요. NIXL 라이브러리를 사용해 완전히 비동기적인 send/receive 연산을 제공하며 효율적인 프로세스 간 KV 캐시 전송을 지원합니다.

기능 호환성 세부 사항(지원 모델 아키텍처, TP 구성, 기능 상호작용)은 NixlConnector 호환성 매트릭스 를 참고하세요.

출처: 문서

본문

사전 준비 (Prerequisites)

설치 (Installation)

NIXL 라이브러리를 설치합니다.

uv pip install nixl

Nvidia 플랫폼에서 빠르게 시작하는 방법입니다. 더 자세한 설치 지침은 NIXL 공식 저장소 를 참고하세요. 필요로 하는 NIXL 버전은 requirements/kv_connectors.txt 및 기타 관련 구성 파일에서 확인할 수 있습니다.

ROCm의 경우 ROCm Dockerfile 이 NIXL과 UCX를 ROCm 지원으로 소스에서 빌드합니다.

비-CUDA 플랫폼에서는 아래처럼 ucx 빌드로 nixl을 소스에서 설치하세요.

python tools/install_nixl_from_source_ubuntu.py

전송 구성 (Transport Configuration)

NixlConnector는 기본 통신에 NIXL 라이브러리를 사용하며, 이는 여러 전송 백엔드를 지원합니다. UCX(Unified Communication X)는 NIXL이 사용하는 기본 전송 라이브러리예요. 전송 환경 변수를 구성하세요.

# Example UCX configuration, adjust according to your environment
export UCX_TLS=all  # or specify specific transports like "rc,ud,sm,^cuda_ipc" ..etc
export UCX_NET_DEVICES=all  # or specify network devices like "mlx5_0:1,mlx5_1:1"

: UCX를 전송 백엔드로 사용할 때 NCCL 환경 변수(NCCL_IB_HCA, NCCL_SOCKET_IFNAME 등)는 NixlConnector에 적용되지 않습니다. NCCL 변수 대신 UCX 전용 환경 변수를 구성하세요.

NIXL 전송 백엔드(플러그인) 선택

NixlConnector는 서로 다른 NIXL 전송 백엔드(플러그인)를 사용할 수 있습니다. 기본적으로 NixlConnector는 UCX를 전송 백엔드로 사용합니다.

다른 백엔드를 선택하려면 --kv-transfer-config 에서 kv_connector_extra_config.backends 를 설정하세요.

LIBFABRIC 백엔드 사용 예시:

vllm serve <MODEL> \
  --kv-transfer-config '{
    "kv_connector":"NixlConnector",
    "kv_role":"kv_producer",
    "kv_connector_extra_config":{"backends":["LIBFABRIC"]}
  }'

JSON 키를 점 표기법 인자로 개별 전달할 수도 있고, + 를 사용해 목록 요소를 추가할 수도 있습니다.

vllm serve <MODEL> \
  --kv-transfer-config.kv_connector NixlConnector \
  --kv-transfer-config.kv_role kv_producer \
  --kv-transfer-config.kv_connector_extra_config.backends+ LIBFABRIC

참고: 백엔드 가용성은 NIXL이 어떻게 빌드되었는지와 환경에 어떤 플러그인이 있는지에 따라 달라집니다. 사용 가능한 백엔드와 빌드 지침은 NIXL 저장소 를 참고하세요.

기본 사용법 (같은 호스트)

프로듀서 (Prefiller) 구성

KV 캐시를 생성하는 prefiller 인스턴스를 시작합니다.

# 1st GPU as prefiller
CUDA_VISIBLE_DEVICES=0 \
UCX_NET_DEVICES=all \
VLLM_NIXL_SIDE_CHANNEL_PORT=5600 \
vllm serve Qwen/Qwen3-0.6B \
  --port 8100 \
  --enforce-eager \
  --kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_producer","kv_load_failure_policy":"fail"}'

컨슈머 (Decoder) 구성

KV 캐시를 소비하는 decoder 인스턴스를 시작합니다.

# 2nd GPU as decoder
CUDA_VISIBLE_DEVICES=1 \
UCX_NET_DEVICES=all \
VLLM_NIXL_SIDE_CHANNEL_PORT=5601 \
vllm serve Qwen/Qwen3-0.6B \
  --port 8200 \
  --enforce-eager \
  --kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_consumer","kv_load_failure_policy":"fail"}'

프록시 서버 (Proxy Server)

프록시 서버를 사용해 prefiller와 decoder 사이에서 요청을 라우팅합니다.

python tests/v1/kv_connector/nixl_integration/toy_proxy_server.py \
  --port 8192 \
  --prefiller-hosts localhost \
  --prefiller-ports 8100 \
  --decoder-hosts localhost \
  --decoder-ports 8200

환경 변수 (Environment Variables)

  • VLLM_NIXL_SIDE_CHANNEL_PORT: NIXL 핸드셰이크 통신용 포트입니다.

    • 기본값: 5600
    • prefiller와 decoder 인스턴스 모두에 필요합니다.
    • 각 vLLM 워커는 호스트에서 고유한 포트가 필요하며, 서로 다른 호스트에서 같은 포트 번호를 쓰는 건 괜찮습니다.
    • TP/DP 배포에서는 노드의 각 워커 포트가 base_port + dp_rank 로 계산됩니다(예: --data-parallel-size=2 와 base_port=5600이면 dp_rank 0..1이 그 노드에서 포트 5600, 5601 사용).
    • prefiller와 decoder 간 초기 NIXL 핸드셰이크에 사용됩니다.
  • VLLM_NIXL_SIDE_CHANNEL_HOST: 사이드 채널 통신용 호스트입니다.

    • 기본값: "localhost"
    • prefiller와 decoder가 서로 다른 머신에 있을 때 설정합니다.
    • 연결 정보는 핸드셰이크를 위해 KVTransferParams를 통해 prefiller에서 decoder로 전달됩니다.
  • kv_lease_duration(kv_connector_extra_config 경유): prefiller의 KV 캐시 블록에 대한 임대 기간(초)입니다. (선택 사항)

    • 기본값: 30
    • prefill 요청이 끝나면 해당 KV 블록은 decoder가 읽을 때까지 이 기간 동안 보유됩니다. 요청이 decoder에 큐잉되는 동안 주기적 하트비트가 임대를 자동 연장합니다. 임대가 만료되기 전에 하트비트나 읽기 통지가 도착하지 않으면 블록이 해제됩니다. 하트비트 간격과 연장량은 이 값에서 자동으로 파생됩니다.
    • 예시: --kv-transfer-config '{"kv_connector_extra_config": {"kv_lease_duration": 60}}'
  • decoder_kv_blocks_ttl(kv_connector_extra_config 경유): 양방향 전송 모드에서 decoder에 캐시된 KV 블록의 TTL(초)입니다. (선택 사항)

    • 기본값: 480
    • 양방향 모드에서 decoder는 다회전 대화를 위해 KV 블록을 캐시합니다. 이 TTL은 해당 블록이 해제되기 전까지 보유되는 기간을 제어합니다. prefiller 임대와 달리 이 TTL은 하트비트로 갱신되지 않습니다.
    • 예시: --kv-transfer-config '{"kv_connector_extra_config": {"decoder_kv_blocks_ttl": 600}}'

양방향 KV 전송 (다회전, Bidirectional KV Transfer)

표준 분리형 프리필링에서 KV 캐시는 한 방향으로 흐릅니다. Prefill(P)이 KV 캐시를 계산하고 Decode(D)가 P로부터 읽습니다. 다회전 대화에서는 이것이 낭비입니다. D는 이전 턴에서 생성된 토큰에 해당하는 KV 캐시를 이미 보유하는데, P는 매 새 턴마다 이를 처음부터 재계산해야 하기 때문이에요. 양방향 KV 전송은 P가 새 토큰만 계산하기 전에 D에서 기존 KV 블록을 RDMA로 풀(pull) 수 있게 하여, 다회전이 많은 시나리오 같은 장문 프리필의 Time-To-First-Token(TTFT)을 크게 줄입니다.

동작 방식 (How it works)

이 기능은 클라이언트와 P/D 인스턴스 사이에 있는 상태 있는 프록시(stateful proxy) 에 의존합니다. 프록시는 각 턴 종료 시 D가 반환한 kv_transfer_params 를 추적하고 이를 다음 턴의 요청에 부착해 P가 D에서 어떤 블록을 풀어야 하는지 알게 합니다.

sequenceDiagram
    participant Client
    participant Proxy
    participant P as Prefill (P)
    participant D as Decode (D)

    rect rgb(240, 240, 250)
    note right of Client: Turn 1 — Cache Miss
    Client->>Proxy: chat request + conversation_id
    Proxy->>P: request (no remote blocks)
    activate P
    note over P: full prefill
    P-->>Proxy: kv_transfer_params (P's blocks)
    deactivate P
    Proxy->>D: request + P's kv_transfer_params
    activate D
    D-->P: RDMA read (D pulls KV from P)
    note over D: decode
    D-->>Proxy: stream response + kv_transfer_params
    deactivate D
    note over Proxy: cache D's kv_transfer_params
    Proxy-->>Client: response
    end

    rect rgb(255, 245, 235)
    note right of Client: Turn 2+ — Cache Hit (Bidirectional)
    Client->>Proxy: chat request + conversation_id
    note over Proxy: lookup cached D blocks
    Proxy->>P: request + D's remote_block_ids
    activate P
    P-->D: RDMA read (P pulls KV from D)
    note over P: prefill new tokens only
    P-->>Proxy: kv_transfer_params (P's blocks)
    deactivate P
    Proxy->>D: request + P's kv_transfer_params
    activate D
    D-->P: RDMA read (D pulls new KV from P)
    note over D: decode
    D-->>Proxy: stream response + kv_transfer_params
    deactivate D
    note over Proxy: update cached kv_transfer_params
    Proxy-->>Client: response
    end

턴 1 (cache miss):

  1. 클라이언트가 conversation_id 와 함께 채팅 요청을 프록시로 보냅니다.
  2. 프록시가 원격 블록 정보 없이 요청을 P로 전달하고, P가 전체 KV 캐시를 계산합니다.
  3. 프록시가 P의 kv_transfer_params(블록 ID, engine ID, host/port)와 함께 요청을 D로 전달합니다.
  4. D가 RDMA로 P에서 KV 블록을 읽고(peer-to-peer pull) 응답을 생성합니다.
  5. D가 프록시를 통해 응답을 스트리밍합니다. 마지막 청크에는 D 자신의 kv_transfer_params 가 포함됩니다.
  6. 프록시가 D의 kv_transfer_paramsconversation_id 로 키해 캐시한 다음 응답을 클라이언트에 반환합니다.

턴 2+ (cache hit — 양방향):

  1. 클라이언트가 같은 conversation_id 로 다음 턴을 보냅니다.
  2. 프록시가 이전 턴의 캐시된 kv_transfer_params 를 조회해 D의 remote_block_ids 를 P로 보내는 요청에 부착합니다.
  3. P가 RDMA로 D에서 기존 KV 캐시를 읽고(D→P pull) 새 토큰에 대해서만 KV를 계산합니다.
  4. 프록시가 P의 업데이트된 kv_transfer_params 와 함께 요청을 D로 전달합니다.
  5. D가 P에서 새 KV 블록을 읽고 응답을 생성하며, 프록시가 다음 턴을 위해 캐시할 업데이트된 kv_transfer_params 를 반환합니다.

구성 (Configuration)

P와 D 인스턴스 둘 다kv_connector_extra_config 에서 bidirectional_kv_xfer 를 설정해 양방향 KV 전송을 활성화합니다.

# Prefill instance
vllm serve <MODEL> \
  --kv-transfer-config '{
    "kv_connector": "NixlConnector",
    "kv_role": "kv_producer",
    "kv_connector_extra_config": {
      "bidirectional_kv_xfer": true
    }
  }'

# Decode instance
vllm serve <MODEL> \
  --kv-transfer-config '{
    "kv_connector": "NixlConnector",
    "kv_role": "kv_consumer",
    "kv_connector_extra_config": {
      "bidirectional_kv_xfer": true
    }
  }'

kv_connector_extra_config 의 추가 구성 옵션:

파라미터 기본값 설명
bidirectional_kv_xfer false 양방향 D→P KV 전송을 활성화합니다.
kv_recompute_threshold 64 D→P 풀을 트리거하는 최소 원격 토큰 수입니다. 이 임계값 아래에서는 P가 풀 대신 로컬로 재계산합니다(전송 지연을 분산시키기 위해).
decoder_kv_blocks_ttl 480 양방향 재사용을 위해 D에 캐시된 KV 블록의 TTL(초)입니다. 이 기간 후 블록이 해제됩니다. 하트비트로 갱신되지 않습니다.

다회전 프록시 설정 (Multi-turn proxy setup)

대화 턴에 걸쳐 kv_transfer_params 캐싱을 관리하려면 제공된 다회전 프록시를 사용하세요.

python examples/disaggregated/disaggregated_serving/disagg_proxy_multiturn.py \
  --host 0.0.0.0 --port 8000 \
  --prefiller-host <P_IP> --prefiller-port 8100 \
  --decoder-host <D_IP> --decoder-port 8200

프록시는 라운드로빈 방식으로 여러 P와 D 인스턴스를 지원합니다.

python examples/disaggregated/disaggregated_serving/disagg_proxy_multiturn.py \
  --host 0.0.0.0 --port 8000 \
  --prefiller-hosts <P_IP1> <P_IP2> --prefiller-ports 8100 8100 \
  --decoder-hosts <D_IP1> <D_IP2> --decoder-ports 8200 8200

클라이언트 사용법 (Client usage)

요청 본문에 conversation_id 필드를 포함해 턴 간 KV 재사용을 활성화하세요. 없으면 프록시는 턴을 연결할 수 없어 전체 재계산으로 폴백합니다.

# Turn 1
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen3-0.6B",
    "conversation_id": "session-42",
    "messages": [
      {"role": "user", "content": "What is vLLM?"}
    ]
  }'

# Turn 2 — same conversation_id triggers bidirectional KV pull
curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen3-0.6B",
    "conversation_id": "session-42",
    "messages": [
      {"role": "user", "content": "What is vLLM?"},
      {"role": "assistant", "content": "vLLM is a high-throughput LLM serving engine..."},
      {"role": "user", "content": "How does disaggregated prefilling work?"}
    ]
  }'

참고: conversation_id 필드는 OpenAI API의 비표준 확장입니다. 프록시가 소비하며 vLLM 엔진에는 전달되지 않습니다.

다회전 프록시 벤치마킹

benchmarks/multi_turn/benchmark_serving_multi_turn.py--send-conversation-id 플래그로 분리형 다회전 프록시를 대상으로 하는 것을 지원합니다. 이 플래그는 모든 요청 페이로드에 대화별 conversation_id 를 주입해 프록시가 턴 간 KV 캐시 재사용을 키할 수 있게 합니다.

이 플래그는 기본적으로 꺼져 있어서 알 수 없는 최상위 필드를 거부하는 엄격한 OpenAI 호환 프론트엔드와 호환됩니다. 다회전 프록시를 벤치마킹할 때는 명시적으로 전달해야 합니다. 그렇지 않으면 모든 턴이 cache MISS가 되어 양방향 KV 전송 경로가 전혀 실행되지 않습니다.

python benchmarks/multi_turn/benchmark_serving_multi_turn.py \
  --model <MODEL> --served-model-name <NAME> \
  --url http://<proxy_host>:8000 \
  --input-file benchmarks/multi_turn/generate_multi_turn.json \
  --num-clients 2 --max-active-conversations 6 \
  --send-conversation-id

제한 사항 (Limitations)

  • 턴 간 kv_transfer_params 를 추적하고 전달하려면 상태 있는 프록시(또는 이에 상응하는 라우터)가 필요합니다.
  • 현재 디바이스 버퍼 KV 캐시와 함께 CUDA에서 지원됩니다. 호스트 버퍼 지원(예: Intel XPU용)은 향후 작업으로 계획되어 있습니다.

thinking 흔적이 제거된 추론 모델 (Reasoning models with stripped thinking traces)

thinking 흔적(`thinking...`)을 생성하는 추론 모델(예: DeepSeek-R1)을 사용할 때, D의 KV 블록은 thinking 토큰을 포함한 전체 토큰 시퀀스를 덮습니다. 클라이언트가 다음 턴을 보내기 전에 대화 기록에서 thinking 흔적을 제거하면, P가 받는 프롬프트는 D가 생성한 것의 중간에서 토큰이 누락된 상태가 됩니다. 블록 정렬 로직은 P의 프롬프트가 D 시퀀스의 프리픽스라고 가정하므로, 이 경우 D에서 KV 블록을 풀면 잘못된 토큰 위치에 대해 계산된 캐시가 전송되어 잘못된 결과를 만듭니다.

우리는 현재 라우터가 턴 간 이러한 불일치를 감지할 수 있다고 가정합니다. #43094 을 참고하세요.

다중 인스턴스 설정 (Multi-Instance Setup)

서로 다른 머신의 여러 Prefiller 인스턴스

# Prefiller 1 on Machine A (example IP: ${IP1})
VLLM_NIXL_SIDE_CHANNEL_HOST=${IP1} \
VLLM_NIXL_SIDE_CHANNEL_PORT=5600 \
UCX_NET_DEVICES=all \
vllm serve Qwen/Qwen3-0.6B --port 8000 \
  --tensor-parallel-size 8 \
  --kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_producer","kv_load_failure_policy":"fail"}'

# Prefiller 2 on Machine B (example IP: ${IP2})
VLLM_NIXL_SIDE_CHANNEL_HOST=${IP2} \
VLLM_NIXL_SIDE_CHANNEL_PORT=5600 \
UCX_NET_DEVICES=all \
vllm serve Qwen/Qwen3-0.6B --port 8000 \
  --tensor-parallel-size 8 \
  --kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_producer","kv_load_failure_policy":"fail"}'

서로 다른 머신의 여러 Decoder 인스턴스

# Decoder 1 on Machine C (example IP: ${IP3})
VLLM_NIXL_SIDE_CHANNEL_HOST=${IP3} \
VLLM_NIXL_SIDE_CHANNEL_PORT=5600 \
UCX_NET_DEVICES=all \
vllm serve Qwen/Qwen3-0.6B --port 8000 \
  --tensor-parallel-size 8 \
  --kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_consumer","kv_load_failure_policy":"fail"}'

# Decoder 2 on Machine D (example IP: ${IP4})
VLLM_NIXL_SIDE_CHANNEL_HOST=${IP4} \
VLLM_NIXL_SIDE_CHANNEL_PORT=5600 \
UCX_NET_DEVICES=all \
vllm serve Qwen/Qwen3-0.6B --port 8000 \
  --tensor-parallel-size 8 \
  --kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_consumer","kv_load_failure_policy":"fail"}'

여러 인스턴스용 프록시

python tests/v1/kv_connector/nixl_integration/toy_proxy_server.py \
  --port 8192 \
  --prefiller-hosts ${IP1} ${IP2} \
  --prefiller-ports 8000 8000 \
  --decoder-hosts ${IP3} ${IP4} \
  --decoder-ports 8000 8000

다중 호스트 DP 배포에서는 헤드 인스턴스의 host/port만 제공하면 됩니다.

KV 역할 옵션 (KV Role Options)

  • kv_producer: KV 캐시를 생성하는 prefiller 인스턴스용입니다.
  • kv_consumer: prefiller로부터 KV 캐시를 소비하는 decoder 인스턴스용입니다.
  • kv_both (deprecated): 역할이 미리 정해지지 않았을 때 포괄적으로 사용되던 값입니다. 이 값은 이제 NixlConnector에서 deprecated이며 향후 릴리즈에서 제거될 예정입니다.

경고: kv_role="kv_both" 는 NixlConnector에서 deprecated입니다. prefill 인스턴스에는 kv_role="kv_producer" 를, decode 인스턴스에는 kv_role="kv_consumer" 를 설정하세요. 자세한 내용은 #33702 를 참고하세요.

KV 로드 실패 정책 (KV Load Failure Policy)

kv_load_failure_policy 설정은 decoder 인스턴스가 prefiller 인스턴스에서 KV 캐시 블록을 로드할 때 실패를 처리하는 방법을 제어합니다.

  • fail (기본값): KV 로드가 실패하면 오류와 함께 요청을 즉시 실패시킵니다. decode 인스턴스에서 prefill 작업의 재계산을 피해 성능 저하를 방지합니다.
  • recompute: 실패한 블록을 decode 인스턴스에서 로컬로 재계산합니다. 스케줄된 prefill이 지연되고 다른 디코드에 간섭하므로 decode 인스턴스에 성능 지터(jitter) 를 유발할 수 있습니다. 게다가 decode 인스턴스는 일반적으로 저지연 최적화로 구성됩니다.

경고: kv_load_failure_policy="recompute" 를 사용하면 프로덕션 배포에서 성능 저하를 일으킬 수 있습니다. KV 로드가 실패하면 decode 인스턴스가 decode에 최적화된 구성으로 prefill 작업을 실행하는데, 이는 비효율적이며 분리형 프리필링의 목적을 무너뜨립니다. 또한 진행 중인 다른 decode 요청의 꼬리 지연 시간도 늘립니다.

NVIDIA GB 시리즈 GPU용

GB 시리즈 GPU는 멀티노드 NVLink를 지원합니다. NIXL은 이 기능을 지원하지만, KVCache는 KVCache 등록 중 VMM으로 등록되어야 합니다. 이 기능을 활성화하려면 --enable-cumem-allocator 또는 --enable-sleep-mode 플래그를 설정하고 UCX_CUDA_IPC_ENABLE_MNNVL: 'y' 환경 변수를 설정해야 합니다. 그렇지 않으면 NIXL은 크로스 노드 KVCache 전송에 RDMA/TCP만 사용할 수 있습니다.

실험적 기능 (Experimental Feature)

이기종 KV 레이아웃 지원 (Heterogeneous KV Layout support)

지원 사용 사례: 실험적 구성으로 LBHNC 로 prefill하고 LBNHC 로 decode하는 경우.

--kv-transfer-config '{..., "enable_permute_local_kv":"True"}'

메트릭 참조 (Metrics Reference)

vLLM은 마지막 보고 간격의 NIXL 전송 활동을 요약하는 KV Transfer metrics 줄을 주기적으로 로깅합니다. 예시 출력:

KV Transfer metrics: Num successful transfers=4, Avg xfer time (ms)=1.381,
P90 xfer time (ms)=2.601, Avg post time (ms)=0.672, P90 post time (ms)=0.801,
Avg MB per transfer=2.25, Throughput (MB/s)=1629.549, Avg number of descriptors=72.0,
Num failed transfers=0, Num KV expired reqs=0

아래 표는 각 필드를 설명합니다. 모든 타이밍 값은 현재 간격에서 기록된 성공적인 전송만 다룹니다. 실패는 같은 줄의 간격 횟수와 Prometheus를 통해 보고됩니다.

메트릭 단위 설명
Num successful transfers count 간격 동안 오류 없이 완료된 NIXL KV-블록 전송 수입니다. 전송 하나는 prefill 요청 분량의 KV 캐시가 prefiller에서 decoder로 이동하는 것에 해당합니다(양방향 모드에서는 그 반대).
Avg xfer time (ms) ms 평균 종단 간 전송 기간입니다(NIXL 텔레메트리의 xferDuration, µs에서 변환). 요청이 post된 시점부터 백엔드가 완료를 보고할 때까지 측정되므로 posting 단계와 실제 데이터 이동을 모두 포함합니다.
P90 xfer time (ms) ms 90번째 백분위수 전송 기간입니다. 꼬리 지연 시간 파악에 사용합니다. 평균과 P90 사이의 큰 차이는 결함 지체자(예: 네트워크 혼잡이나 큰 KV 블록)를 시사합니다.
Avg post time (ms) ms RDMA 백엔드로 전송 요청을 제출하는 평균 시간입니다(NIXL 텔레메트리의 postDuration). 비동기 데이터 이동이 시작되기 전에 NIC 큐에 작업을 post하는 동기 비용(디스크립터 설정 등)입니다.
P90 post time (ms) ms 90번째 백분위수 요청-post 기간입니다. 여기서 P90이 높으면(전송 P90은 낮은데) 데이터 전송 자체가 아니라 요청 제출에서 오버헤드가 발생하고 있음을 가리킵니다.
Avg MB per transfer MB 전송당 평균 페이로드 크기로 total bytes transferred / number of transfers 로 계산됩니다. 단일 요청의 평균 KV 캐시 풋프린트(시퀀스 길이 × 레이어 × 헤드 차원 × dtype 바이트)를 반영합니다.
Throughput (MB/s) MB/s 간격 동안의 유효 대역폭입니다: 모든 성공 전송에 걸친 total MB transferred / total xfer time (s). 요청별 대역폭이 아니라 집계 처리량입니다.
Avg number of descriptors count 전송당 제출된 NIXL 메모리 디스크립터(scatter-gather 세그먼트)의 평균 수입니다. 디스크립터가 많을수록 더 단편화되거나 더 큰 KV 캐시 할당을 의미하며, 매우 높은 수는 디스크립터 등록 오버헤드를 증가시킬 수 있습니다.
Num failed transfers count 간격 동안 실패한 NIXL 전송, 핸드셰이크, 완료 통지(send_notif) 수입니다. 모두 드문 하위 전송 계층 이벤트이므로 함께 그룹화됩니다.
Num KV expired reqs count KV 블록이 읽히기 전에 만료된 요청 수입니다. 전송 문제가 아니라 오토스케일러/임대 튜닝 신호이므로 위의 실패 횟수와 별도로 보고됩니다.

Prometheus 메트릭

주기적 로그 줄 외에도 NixlConnector가 활성화되면 다음 Prometheus 메트릭이 내보내집니다.

메트릭 이름 타입 설명
vllm:nixl_xfer_time_seconds Histogram 전송당 RDMA 복사 기간(초)입니다.
vllm:nixl_post_time_seconds Histogram RDMA 백엔드로 전송 요청을 제출하는 시간(초)입니다.
vllm:nixl_bytes_transferred Histogram 전송당 이동된 바이트 수입니다.
vllm:nixl_num_descriptors Histogram 전송당 디스크립터 수입니다.
vllm:nixl_num_failed_transfers Counter 핸드셰이크와 통지(send_notif) 실패를 포함한 실패한 NIXL KV-블록 전송의 누적 수입니다. 모두 드문 하위 전송 계층 이벤트이므로 함께 그룹화됩니다.
vllm:nixl_num_failed_notifications Counter 실패한 통지(send_notif)의 누적 수이며 호환성을 위해 유지됩니다. 이 실패는 vllm:nixl_num_failed_transfers 에도 포함되므로 두 카운터를 합산하지 마세요.
vllm:nixl_num_kv_expired_reqs Counter decoder가 읽기 전에 prefiller에서 KV 블록이 만료된 요청 수(P 인스턴스에서 추적)입니다. 위의 실패 카운터와 분리되어 유지됩니다. KV 만료는 전송 문제가 아니라 오토스케일러/임대 튜닝 신호입니다.

: vllm:nixl_num_kv_expired_reqs 가 높으면 prefiller의 임대 기간(kv_lease_duration)이 네트워크나 워크로드에 비해 너무 짧다는 뜻입니다. --kv-transfer-config '{"kv_connector_extra_config": {"kv_lease_duration": <seconds>}}' 로 늘리세요.

예시 스크립트/코드

vLLM 저장소의 다음 예시 스크립트를 참고하세요:

더 알아보기 (Learn more)