◆ Source Reading · File № 003 A chart of 633,079 lines VLLM-001 / 2026 ◆

vLLM.

PagedAttention turned KV cache into virtual memory. Then v1 turned the engine itself into a process. A reading of vLLM's reinvention of inference, in seven plates.

Source
633,079loc · py
v1 Reborn
2024complete rewrite
Attn backends
20incl. AITER
CUDA / HIP src
csrc/extensive
gpu_model_runner
7,185lines · 1 file
Reading time
~6hthree sessions

§ 00 · PrologueThe territory charted.

vLLM 不是单纯的 inference engine — 它发明了"PagedAttention"这个抽象。把 KV cache 像虚拟内存一样分页管理,让吞吐量和拼批策略解耦于物理 GPU 内存碎片。这是它从 2023 年发布到 2026 年仍然是事实标准的根本原因。这次精读关注它 2024 年完成的 v1 重构 — 把原本的单体引擎拆成可插拔的 EngineCore + Worker,并提供进程内 / 独立进程 / Ray actor 三种部署模式。

跟 SGLang 的对比是这份文档的潜流。SGLang 用 RadixCache 在请求间共享 prefix;vLLM 用 BlockPool 在物理内存里共享 block。两条路径走到了相似的终点(prefix caching),但底层的抽象层级不同 — 这造就了两个系统在多轮对话、结构化生成、多模态扩展上的不同表现。

7,185
gpu_model_runner
2,234
v1/scheduler
2,161
v1/engine/core
1,969
flashinfer backend
1,471
rocm_aiter_fa
1,236
flash_attn
1,107
async_llm
541
kv_cache_manager
509
block_pool
20
attn backends
3
deploy modes
v1
architecture
Plate I — Two eras of vLLM v0 monolith versus v1 dispatched architectural
v0 — monolith until 2024 · single process owns everything LLMEngine single process holds it all Scheduler BlockManager (KV) Worker.execute_model() Model.forward() Detokenize → output CPU 调度 ↔ GPU 执行 严格串行 — GPU idle 等 CPU → rewrite, 2024 → v1 — dispatched EngineCore + Worker · IPC over ZMQ AsyncLLM user-facing async client ZMQ EngineCore core.py · 2161 lines Scheduler KVCacheManager 3 modes: Proc · Actor · Inline IPC GPU Worker(s) — N× gpu_worker.py GpuModelRunner · 7185 lines forward, attn backend dispatch, KV ops ★ CPU & GPU overlap — async by design 每 GPU step: ~1 IPC round-trip Both still exist in the codebase. v1 is default since v0.6; v0 marked legacy.
v0 把所有事在一个 Python 进程里串行做。v1 把调度模型执行拆成 EngineCore + Worker — 它们之间用 ZMQ / IPC 通信,CPU 调度天然 overlap 在 GPU forward 之上。这是 vLLM 2024 年最大的工程转向,也是它现在能跟 SGLang 在吞吐量上拉近差距的关键。

§ M0 · 25 minThe repo, at first sight.

vLLM 是个 monorepo — 顶层就有 vllm/(Python 包)+ csrc/(C++/CUDA/HIP 源码)+ cmake/(构建系统)+ tests/ + benchmarks/ + docs/。没有像 SGLang 那样把 kernel 拆成独立 wheel — vLLM 的策略是"一个 wheel 内置所有 platform 的 CUDA/HIP 二进制"。

vllm/ 主包里有几个值得立刻定位的 file:

File / DirRole
vllm/v1/★ 2024 重构后的新架构 — 整个内核都在这
vllm/engine/老 v0 入口(llm_engine.py · async_llm_engine.py · arg_utils.py)
vllm/_aiter_ops.pyAMD AITER 自定义算子包装
vllm/_custom_ops.py通用 C++ ext 算子包装(量化、norm、rotary etc.)
vllm/_xpu_ops.pyIntel XPU 算子
vllm/attention/老 v0 attention 框架(v1 在 v1/attention/)
vllm/model_executor/model 定义 + 加载(Llama / DeepSeek / Kimi / ...)
vllm/distributed/TP/PP/DP 通信 + KV connector(NIXL · offloading)
vllm/compilation/torch.compile 集成 + custom passes
vllm/platforms/CUDA / ROCm / TPU / XPU / CPU 平台抽象
vllm/kernels/纯 Python kernel 封装
vllm/entrypoints/OpenAI 兼容 API server + offline LLM 类
csrc/extensive C++/CUDA/HIP 源码

vllm/v1/ 进一步切分:

v1 subdirWhat
v1/engine/EngineCore(core.py 2161 行)· AsyncLLM · LLMEngine
v1/core/KVCacheManager · BlockPool · sched/Scheduler
v1/worker/GpuModelRunner(7185 行!)· CPU/TPU/XPU runner
v1/attention/20 个 attention backend(含 3 个 ROCm)
v1/kv_offload/★ KV cache offload 到 CPU / disk / NIXL(disagg serving)
v1/spec_decode/投机解码
v1/structured_output/JSON / regex 约束
v1/sample/采样(top_k / top_p / typical)
观察 · ARCHITECTURE INVARIANT

vLLM 把"什么调度(Scheduler · KVCacheManager · 在 EngineCore 里)"和"怎么执行(Worker · ModelRunner · 在独立进程或 Ray actor 里)"完全分开。这是它跟 SGLang 最显眼的设计差异 — SGLang 是每个 TP rank 都是一个完整 scheduler(N 个 scheduler 进程),vLLM 是一个 scheduler 协调 N 个 worker

vLLM 路径的好处:scheduler 状态单点权威,KVCacheManager 不用同步;代价:scheduler 是单点瓶颈,必须做得很快(这也是为什么有 7185 行的 gpu_model_runner,把工作尽量推到 worker 端做)。

§ M1 / M2 · 50 minEngineCore — three lives.

vllm/v1/engine/core.py(2161 行)是 vLLM v1 的心脏。它定义了一个清晰的继承体系,让同一个 EngineCore 可以以三种部署形态运行

class EngineCore:                            # line 91  · 基类,纯逻辑
    """Scheduler + KVCacheManager + Workers · 同步接口"""

class EngineCoreProc(EngineCore):            # line 810 · 独立进程
    """Subprocess 形态 · 与 AsyncLLM 通过 ZMQ 通信"""

class DPEngineCoreProc(EngineCoreProc):      # line 1626 · 数据并行
    """DP 拓扑下 N 个 EngineCoreProc 协作"""

class EngineCoreActorMixin:                  # line 1985 · Ray actor 行为
class EngineCoreActor(EngineCoreActorMixin, EngineCoreProc):  # line 2133
class DPMoEEngineCoreActor(EngineCoreActorMixin, DPEngineCoreProc):  # line 2110

这意味着用户可以选 3 种部署:

DeploymentClassWhen
In-process (sync)EngineCorePython 脚本里 LLM(...) 离线推理
Subprocess (async)EngineCoreProcOpenAI API server 默认
Ray ActorEngineCoreActor多机多 GPU 部署

三种部署共享同一份核心逻辑 — 这是 OO 多态在系统工程里的漂亮应用。

AsyncLLM — 异步客户端

vllm/v1/engine/async_llm.py(1107 行)是 OpenAI-compatible server 用的高级入口。它做的事:

  1. fork 一个 EngineCoreProc 子进程
  2. 建立 ZMQ socket(PUSH/PULL + PUB/SUB 混用)
  3. 提供 async def generate(prompt) async 生成器接口
  4. 每次拿到 EngineCore 的一批 outputs,把它们 demux 给等待的 async 请求

跟 SGLang 的 TokenizerManager 类似,但 vLLM 把 tokenizer / detokenizer 都合在 EngineCore 进程里(不是单独进程)— 这是 vLLM 整体进程数少的原因。

Plate II — One scheduler, N workers EngineCore / Worker IPC topology deployment
Process · Client AsyncLLM v1/engine/async_llm.py 1,107 lines tokenize async def generate() demux outputs to coroutines ZMQ requests outputs Process · EngineCoreProc (subprocess or actor) EngineCore v1/engine/core.py · 2,161 lines Scheduler 2,234 KVCacheManager 541 BlockPool 509 Detokenize in-proc EngineCoreBusyLoop · step / step / step Schedule t+1 ⇄ collect output t SchedulerOutput (IPC / shm) ModelRunnerOutput Process(es) · Worker(s) — N× GpuWorker v1/worker/gpu_worker.py GpuModelRunner gpu_model_runner.py · 7,185 lines vLLM's largest single file model.forward attn backend KV cache write sampling CUDA Graph captured per shape bucket
一个 EngineCore + N 个 Worker。Scheduler 在 EngineCore 这边 — 它知道全局所有请求的状态、KV cache 占用、block 分配。Worker 只负责"接收一批 schedule,跑 forward,输出 token"。这种"单 scheduler 多 worker"是 vLLM 路径;SGLang 是"N 个 scheduler,各管自己的 rank"。两种都能 work,但调试体验和扩展方向不同。

§ M5 · 50 minPagedAttentionvirtual memory for KV.

这是 vLLM 的原创贡献。把整个 KV cache 物理内存切成定长 block(默认 16 token 一个 block),用一个"虚拟 → 物理"映射表(block table)让每个 sequence 看到的是逻辑连续的 KV,但物理上可以散布在内存任何位置。

v1 里的实现拆成三个类:

ClassFile / LineRole
BlockPoolv1/core/block_pool.py:130物理 block 池 — 哪些 block 空闲 / 被引用
BlockHashToBlockMapv1/core/block_pool.py:34★ block hash → block id — 这是 prefix caching 的核心
KVCacheBlocksv1/core/kv_cache_manager.py:22一个请求拥有的 block 集合
KVCacheManagerv1/core/kv_cache_manager.py:106scheduler 用的 high-level API
KVCacheCoordinatorv1/core/kv_cache_coordinator.py多种 cache(attn / mamba)的协调

Prefix caching — vLLM 的方式

跟 SGLang 的 RadixCache(树形)不同,vLLM 用哈希 + 不可变 block实现 prefix caching:

def compute_block_hash(tokens):
    # 一个 block 的 hash 是它自己的 tokens + 父 block 的 hash
    return hash((parent_block_hash, tuple(tokens)))

# 当新请求来时:
for i, block_tokens in enumerate(tokenize(prompt).blocks):
    h = compute_block_hash(block_tokens)
    if h in block_hash_to_block_map:
        # cache hit — 直接复用物理 block
        reuse(block_hash_to_block_map[h])
    else:
        # cache miss — allocate 新 block,记录 hash
        new_block = block_pool.allocate()
        new_block.hash = h
        block_hash_to_block_map[h] = new_block

关键差异:block 的 hash 包含父 block 的 hash — 这让 hash 隐含了"我前面所有 token 的精确历史"。两个请求只有当 prefix 完全一致时,它们的 block hash 才会一样。

★ 设计对比 · TREE vs HASH

SGLang RadixCache(树):节点显式持有 token 序列,match_prefix 沿树查最长匹配。优点:能匹配任意长度的部分 prefix,分裂粒度细。缺点:树维护成本高,需要 ref_count + LRU。

vLLM BlockPool(hash):固定 16-token block,每个 block 一个 hash。优点:实现极简,lookup O(1),整 block 复用对 attention kernel 友好。缺点:粒度粗 — prefix 必须是 16 的倍数才能 cache hit。

实际效果:在长 prompt + 多轮对话场景,两者差距很小(因为 prefix 一致性通常是 hundreds-of-tokens 级别);但 SGLang 在短 prompt 部分共享场景下更灵活。

Plate III — PagedAttention, dissected virtual layout vs. physical pool memory
Two requests share "You are helpful" · only the tail diverges Request A — logical layout block 0You,are,a,helpful block 1asst.User asks: block 2How to print block 3hi? Answer: request_a.block_table = [7, 12, 3, 9] Request B — logical layout block 0You,are,a,helpful block 1asst.User asks: block 2What is 2+2? block 3. Reply: 4. request_b.block_table = [7, 12, 5, 11] BlockPool — physical KV memory (256 blocks) block 7 · "You,are,a,helpful" · ref=2 (shared!) block 12 · "asst.User asks:" · ref=2 (shared!) block 3 · "How to print" · ref=1 (A only) block 5 · "What is 2+2?" · ref=1 (B only) block 9 · "hi? Answer:" · ref=1 block 11 · ". Reply: 4." · ref=1 ★ Two requests share blocks 7 + 12 — 32 tokens × 2 layers × hidden_dim × 2 (K+V) bytes saved. Hash chain ensures sharing is safe even with mid-prompt divergence.
Request A 和 B 各看到 4 个逻辑 block。block_table 把它们映射到物理 BlockPool 里的 block id。Block 7 和 12 被两个请求共享(ref_count=2)— 这就是 prefix caching 在 vLLM 里的实现。当 ref_count 归零,block 回到 free pool 可被新请求用。整个机制类似操作系统页表 + 写时复制(COW),所以叫"PagedAttention"。

§ M4 · 40 minThe Scheduler — budget keeper.

vllm/v1/core/sched/scheduler.py 是 2234 行的单类。Scheduler(SchedulerInterface) 在 line 62。它的核心数据结构出乎意料地简单:

class Scheduler(SchedulerInterface):
    def __init__(self, ...):
        self.waiting = create_request_queue(self.policy)  # 等待 prefill 的请求
        self.running: list[Request] = []                  # 正在 generation 的请求
        # + KVCacheManager, max_num_running_reqs, token_budget, etc.

schedule() 方法(line 310)是每个 step 调用一次的核心。它做两轮调度决策

  1. Phase A — running 请求继续 decode(line 347-462)
    遍历 self.running,给每个请求 1 个 decode token 的预算。如果总 token budget 用完 / KV cache 不够,preempt 最低优先级的请求(line 442:self.running.remove(preempted_req))。
  2. Phase B — waiting 请求 admit + prefill(line 529-765)
    self.waiting 拉新请求,尝试 chunked prefill — 一次 step 不跑完整个 prompt,分多个 chunk 边 prefill 边和 decode 混跑。

这种"Phase A + Phase B 在同一 step 里混跑"是 vLLM continuous batching 的精髓。"continuous" 不是"不停跑",而是"prefill 和 decode 在 batch 维度共存"。

Preemption — 当资源不够

line 910 的 _preempt_request

def _preempt_request(self, request, timestamp):
    # 把所有 KV blocks 还回 BlockPool (但保留 hash → 后续可能复用)
    self.kv_cache_manager.free(request)
    # 状态变 WAITING,重新插到 waiting 队列前部
    request.status = RequestStatus.WAITING
    self.waiting.prepend_request(request)

Preempted 请求会丢失它的 KV cache(虽然 prefix block 因为有 hash 可能在 BlockPool 里被新请求复用,从而部分恢复)。下次被 schedule 时要重新跑 prefill — 这是 vLLM 在内存受限场景下的 graceful degradation。

§ M6 · 40 minGpuModelRunner — seven thousand lines.

vllm/v1/worker/gpu_model_runner.py整个 vLLM codebase 里最大的单一文件 — 7185 行。它干的事:

  1. 从 EngineCore 收 SchedulerOutput(含每个请求的 block_table、要跑的 token 数、采样参数)
  2. 构造 ForwardContext(含 attention metadata、cuda graph bucket key 等)
  3. 把 token 张量准备好(concat 所有请求的 input_ids、build position_ids、mask、block table padding)
  4. 选择 attention backend(FlashAttention / FlashInfer / Triton / ROCm AITER / ...)调它的 init_forward_metadata()
  5. model.forward(input_ids, positions, attn_metadata, kv_caches)
  6. 跑 sampling(top_k / top_p / temperature / 结构化生成 mask)
  7. 把 token 写回 KV cache(kernel-level)+ append 到 block
  8. 构造 ModelRunnerOutput 还给 EngineCore

它为什么这么大?因为它要支持:

  • CUDA Graph capture(多个 batch size bucket)+ 不 capture 的 fallback
  • 不同模型架构(dense / MoE / Mamba / 多模态)的 forward 差异
  • LoRA / 多 adapter 切换
  • Speculative decoding(draft + verify 两步走)
  • EP (Expert Parallel) MoE 的 all-to-all 通信
  • Mixed-precision (FP16 / BF16 / FP8 / INT4) 路径

每多一种"feature"都给这个类加几百行。这是大部分 inference engine 都会遇到的"巨型类陷阱"。vLLM 走的路是用 Mixin 拆(ec_connector_model_runner_mixin / kv_connector_model_runner_mixin / lora_model_runner_mixin)— 跟 SGLang Scheduler 是同一种应对策略。

§ M7 / M8 · 45 minBackends, twenty of them.

vllm/v1/attention/backends/ 有 20 个 attention 实现,全部实现同一个 AttentionBackend 抽象(backend.py)。registry.py 维护名字 → class 映射,selector.py 自动选择(根据模型架构和硬件)。

FamilyFilesLines
Flash familyflash_attn, flash_attn_diffkv, flashinfer1236 + 321 + 1969
Tritontriton_attn774
Flexflex_attention1217
ROCmrocm_aiter_fa · rocm_aiter_unified_attn · rocm_attn1471 + 304 + 545
CPUcpu_attn545
State spacemamba_attn, mamba1_attn, mamba2_attn, gdn_attn, linear_attn, short_conv_attn588 + 64 + 171 + 475 + 93 + 34
Quantizedturboquant_attn906
MLAmla/(子目录)多文件

ROCm 三件套

vLLM 在 AMD 上有三个 attention backend,对应三种策略:

BackendWhatWhen
rocm_aiter_fa.py (1471 行)★ 调 AITER 的 FlashAttention kernel(CK 实现)MI300X+ · 默认主力
rocm_aiter_unified_attn.py (304)AITER unified attention(统一 prefill+decode 入口)较新模型
rocm_attn.py (545)ROCm 通用 fallback(不依赖 AITER)老硬件 / AITER 不支持的形状

跟 SGLang 的单一 aiter_backend.py(3284 行)对比 — vLLM 把 AITER 调用拆得更细,可读性更好,但加新 ROCm-specific 优化时要看清楚改哪一个。

关键对比 · ROCm SUPPORT MATURITY

vLLM 的 ROCm 支持比 SGLang 更结构化 — 它把 AITER 包装在 vllm/_aiter_ops.py(顶层 module)里,attention 层只是消费者。改 AITER 集成时改 _aiter_ops.py 一处即可,attention backend 自动跟着走。SGLang 是把 AITER 调用直接写在 attention backend 里,更扁但耦合更深。

对你的工作:在 vLLM 上加 AITER 新 kernel 时,先改 vllm/_aiter_ops.py 暴露 API,再在 3 个 ROCm backend 里选择消费方式。

Plate IV — Two engines, side by side vLLM and SGLang, where they converge and diverge comparative
vLLM SGLang same problem space · different abstractions vLLM SCHEDULER 1× EngineCore N workers as subprocs / Ray actors PREFIX CACHE BlockPool + hash chain 16-token block granularity CONTINUOUS BATCH chunked prefill + decode mix single-pass schedule() per step EXEC OVERLAP IPC-driven (EngineCore ↔ Worker) CPU schedule overlaps GPU step ROCm 3 backends + _aiter_ops aiter_fa / unified / fallback CODE 633K · v1 rewrite 7,185-line model_runner SHINES IN general serving / OpenAI compat deployment flexibility SGLang SCHEDULER N× Scheduler one per TP rank, fully symmetric PREFIX CACHE RadixCache (tree) token-level granularity CONTINUOUS BATCH schedule_batch + policy priority queues, low-priority-first EXEC OVERLAP event_loop_overlap (in scheduler) CUDA stream / future-based ROCm 1 monolithic aiter_backend 3,284 lines · all-in-one CODE 729K · multi-package sgl-kernel as separate wheel SHINES IN multi-turn / structured / DSL prefix-heavy workloads Same problem · two abstractions
两个系统解决同一个问题(高吞吐 LLM 推理),但底层抽象选了不同路径:vLLM 走"物理 block + hash",SGLang 走"逻辑 prefix + 树"。两条路最终都会做 prefix caching、chunked prefill、speculative decoding — 但底层抽象的选择决定了哪种 workload 更舒服。短回复的 OpenAI compat API:vLLM 略好;多轮 + 结构化生成:SGLang 略好。在 AMD MI300X 上:两者都能跑,AITER 集成 vLLM 更结构化,SGLang 更直接。

§ Reefs · fiveWhat to avoid running aground.

读 vLLM 时最容易触礁的几处。

Reef N° 1 · v0 vs v1 — two universes

vllm/engine/(老 v0)和 vllm/v1/engine/(新 v1)都还在 codebase 里。看老 issue / 老 blog post 时引用的 LLMEngine 可能是 v0 那个,跟你实际在跑的 v1 EngineCore 完全不同对象。改代码前先 grep "VLLM_USE_V1" 确认 codepath。

Reef N° 2 · Block size 是 hash 函数的隐式参数

BlockPool 的 prefix caching 依赖每个 block 的 hash 包含父 block 的 hash。如果你改 block_size(默认 16),所有现存的 cache 都失效,因为 hash 计算变了。重启 vLLM 服务后必然 cold start。改 block_size 是个有副作用的运维操作。

Reef N° 3 · Preempted 请求不一定能复用 cache

_preempt_request 释放 KV blocks 回 pool,但BlockPool 可能在下次 schedule 时已经把这些 block 分配给别的请求了。所谓"hash 仍在 map 里"只在 block 还没被复用前才有效。preemption + 高 KV 压力的场景下,"复用率"是个统计平均,不是保证。

Reef N° 4 · GpuModelRunner 的 mixin 拆分易看漏

7185 行的 GpuModelRunner 用了 5+ 个 mixin(kv_connector_model_runner_mixin / lora_* / ec_connector_*)。grep 某个方法时可能找不到 — 它在 mixin 里。读 forward path 时一定要先看 class GpuModelRunner(...) 的所有父类。

Reef N° 5 · Attention backend selector 是隐式自动的

用户不指定时 v1/attention/selector.py 会根据模型架构 + 硬件自动选 backend。在 MI300X 上跑 Llama-3 默认会选 rocm_aiter_fa,但跑 DeepSeek-V3(MLA)可能选 triton_attn 或 fallback。跑 benchmark 时务必打印实际选中的 backend,不要假设。

§ AMD bearings · for JhinWhere to start touching.

三个具体起手点,对应你 multi-agent kernel optimization 的两个 ultimate goal。

1 · 在 vLLM 上跑 MI300X 性能 baseline

vLLM 的 ROCm 路径比 SGLang 更结构化 — 适合做横向对比基准

# 用 vLLM 跑同一个 model 做参照
VLLM_USE_V1=1 vllm serve meta-llama/Llama-3-70B \
  --tensor-parallel-size 8 \
  --attention-backend rocm_aiter_fa \
  --enable-prefix-caching \
  --max-num-batched-tokens 8192

# 同样的 model 在 SGLang 上
python -m sglang.launch_server \
  --model meta-llama/Llama-3-70B \
  --tp 8 \
  --attention-backend aiter

用两边自带的 benchmarks/ 跑同一组 trace,对比 throughput / TTFT / ITL。这是你 AMD performance database 的第一行数据。

2 · 改 _aiter_ops.py 加你的新 kernel

当你 multi-agent 系统跑出一个比当前 AITER kernel 更快的 attention variant,vLLM 集成路径只需改一个文件

# 添加一个新的 wrapper
def my_faster_attn(q, k, v, ...):
    """Custom AITER attention kernel optimized by MAS."""
    from my_kernels import fast_attn_v2
    return fast_attn_v2(q, k, v, ...)

然后在 rocm_aiter_fa.pyforward_extend / forward_decode 里替换调用。这种"先暴露 API,再选择消费方"的两层结构让 kernel 实验非常快。

3 · 抄 vLLM 的 _aiter_ops.py 模式做你自己的 kernel package

SGLang 的 sgl-kernel 是独立 wheel 包;vLLM 的 _aiter_ops.py顶层 module 层级的 wrapper。两种都是把"kernel"和"使用 kernel 的代码"解耦的有效手段。对你的 multi-agent kernel optimization 系统:

  • 短期:用 _aiter_ops.py 这种顶层 wrapper 模式 — kernel 改进无需碰各个 backend 文件
  • 长期:做成独立 wheel 包(学 sgl-kernel),让 vLLM / SGLang / 其他 inference engine 都能直接 import

这是 leverage 你工作的双层路径 — 先在一个引擎上做出收益,再独立发行让生态都受益。

§ EpilogueThree readings, one map.

File № 001(SkyPilot)讲的是"如何把工作丢到任何云上的任何 GPU"。File № 002(SGLang)讲的是"在那个 GPU 上如何高效跑 LLM 推理"。File № 003(vLLM)也讲推理 — 但用了不同的抽象。这三份合起来读,正好覆盖你 AMD 工作的完整栈

  • Orchestration 层(SkyPilot)— 让 multi-agent kernel optimization 系统能在多 MI300X 节点上跑分布式实验
  • Inference 层 A(SGLang)— 你目前的主力 serving 引擎,了解它的 scheduler / RadixCache 让你能改 / 加 backend
  • Inference 层 B(vLLM)— 对照系统 + 第二个测试床,跑 baseline + 验证你的 kernel 通用性

三个系统在工程上有同构的设计模式:(1) 把请求 / 任务 / 配置做成不可变值对象;(2) 把状态 / 物理资源做成可写实体并集中管理;(3) 用异步消息总线解耦组件;(4) 把调度决策真正干活分到不同进程;(5) 用plugin / abstract base class 让平台扩展低成本。这五点的反复出现告诉你 — 现代分布式 ML 系统在收敛于一组共同的工程姿态。值得把这套姿态吸收进你即将搭的 multi-agent kernel optimization 系统。

— Fin de trilogie.