4.1 KiB
Distributed Layerwise Offloading
Distributed layerwise offloading (DLO) extends block streaming to multi-device
deployments. With AllGather enabled, each rank stores roughly 1 / dp_size of
the host weights and reconstructs each layer at runtime. Without AllGather,
each rank streams its standard-loader rank-local weights independently.
See the DLO feature design for the implementation contract and compatibility matrix.
Execution model
DLO overlaps three operations with a fixed two-block device buffer:
Compute stream: [Layer N] [Layer N+1] [Layer N+2]
H2D stream: [H2D shard N+1] [H2D shard N+2]
AllGather: [AG N+1] [AG N+2]
Slots: slot 0: Layer N slot 1: Layer N+1
AllGather communicates only request-independent weight shards, so data- parallel ranks may process different requests concurrently.
Usage
# Four ranks with sharded host weights and AllGather
vllm serve /path/to/model --omni \
--enable-distributed-layerwise-offload \
--data-parallel-size 4
# Standard-loader rank-local weights, without DLO AllGather
vllm serve /path/to/model --omni \
--enable-distributed-layerwise-offload \
--data-parallel-size 4 \
--dlo-no-use-allgather
# Sequence parallel deployment
vllm serve /path/to/model --omni \
--enable-distributed-layerwise-offload \
--usp 4
from vllm_omni import Omni
omni = Omni(
model="/path/to/model",
enable_distributed_layerwise_offload=True,
dlo_use_allgather=True,
)
Flags
| Flag | Meaning | Default |
|---|---|---|
--enable-distributed-layerwise-offload |
Enable DLO | false |
--data-parallel-size N |
DP ranks and AllGather weight-sharding group | 1 |
--dlo-use-allgather |
Shard host weights and reconstruct with AllGather | true |
--dlo-no-use-allgather |
Keep standard-loader rank-local weights | false |
--dlo-resident-layers N |
Keep N leading main-DiT blocks on device; requires no-AllGather and model-declared resident paths | 0 |
mmap weight loading
The DLO plus AllGather path:
- saves non-persistent buffers such as RoPE frequencies;
- moves the normally created transformer to the meta device;
- loads checkpoint tensors as mmap views backed by the shared OS page cache;
- calls model-specific
post_load_weights()conversions; and - restores the saved non-persistent buffers.
This avoids one full checkpoint RSS copy per rank and does not require model-specific loading code.
Declarative topology
Models may declare an OffloadPlan instead of embedding offload logic:
from vllm_omni.diffusion.offloader import OffloadPlan
class MyPipeline(nn.Module):
_dit_modules = ["transformer"]
_offload_plan = OffloadPlan(
block_attrs={"transformer": ("blocks",)},
offload_submodules={"context_encoder": "layers"},
)
When no plan exists, discovery falls back to
_layerwise_offload_blocks_attrs and then heuristic attribute lookup.
Data-parallel concurrency
With data_parallel_size > 1 and AllGather enabled, the scheduler can process
up to dp_size requests per denoising step. Every concurrent request must set
the same explicit num_inference_steps; None is rejected because every rank
must enter each collective.
Limitations
- Online FP8 quantization is rejected with the DLO plus AllGather mmap path.
Use
--dlo-no-use-allgatheror disable online quantization. - Tensor parallel size greater than one is rejected in the mmap path because it bypasses TP-aware loader callbacks. The no-AllGather path retains the standard loader and remains experimental with TP.
- HSDP plus AllGather is rejected to avoid double sharding. HSDP without AllGather has limited end-to-end validation.
- Resident leading layers require
--dlo-no-use-allgatherand a modelOffloadPlanthat declares eligibleresident_dit_paths. - DP concurrency requires an explicit, identical inference-step count.
See the Cosmos3 DistOffload recipe for an end-to-end example.