功能
将 offloading connector 的后端模块化,消除硬件耦合。通过 Spec 注册机制,外部项目可以用 spec_module_path 动态加载自定义后端(如 llm-d-kv-cache 的 SharedStorageOffloadingSpec),同时复用 vLLM 已有的调度和 metrics 逻辑。
Spec 继承体系
OffloadingSpec (ABC)
├── @abstractmethod get_manager()
├── @abstractmethod get_handlers()
└── build_metric_definitions() → return {} (默认)
↓ 继承
CPUOffloadingSpec(OffloadingSpec)
├── get_manager() → 创建 CPUOffloadingManager
├── create_handlers() → 创建 CpuGpuOffloadingHandlers (torch.zeros CPU buffer)
└── build_metric_definitions() → stores_skipped (store_threshold >= 2 时)
↓ 继承
TieringOffloadingSpec(CPUOffloadingSpec)
├── get_manager() → 创建 TieringOffloadingManager (primary + secondary tiers)
├── create_handlers() → 创建带 worker_mmap 的 CpuGpuOffloadingHandlers
└── store_threshold >= 2 → raise ValueError (不支持)
OffloadingSpec (ABC) — 插件接口
| 方法 |
作用 |
build_metric_definitions() |
返回 {},子类 override 注册指标 |
__init__() |
解析 extra_config:offload_prompt_only、block_size_factor |
get_manager() |
@abstractmethod,返回 OffloadingManager |
get_handlers() |
@abstractmethod,yield GPU↔CPU handler pairs |
CPUOffloadingSpec — GPU ↔ CPU 缓存
| 方法 |
作用 |
__init__() |
计算 num_blocks、kv_bytes_per_offloaded_block |
get_manager() |
创建 CPUOffloadingManager(LRU 淘汰) |
create_handlers() |
创建 CpuGpuOffloadingHandlers,CPU buffer = torch.zeros() |
build_metric_definitions() |
条件注册 vllm:kv_offload_stores_skipped |
TieringOffloadingSpec — 多级级联缓存
| 方法 |
作用 |
__init__() |
额外解析 secondary_tier_configs |
get_manager() |
创建 SharedOffloadRegion → CPUPrimaryTier → SecondaryTiers → TieringOffloadingManager |
create_handlers() |
创建带 worker_mmap 的 CpuGpuOffloadingHandlers |
关键区别:TieringOffloadingSpec 继承自 CPUOffloadingSpec(不是 OffloadingSpec),所以继承了父类的 build_metric_definitions 和 get_handlers。
TieringOffloadingSpec.get_manager() 流程
get_manager():
1. SharedOffloadRegion(rank=None) # scheduler_mmap,拥有完整区域
2. CPUPrimaryTierOffloadingManager( # 绑定 mmap,LRU/ARC 淘汰
mmap_region=scheduler_mmap)
3. primary_kv_view = primary.get_kv_memoryview() # memoryview
4. for tier_config in secondary_tier_configs:
SecondaryTierFactory.create_secondary_tier(tier_config, primary_kv_view)
5. TieringOffloadingManager(primary_tier, secondary_tiers)
多级 Tier 操作
| 操作 |
涉及 tier |
行为 |
并发模式 |
| lookup |
primary → sec_0 → sec_1 → … |
短路查找,找到第一个 hit 就停 |
同步 |
| store |
primary → 所有 secondary |
广播写入,每个 tier 一份 |
异步 (submit_store) |
| load |
某个 secondary → primary |
按需 promotion,批量提交 |
异步 + on_schedule_end() |
Store 流程
prepare_store() → GPU → primary (共享内存)
complete_store() → 级联到所有 secondary tiers (异步写入磁盘/S3)
Lookup 流程
primary.lookup() → hit → True
→ miss → secondary_0.lookup() → hit → initiate_promotion() → None
→ miss → secondary_1.lookup() → ...
Load 流程
lookup() 命中 secondary → _initiate_promotion() → 加入 _pending_load_submissions
on_schedule_end() → _flush_pending_promotions() → secondary.submit_load() → 异步拉回
complete_load() → ref_cnt-- → 允许淘汰
SharedOffloadRegion
本质:多进程共享内存协调器(不是普通 buffer)。
物理载体
- 文件:
/dev/shm/vllm_offload_{instance_id}.mmap(tmpfs,在 RAM 中)
- 多个进程 mmap 同一文件 → 共享同一块物理 RAM
交错内存布局
Block 0: [ W0_16B | W1_16B | W2_16B ]
Block 1: [ W0_16B | W1_16B | W2_16B ]
Block 2: [ W0_16B | W1_16B | W2_16B ]
为什么交错:
- 无锁并发 — 每个 worker 只写自己的列,天然不冲突
- DMA 友好 — worker 拿到 strided tensor
(num_blocks, page_size), stride=(row_stride, 1),GPU 直接搬运
- Block 级淘汰 — “一行 = 一个 block”,secondary tier 直接
memoryview[block_id] 读写整行
scheduler_mmap vs worker_mmap
| |
scheduler_mmap |
worker_mmap |
| rank |
None |
GPU_ID (0,1,2...) |
| 访问范围 |
完整内存区域 |
只访问自己那列 |
| 用途 |
primary tier 管理 + secondary tier 导出 |
GPU ↔ CPU 数据传输 |
| API |
create_kv_memoryview() → 完整 memoryview |
create_next_view() → strided tensor |
vs IPC 效率对比
| |
IPC |
SharedOffloadRegion |
| CPU 拷贝 |
2 次 |
1 次 (GPU→内存) |
| 序列化/反序列化 |
需要 |
不需要 |
| 内存占用 |
2× (每个进程一份) |
1× (共享) |
| 延迟 |
~2.3ms |
~1ms |