vllm.distributed.weight_transfer
¶
Weight transfer engines for syncing model weights from trainers to inference workers.
Modules:
-
base–Base class for weight transfer engines.
-
clients–Built-in
VLLMWeightSyncClientimplementations. -
factory–Factory for weight transfer engines with lazy loading.
-
ipc_engine–IPC-based weight transfer engine using CUDA IPC for communication.
-
m2n_common–Shared helpers for the NCCL M2N (
nccl_m2n) weight transfer backend. -
m2n_engine–Inference-side weight transfer engine built on NCCL M2N (
nccl_m2n). -
m2n_layout–Destination-layout resolution for the NCCL M2N weight transfer backend.
-
m2n_trainer–Trainer-side weight transfer engine for the NCCL M2N backend.
-
modelexpress_engine–Re-export the weight-transfer backend maintained by ModelExpress.
-
nccl_common–Shared NCCL initialization helpers for weight transfer engines.
-
nccl_engine–NCCL-based (dense) weight transfer engine.
-
packed_tensor–Packed tensor utilities for efficient weight transfer.
-
sharded_rdt_common–Shared pieces of the sharded-RDT backend: the op-chain allowlist, buffer
-
sharded_rdt_engine–Sharded Ray Direct Transport (RDT) weight transfer engine (consumer side).
-
sharded_rdt_fake–Op-chain recording for the sharded-RDT backend.
-
sharded_rdt_trainer–Trainer-side engine for the sharded-RDT (pull-based NIXL) backend.
-
sparse_nccl_engine–Sparse NCCL weight transfer engine.
Classes:
-
HTTPVLLMWeightSyncClient–Talks to a vLLM server over the RLHF HTTP routes.
-
ModuleSource–WeightSourceovermodule.named_parameters(): plain, FSDP or DTensor. -
ParamMeta–One output parameter: its name, wire dtype and full (HF) shape, plus
-
RayVLLMWeightSyncClient–Talks to one or more vLLM
AsyncLLM/LLMRay actors. -
Replicate–Every coordinate along this mesh axis holds the whole extent.
-
Shard–This mesh axis splits tensor dim
dimthe waytorch.chunkdoes. -
TrainerWeightTransferEngine–Trainer-side weight transfer engine.
-
VLLMWeightSyncClient–Trainer-side stub for the inference engine's weight-sync control plane.
-
WeightSource–The trainer's weights, as metadata plus one or two iteration modes.
-
WeightTransferEngine–Base class for weight transfer engines that handle transport of model weights
-
WeightTransferEngineFactory–Factory for creating weight transfer engines with lazy loading.
-
WeightTransferTrainerFactory–Factory for creating trainer-side weight transfer engines.
HTTPVLLMWeightSyncClient
¶
Talks to a vLLM server over the RLHF HTTP routes.
Mirrors vllm/entrypoints/rl/online/api_router.py:
/init_weight_transfer_engine, /start_weight_update, /update_weights,
/finish_weight_update, /shutdown_weight_transfer_engine.
Source code in vllm/distributed/weight_transfer/clients.py
ModuleSource
¶
Bases: WeightSource
WeightSource over module.named_parameters(): plain, FSDP or DTensor.
A plain tensor is owned by every rank. A DTensor is owned by the global
ranks of its device mesh, with the mesh's shape and the DTensor's
placements. iter_full gathers each DTensor with full_tensor() (a
collective among its owners); iter_local yields to_local(). A DTensor
whose placements are not plain Shard / Replicate is declared replicated,
and iter_local gathers it. metadata reads global shapes, never
gathers, and is cached on first read, so shard the module first.
The mesh ranks are taken as trainer ranks, so the default process group's
ranks must be the TrainerInitInfo.ranks.
Source code in vllm/distributed/weight_transfer/base.py
ParamMeta
dataclass
¶
One output parameter: its name, wire dtype and full (HF) shape, plus which trainer ranks own it and how it is laid out across them.
Metadata is identical on every trainer rank, ownership included, so every rank and every engine derives the same plan from it without a runtime exchange.
Attributes:
-
owners(tuple[int, ...] | None) –Global trainer ranks (
TrainerInitInfo.rank) that own this parameter, in mesh order.Nonemeans every rank. -
mesh_shape(tuple[int, ...] | None) –Row-major shape of the mesh over
owners. Defaults to(len(owners),). -
placements(tuple[Placement, ...] | None) –One
ReplicateorShardper mesh axis, describing whatWeightSource.iter_localyields on each owner;Shardsplits the waytorch.chunkdoes, outer mesh axis first when two axes shard one dim.Nonemeans replicated; a source withoutiter_localleaves it unused.
Source code in vllm/distributed/weight_transfer/base.py
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | |
RayVLLMWeightSyncClient
¶
Talks to one or more vLLM AsyncLLM/LLM Ray actors.
Each call fans out to every handle and blocks on all of them, so a multi-actor (e.g. multi-DP) deployment is driven as one unit.
Source code in vllm/distributed/weight_transfer/clients.py
Replicate
dataclass
¶
Shard
dataclass
¶
TrainerWeightTransferEngine
¶
Bases: ABC, Generic[TTrainerInitInfo]
Trainer-side weight transfer engine.
Symmetric to WeightTransferEngine but lives in the training process.
Constructed via the trainer_init factory classmethod; carries any
backend-specific state (NCCL communicators, IPC device info, transfer
plans) on self. Full-resync backends (NCCL, IPC) take a WeightSource at
trainer_init and replay it each round via the no-argument
send_weights(). Backends that push per-round deltas instead (e.g. sparse
patches) leave source as None and take their payload as a send_weights
argument.
Unlike the worker engine, the trainer side does not take a
WeightTransferConfig: the backend is selected from the init info's
backend ClassVar (so callers pass only the init info), and the static
wire params (packed, buffer sizes) ride the backend-specific
TrainerInitInfo, which the sender also propagates to the worker at the init
handshake.
Multi-rank trainers: trainer_init and send_weights are
called on every trainer rank. Rank 0 is the sender, resolved once at
trainer_init into is_sender. Non-sender ranks still run every
collective (iterating the source, metadata export, IPC handle all-gather) so
the group stays aligned, but each engine explicitly guards the control-plane
RPCs and the transmit on self.is_sender, so only the sender touches the
client.
Subclasses should define
init_info_cls: Type of backend-specific trainer init info
Methods:
-
send_weights–Push weights to inference workers and drive the full update round
-
shutdown–Tear down communicators / process groups. Default no-op.
-
trainer_init–Rendezvous with the inference side and return a ready instance.
Source code in vllm/distributed/weight_transfer/base.py
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 | |
send_weights()
abstractmethod
¶
Push weights to inference workers and drive the full update round
trip: start_weight_update, update_weights (run concurrently with the
trainer-side broadcast when the backend requires it), then
finish_weight_update. Called on every trainer rank.
Source code in vllm/distributed/weight_transfer/base.py
shutdown()
¶
trainer_init(init_info, *, client, source=None)
abstractmethod
classmethod
¶
Rendezvous with the inference side and return a ready instance.
Called on every trainer rank. The sender drives the full handshake via
client (build the worker-side init info, call
client.init_weight_transfer_engine, open the trainer-side endpoint);
non-sender ranks skip the rendezvous and the RPC.
Source code in vllm/distributed/weight_transfer/base.py
VLLMWeightSyncClient
¶
Bases: Protocol
Trainer-side stub for the inference engine's weight-sync control plane.
Mirrors the weight-sync methods that the inference engine exposes
(EngineClient / the HTTP RLHF routes / Ray actors). A
TrainerWeightTransferEngine drives the full handshake through this
protocol so trainer code never has to know the transport.
All methods are synchronous and accept plain dicts (matching what the
inference side already accepts). Concurrency that some backends need
(e.g. NCCL must run update_weights concurrently with the trainer-side
broadcast) is the engine's responsibility, not the client's, so the
protocol stays a flat four-method surface that any wrapper can implement.
The protocol is structural (PEP 544), so user implementations need only define these four methods — no import or subclassing required.
Source code in vllm/distributed/weight_transfer/base.py
WeightSource
¶
Bases: ABC
The trainer's weights, as metadata plus one or two iteration modes.
metadatadeclares every parameter of the whole model, on every rank: name, wire dtype, full shape, and which ranks own it in what layout (seeParamMeta). It transfers nothing.iter_full()yields each owned parameter as a full tensor.iter_local()yields each owned parameter as this rank's piece, shaped byParamMeta.placements.
A source implements one mode or both, and nothing is derived from one mode
to the other. Each engine consumes the mode it needs: broadcast, IPC and
RDT consume iter_full, NCCL M2N consumes iter_local.
Both modes yield (name, tensor) pairs: exactly owned_names(rank), in
metadata order. Either may run collectives among a parameter's
owners (an FSDP all-gather, one per layer if it likes); every owner
iterates in metadata order, so the collectives line up. Work is enqueued
on the caller's current stream. Each call starts a fresh pass.
Methods:
-
iter_full–Yield the full tensor of each name this rank owns.
-
iter_local–Yield this rank's piece of each name it owns.
-
owned_names–The names
rankowns, in metadata order: exactly what it iterates.
Attributes:
Source code in vllm/distributed/weight_transfer/base.py
metadata
abstractmethod
property
¶
Every parameter, declared without transferring anything.
Implement it as a functools.cached_property. Must be identical on
every trainer rank, including ownership: engines plan from it without
exchanging it.
iter_full()
¶
Yield the full tensor of each name this rank owns.
iter_local()
¶
Yield this rank's piece of each name it owns.
owned_names(rank)
¶
The names rank owns, in metadata order: exactly what it iterates.
WeightTransferEngine
¶
Bases: ABC, Generic[TInitInfo, TUpdateInfo]
Base class for weight transfer engines that handle transport of model weights from a trainer to inference workers.
This abstraction separates weight transfer transport logic from the worker implementation, allowing different backends (NCCL, CUDA IPC, RDMA[TODO]) to be plugged in.
Each engine owns its full weight-update lifecycle: start_weight_update,
update_weights, and finish_weight_update. Layerwise reloading (used by
checkpoint-format engines) is opted into per engine by running it inside
start_weight_update/finish_weight_update. Engines that apply weights in
place (e.g. sparse patches) leave those methods as no-ops.
Subclasses should define
init_info_cls: Type of backend-specific initialization info update_info_cls: Type of backend-specific update info
Methods:
-
__init__–Initialize the weight transfer engine.
-
drain_pending–Block until every deferred update has been applied to the model.
-
finish_weight_update–Finalize the current weight update.
-
init_transfer_engine–Initialize the weight transfer mechanism.
-
parse_init_info–Construct typed init info from dict with validation.
-
parse_update_info–Construct typed update info from dict with validation.
-
receive_weights–Receive weights from the trainer and load them into the model.
-
reset_weight_update_target–Restore weight updates to the engine's default target model.
-
set_weight_update_target–Set the model that will receive the active weight update.
-
shutdown–Release transfer resources without shutting down the inference worker.
-
start_weight_update–Prepare the engine for a new weight update.
-
update_weights–Receive one weight update chunk and load it into the model.
Attributes:
-
defers_processing(bool) –Whether
update_weightsreturns before the weights are on the device.
Source code in vllm/distributed/weight_transfer/base.py
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 | |
defers_processing = False
class-attribute
instance-attribute
¶
Whether update_weights returns before the weights are on the device.
An engine that pipelines its GPU post-processing onto background threads
cannot let update_weights synchronize the device — that would block on those
threads and serialize the pipeline. Such an engine sets this True, omits the
per-update sync, and guarantees completion in finish_weight_update instead.
Callers that go through finish_weight_update need do nothing: the engine
drains there. A caller that instead drives the tail itself — running its own
finalize_layerwise_reload, say — must read this flag and call
drain_pending() first, because with it set a returned update_weights means
"queued", not "applied".
__init__(config, vllm_config, device, model)
¶
Initialize the weight transfer engine.
Parameters:
-
(config¶WeightTransferConfig) –The configuration for the weight transfer engine
-
(vllm_config¶VllmConfig) –The full vLLM config (provides parallel/model config)
-
(device¶device) –The device this worker's model lives on
-
(model¶Module) –The local model instance which will receive the weights
Source code in vllm/distributed/weight_transfer/base.py
drain_pending()
¶
Block until every deferred update has been applied to the model.
The companion to defers_processing: a caller that has taken over the
update tail calls this to re-establish the guarantee that
finish_weight_update would otherwise have given it. Idempotent, and a
no-op by default — an engine that processes synchronously has nothing to
drain, so this is always safe to call.
Source code in vllm/distributed/weight_transfer/base.py
finish_weight_update()
abstractmethod
¶
Finalize the current weight update.
Checkpoint-format engines finalize layerwise reloading here; engines that apply weights in place leave this as a no-op.
Source code in vllm/distributed/weight_transfer/base.py
init_transfer_engine(init_info)
abstractmethod
¶
Initialize the weight transfer mechanism. This is called once at the beginning of training.
Parameters:
-
(init_info¶TInitInfo) –Backend-specific initialization info
Source code in vllm/distributed/weight_transfer/base.py
parse_init_info(init_dict)
¶
Construct typed init info from dict with validation.
Parameters:
Returns:
-
TInitInfo–Typed backend-specific init info dataclass
Raises:
-
ValueError–If init_dict is invalid for this backend
Source code in vllm/distributed/weight_transfer/base.py
parse_update_info(update_dict)
¶
Construct typed update info from dict with validation.
Parameters:
Returns:
-
TUpdateInfo–Typed backend-specific update info dataclass
Raises:
-
ValueError–If update_dict is invalid for this backend
Source code in vllm/distributed/weight_transfer/base.py
receive_weights(update_info)
abstractmethod
¶
Receive weights from the trainer and load them into the model.
Parameters:
-
(update_info¶TUpdateInfo) –Backend-specific update info containing parameter metadata and any backend-specific data
Source code in vllm/distributed/weight_transfer/base.py
reset_weight_update_target()
¶
Restore weight updates to the engine's default target model.
set_weight_update_target(model, model_config)
¶
Set the model that will receive the active weight update.
shutdown()
abstractmethod
¶
start_weight_update()
abstractmethod
¶
Prepare the engine for a new weight update.
Engines that receive weights in checkpoint format initialize layerwise reloading here, else this is typically a no-op. See: https://docs.vllm.ai/en/latest/training/layerwise/ for more details.
Source code in vllm/distributed/weight_transfer/base.py
update_weights(update_info)
¶
Receive one weight update chunk and load it into the model.
Parameters:
Source code in vllm/distributed/weight_transfer/base.py
WeightTransferEngineFactory
¶
Factory for creating weight transfer engines with lazy loading.
This factory implements a registry pattern that supports: - Lazy loading: Engine modules are only imported when actually needed - Extensibility: Custom engines can be registered at runtime - Centralized registration: All built-in engines registered in one place
Methods:
-
create_engine–Create a weight transfer engine instance.
-
register_engine–Register an engine with lazy-loading or direct class reference.
Source code in vllm/distributed/weight_transfer/factory.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
create_engine(config, vllm_config, device, model)
classmethod
¶
Create a weight transfer engine instance.
Parameters:
-
(config¶WeightTransferConfig) –Weight transfer configuration containing the backend name
-
(vllm_config¶VllmConfig) –The full vLLM config (provides parallel/model config)
-
(device¶device) –The device this worker's model lives on
-
(model¶Module) –The local model instance which will receive the weights
Returns:
-
WeightTransferEngine–An initialized weight transfer engine instance
Raises:
-
ValueError–If the backend is not registered
Source code in vllm/distributed/weight_transfer/factory.py
register_engine(name, module_path_or_cls, class_name=None)
classmethod
¶
Register an engine with lazy-loading or direct class reference.
Supports two calling conventions: 1. Lazy loading: register_engine(name, module_path, class_name) 2. Direct class: register_engine(name, engine_cls)
Parameters:
-
(name¶str) –The name to register the engine under (e.g., "nccl")
-
(module_path_or_cls¶str | type[WeightTransferEngine]) –Either a module path string for lazy loading, or the engine class directly
-
(class_name¶str | None, default:None) –Name of the engine class (required if module_path is string)
Raises:
-
ValueError–If an engine with the same name is already registered
Source code in vllm/distributed/weight_transfer/factory.py
WeightTransferTrainerFactory
¶
Factory for creating trainer-side weight transfer engines.
Parallel to WeightTransferEngineFactory, with its own lazy-import
registry. The trainer-side and worker-side registries are kept separate:
they share backend names by convention, but the trainer process never
instantiates a worker engine and vice versa, so unifying them would only
couple the import graphs.
Methods:
-
register_engine–Register a trainer engine. Same conventions as
-
trainer_init–Build and rendezvous a ready-to-send trainer engine.
Source code in vllm/distributed/weight_transfer/factory.py
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | |
register_engine(name, module_path_or_cls, class_name=None)
classmethod
¶
Register a trainer engine. Same conventions as
WeightTransferEngineFactory.register_engine.
Source code in vllm/distributed/weight_transfer/factory.py
trainer_init(init_info, *, client, source=None)
classmethod
¶
Build and rendezvous a ready-to-send trainer engine.
Called on every trainer rank (multi-rank trainers construct on all
ranks; the sender is resolved inside the engine's trainer_init).
The trainer side takes no WeightTransferConfig and no separate
backend argument: the backend is read from init_info.backend (a
ClassVar on each TrainerInitInfo subclass), and the static wire
params ride init_info.
Parameters:
-
(init_info¶TrainerInitInfo) –Backend-specific trainer init info. Its
backendselects the engine; it also carries the wire params (e.g.packed). -
(client¶VLLMWeightSyncClient) –Inference-side control-plane client.
-
(source¶WeightSource | None, default:None) –WeightSourceof(name, tensor)pairs to send each round, for full-resync backends (NCCL, IPC). Sparse backend omits it and passes its per-round payload tosend_weights.
Raises:
-
ValueError–If
init_info.backendis not registered.