Signed-off-by: yuanwu <yuan.wu@intel.com> Signed-off-by: Yuan Wu <yuan.wu@intel.com>
6.4 KiB
NixlConnector
When to Use
Multi-node or intra-node stage transfer over NIXL, which brokers RDMA/shared-memory transports through a single API. Useful when the deployment already standardises on NIXL for KV transfer, or when the target accelerator has no Mooncake/Mori backend -- NIXL reaches Intel XPU through UCX's Level Zero support.
Mechanism
Uses vLLM's NixlWrapper (vllm.distributed.nixl_utils) to register the producer's
tensors and let the consumer pull them with a NIXL READ.
- Data Plane: NIXL agent-to-agent
READ, GPU-to-GPU where the backend allows it. - Control Plane: a ZMQ ROUTER socket atomically claims the source allocation before
returning descriptors. Forwarded
put()metadata includes the generation and endpoint; the consumer claims that generation before submitting any READ.
Transfer metadata uses schema version 1. Tensor descriptors are grouped by NIXL
memory type (DRAM, VRAM, and so on), while each descriptor retains its global
tensor index so mixed CPU/accelerator payloads can be reconstructed in order.
Payloads are not restricted to tensors. A single tensor or a list of tensors is
transferred as-is; a nested structure has its tensor leaves extracted and shipped
alongside a msgpack-encoded skeleton; anything else is msgpack-encoded into one
uint8 tensor. Mapping and sequence structure is preserved. msgspec.Struct values,
including OmniPayloadStruct, are normalised to mappings so their tensor leaves use
the direct NIXL path rather than CPU object serialisation.
Each NIXL agent uses strict thread synchronization. A consumer performs one short metadata query per scheduler poll (10ms by default), which prevents an unavailable producer from blocking unrelated requests. The regular transfer-completion handshake keeps the configured transfer timeout.
Installation
CUDA hosts can install the published wheel:
pip install nixl
For Intel XPU, use docker/Dockerfile.xpu. Its upstream vLLM XPU base image
provides a matching torch-xpu, UCX with Level Zero support, and NIXL runtime.
Configuration
connectors:
nixl_connector:
name: NixlConnector
extra:
host: "auto"
zmq_port: 50061
backends: ["UCX"]
stages:
- stage_id: 0
output_connectors:
to_stage_1: nixl_connector
- stage_id: 1
input_connectors:
from_stage_0: nixl_connector
Parameters:
host: address the producer binds its handshake socket to ("auto"to detect).zmq_port: handshake port. If a producer omits it, an ephemeral port is opened for ownership claims and returned input()metadata. The value in the deploy YAML is a base port. Purpose, replica, rank, and producer-stage offsets are added centrally, so colocated connectors and tensor-parallel workers receive distinct endpoints without one config entry per rank.sender_host/sender_zmq_port: consumer-side override naming the producer's handshake endpoint. Only needed when the consumer cannot learn it from metadata. In replicated deployments, the producer endpoint is carried with each request and selected atget()time; it is not mutable connector-wide state. Explicit sender ports are preserved, not recomputed using the receiver replica. Intermediate NIXL stages retain their incoming receiver configuration and a separate outgoing bind configuration, so one worker can receive and publish.backends: NIXL backends to register memory with. Defaults to["UCX"].receive_device: forces where received tensors land. By default the consumer keeps the producer's device type but uses its own current device of that type.memory_type: overrides the NIXL memory type, otherwiseDRAMfor CPU tensors andVRAMfor accelerator tensors.lease_seconds: how long aput()payload stays registered while waiting to be read (default 3600). The consumer reports completion, so this only bounds payloads nobody has claimed. An internal reaper releases only unclaimed registrations.VLLM_OMNI_NIXL_LEASE_Soverrides it.transfer_timeout_s: how long aget()waits for itsREADto complete (default 300). NIXL 1.3 has no transfer cancellation API, so a timed-out transfer's buffers and registrations remain owned by the connector until NIXL reports a terminal state;close()waits for that state before releasing them.VLLM_OMNI_NIXL_XFER_TIMEOUT_Soverrides it.
Source ownership and failure limits
Claims and expiry use the same lock. Completion identifies both a payload generation and a unique READ claim; duplicate or stale ACKs cannot release a different reader or replacement payload. Replacing a claimed key is rejected. Terminal errors also release claims; timeout, unknown status, and active sibling transfers retain the complete destination bundle and source claim until terminal. Zero-element tensors retain their shape/dtype/skeleton positions but never create DMA descriptors or registrations.
A lost metadata response, lost completion ACK, or abandoned consumer can retain a
claim indefinitely. NIXL 1.3 cannot prove remote cancellation, so neither TTL nor
cleanup() frees those allocations. Producer close() rejects new work and
retains its agent, listener and claimed allocations; a later close() finishes
teardown after claims drain. Permanently abandoned claims remain until process
exit. This favors memory safety over bounded shutdown/memory usage. Only trusted
peers may access this unauthenticated control plane. Both endpoints must use the
claim-aware protocol; rolling compatibility with older GET_META clients is not
provided. Legacy externally-owned metadata without a generation is accepted only
under the caller's lifetime guarantee, not managed as a leased allocation here.
Validation
The native CUDA smoke test requires NIXL and at least two visible CUDA devices:
UCX_RCACHE_MAX_UNRELEASED=1024 pytest -o addopts='' -q -s \
tests/distributed/omni_connectors/test_nixl_connector_native.py
It starts independent producer and consumer processes, loads the real UCX backend,
performs the ZMQ GET_META handshake and a native NIXL READ from GPU 0 to GPU 1,
checks mixed CPU/GPU tensor leaves from an OmniPayloadStruct, sends XFER_DONE,
and verifies that producer registrations are released. This validates same-host,
cross-GPU operation. Inter-node UCX transport is supported by the design but was not
validated by this test.
For more details, refer to the NIXL repository.