2026-02-12 17:29:55 +08:00
# CPU Offloading for Diffusion Models
2026-01-12 16:11:18 +05:30
## Overview
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
vLLM-Omni provides two offloading strategies to reduce GPU memory usage for diffusion models:
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
1. **Model-level (Sequential) Offloading** : Mutual exclusion between DiT model and encoder - only one is on GPU at a time.
2. **Layerwise (Blockwise) Offloading** : Keeps only one transformer block on GPU at a time with compute-memory overlap.
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
Both strategies use pinned memory for faster CPU-GPU transfers. The strategies are **mutually exclusive** for now - if both are enabled, layerwise takes priority.
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
## Model-level (Sequential) Offloading
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
### How It Works
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
Model-level offloading implements mutual exclusion between DiT transformer and encoder modules using pre forward hooks:
2026-01-12 16:11:18 +05:30
2026-02-12 17:29:55 +08:00
- **When encoders run**: DiT transformer is offloaded to CPU
- **When DiT runs**: Encoders are offloaded to CPU
- **VAE**: Stays resident on GPU
2026-01-12 16:11:18 +05:30
2026-02-12 17:29:55 +08:00
Before each module's forward pass, the hook automatically moves it to GPU while offloading the other module group to CPU. Transfers use pinned memory for speed.
2026-01-12 16:11:18 +05:30
2026-02-12 17:29:55 +08:00
### Usage
2026-01-12 16:11:18 +05:30
2026-02-12 17:29:55 +08:00
**Python API:**
2026-01-12 16:11:18 +05:30
```python
from vllm_omni import Omni
2026-02-12 17:29:55 +08:00
m = Omni ( model = "Wan-AI/Wan2.2-T2V-A14B-Diffusers" , enable_cpu_offload = True )
2026-01-12 16:11:18 +05:30
```
2026-02-12 17:29:55 +08:00
**CLI:**
```bash
vllm-omni serve diffusion Wan-AI/Wan2.2-T2V-A14B-Diffusers --enable-cpu-offload
```
2026-01-12 16:11:18 +05:30
2026-01-30 17:35:09 +08:00
### Limitations
2026-02-12 17:29:55 +08:00
- Cold start latency increases
- Adds overhead from CPU-GPU transfers between encoder and denoising phases
- Support single GPU only for now
2026-01-30 17:35:09 +08:00
## Layerwise (Blockwise) Offloading
2026-02-12 17:29:55 +08:00
### How It Works
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
Layerwise offloading keeps only one transformer block on GPU at a time.
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
As each block completes, the next block is prefetched to GPU while the current block is freed. The pre and forward hooks utilized by layerwise offloading apply a separate CUDA stream (`copy_stream` ) to overlap weight transfer with computation, and retain flattened tensors in pinned CPU memory for block parameters re-materialization. Encoders, VAE, and non-block DiT modules (embeddings, norms) always stay on GPU.
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
**Execution Flow:**
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
| Block | Pre-forward Hook | Forward | Post-forward Hook |
|-------|------------------|---------|-------------------|
| block-0 | Prefetch block-1 (async) | Compute block-0 | Free block-0 |
| block-1 | Prefetch block-2 (async) | Compute block-1 | Free block-1 |
| ... | ... | ... | ... |
| block-(n-1) | **Prefetch block-0** (async) | Compute block-(n-1) | Free block-(n-1) |
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
Each transformer block has a `LayerwiseOffloadHook` that prefetches the next block before forward and frees the current block after forward.
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
Layerwise offloading is primarily recommended for large **video generation models** where the compute cost per block is high enough to effectively overlap with memory prefetch operations. For example, Wan2.2 T2V and I2V pipelines.
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
### Usage
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
**Python API:**
2026-01-30 17:35:09 +08:00
```python
from vllm_omni import Omni
2026-02-12 17:29:55 +08:00
# Text-to-video
m = Omni ( model = "Wan-AI/Wan2.2-T2V-A14B-Diffusers" , enable_layerwise_offload = True )
# Or image-to-video
m = Omni ( model = "Wan-AI/Wan2.2-I2V-A14B-Diffusers" , enable_layerwise_offload = True )
2026-01-30 17:35:09 +08:00
```
2026-02-12 17:29:55 +08:00
**CLI:**
```bash
# Text-to-video
vllm-omni serve diffusion Wan-AI/Wan2.2-T2V-A14B-Diffusers --enable-layerwise-offload
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
# Or image-to-video
vllm-omni serve diffusion Wan-AI/Wan2.2-I2V-A14B-Diffusers --enable-layerwise-offload
```
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
### To Support a Model
2026-01-30 17:35:09 +08:00
2026-02-12 17:29:55 +08:00
Models must define the blocks attribute name for layerwise offloading:
```python
class WanTransformer3DModel ( nn . Module ):
2026-04-06 11:49:35 +08:00
_layerwise_offload_blocks_attrs = [ "blocks" ] # Attribute names containing transformer blocks
2026-02-12 17:29:55 +08:00
def __init__ ( self ):
self . blocks = nn . ModuleList ([ ... ]) # Transformer blocks
```
2026-01-30 17:35:09 +08:00
2026-04-06 11:49:35 +08:00
For models with multiple block types:
```python
class Flux2Transformer2DModel ( nn . Module ):
_layerwise_offload_blocks_attrs = [ "transformer_blocks" , "single_transformer_blocks" ]
```
2026-01-30 17:35:09 +08:00
### Limitations
- Cold start latency increases because of
2026-02-12 17:29:55 +08:00
1) components are loaded to CPU first at the very first during initialization,
2026-01-30 17:35:09 +08:00
2) weight consolidation and pinning
2026-02-12 17:29:55 +08:00
- Performance depends on compute cost and H2D bandwidth as well
2026-01-30 17:35:09 +08:00
- Support single GPU only for now
2026-02-12 17:29:55 +08:00
### Implementation Notes
**Module Discovery**
The offloader automatically discovers pipeline components:
- **DiT modules**: `transformer` , `transformer_2` , `dit`
- **Encoders**: `text_encoder` , `text_encoder_2` , `text_encoder_3` , `image_encoder`
- **VAE**: `vae`
**Hook System**
Both strategies use vLLM-Omni's hook registry system (`HookRegistry` and `ModelHook` ) to register pre/post forward callbacks on modules, enabling automatic swapping without modifying model code.
**Backend Architecture**
```
OffloadBackend (base class)
├── ModelLevelOffloadBackend → uses SequentialOffloadHook
└── LayerWiseOffloadBackend → uses LayerwiseOffloadHook
```
Factory function `get_offload_backend()` selects the appropriate backend based on configuration.
## Supported Models
2026-04-08 09:55:09 +08:00
| Architecture | Example Models | DiT Class | Model-Level Offload | Layerwise Offload | Blocks Attrs (Layerwise specific) |
|--------------|----------------|-----------|---------------------|-------------------|-----------------------------------|
| LongCatImagePipeline | `meituan-longcat/LongCat-Image` | `LongCatImageTransformer2DModel` | - | ✓ | `"transformer_blocks"` , `"single_transformer_blocks"` |
| NextStep11Pipeline | `stepfun-ai/NextStep-1.1` | `NextStepModel` | - | ✓ | `"layers"` |
| OvisImagePipeline | `AIDC-AI/Ovis-Image-7B` | `OvisImageTransformer2DModel` | - | ✓ | `"transformer"` |
2026-02-12 17:29:55 +08:00
| QwenImagePipeline | `Qwen/Qwen-Image` | `QwenImageTransformer2DModel` | ✓ | ✓ | `"transformer_blocks"` |
2026-04-08 09:55:09 +08:00
| StableDiffusion3Pipeline | `stabilityai/stable-diffusion-3.5-medium` | `SD3Transformer2DModel` | - | ✓ | `"transformer_blocks"` |
| Wan22I2VPipeline | `Wan-AI/Wan2.2-I2V-A14B-Diffusers` | `WanTransformer3DModel` | ✓ | ✓ | `"blocks"` |
| Wan22Pipeline | `Wan-AI/Wan2.2-T2V-A14B-Diffusers` | `WanTransformer3DModel` | ✓ | ✓ | `"blocks"` |
2026-02-12 17:29:55 +08:00
**Notes:**
- Model-Level Offloading is expected to be supported by all common diffusion models (DiT and encoders) naturally
2026-04-06 11:49:35 +08:00
- Layerwise Offloading requires DiT class to define `_layerwise_offload_blocks_attrs` pointing to transformer blocks