📘 vLLM Architecture · home

vLLM Unified Architecture Report

一份文档,合并了此前所有报告: spine + L1–L4 agent + 第一性原理(软件+物理双视角) + Performance Handbook + Ascend 官方设计文档 + community 90 天 pulse。 每个 section 顶部标注 source: 溯源锚点。全部原始报告保存在 /vllm_research/vllm_analysis_raw/,1:1 可回溯。 阅读顺序: §0 Overview → §1 软件架构第一性原理 → §2 分层 → §3 热点路径 → §4–§10 深度 → §11 引用。

0. Overview & v0→v1 Synthesis

This single document merges all prior analyses (spine, L1–L4 agents, first-principles software+physical, performance handbook, community pulse, Ascend official design docs) into one navigable report without losing any file:line source anchor. All original raw reports are preserved in /vllm_research/vllm_analysis_raw/ for 1:1 traceability. Each section carries a source band (source: …). Reading order: this overview → §1 first-principles → §2 architecture layers → §3 execution hot path → §4–§10 deep dives → §11 references.

0.1 v0 的两条缠结 → v1 的解法

v0 症状根因 (v0 结构)v1 解法
调度策略改动必须同时改 Worker+Scheduler+ModelRunner三者按“功能”分区,没按“变化速率”分区Scheduler 独立 + EngineCore 单线程事件循环
长 prefill 卡死 decode,TTFT/TTIT 不可同时优化prefill phase + decode phase 两阶段模型单一 token-budget 循环,无阶段之分
加新硬件需碰 200+ 个模型文件attention kernel 嵌在模型代码里AttentionBackend + Builder + Impl + KVCacheSpec 家族
prefix cache / CUDA graph / offload 改动互相传染单一 BlockSpaceManager 耦合请求生命周期+分配+缓存+swap拆 KV-Stack 为 Manager/Coordinator/BlockPool/Connector 四层

1. Software-Architecture First Principles

PRINCIPLE #0 — The single axiom: "A module boundary should be drawn where the rate of change changes." If A's code changes every day and B's every year, splitting them means "A's daily changes never touch B." If A and B always change together, they belong in the same module.

1.1 The axiom applied — rates → modules

RatevLLM code elementIsolated into module
daily — policy, schedule order, thresholdrecompute / SRF / chunked / FCFS / profiling-chunkScheduler
weekly — new models200+ models (DeepSeek/Qwen/GLM/Gemma/Kimi/MiniMax…)models/ directory
monthly — new HW / new kernel variantsFA3 / FlashInfer / Triton / CANN / ROCmAttentionBackend + ops/
quarterly — topology, comm layoutTP/PP/DP/EP/CP combinationsWorker + distributed/
yearly — execution paradigmCUDA Graph / torch.compile / ACL GraphCompilation
never — inference math"1 step = schedule → forward → sample"EngineCore.step

1.2 Each module — its ONE job and what it never touches

ModuleOwnsDoes NOT touch
EngineCore
v1/engine/core.py:101
Time-line (the step() loop), request lifecycle, pause/resume/sleep/wake, DP coordination, LoRA hot-plugdevice, model, tensor, scheduling strategy
Scheduler
v1/core/sched/scheduler.py:418
PURE decision fn: request state + blocks -> SchedulerOutputdevice, model, kernels, comm
Worker
v1/worker/worker_base.py+gpu_worker.py
The device, weights in HBM, KV-cache tensors, load/determine_memory/sleep/healthscheduling decisions, request state
ModelRunner
v1/worker/gpu/model_runner.py:1134
Translates SchedulerOutput -> kernel dispatch (5 stages)request admission, scheduling, device discovery
AttentionBackend
v1/attention/backend.py
Common attn metadata -> HW-private metadatamodel structure, scheduling, KV-cache ownership
KV 4-layer stackManager (request↔block) / Coordinator (multi-group) / BlockPool (free-list+hash) / Connector (cross-worker tiering)scheduling dispatch, model execution
Compilation
compilation/
Kernel launches -> graph replay (FULL/PIEWISE/NONE)model semantics, scheduling
Platform
platforms/
Device-specific assumptions behind 6 mandatory methodseverything above

1.3 Cross-module contracts — why they are cut this way

ContractProducer → ConsumerDesign decisionWhy
SchedulerOutputv1/core/sched/output.pyScheduler → ModelRunneronly decisions (block ids + token counts), no tensorsScheduler runs CPU-only; enables cross-node transport (PD disagg)
ForwardContextforward_context.py:132ModelRunner → modelmodel reads ForwardContext only; never sees SchedulerOutputchanging scheduling/graph-mode/parallelism never touches 200+ model files
block_tables + slot_mappingsModelRunner → AttentionBackendONE translation shared by N backendsavoids N copies of page-table-walk logic
KVCacheBlockskv_cache_manager.py:30Scheduler → Workeronly block ids, no tensorscross-node transport (PD disagg)
allocate_slots → NoneKVCacheManager → Schedulerreturns None instead of raising on OOM"allocation failure" → normal control flow; one while-loop handles both allocate & preempt

1.4 First-principles meta-judgement — forced vs chosen

Among all vLLM's layers, a few are forced by physics: paged-KV, Attention-as-separable-backend, Communication-via-Connector, Platform-as-interface — these are stable across HW generations. Others are engineering choices a v2 may freely redesign: the Python front-end, the shm-RPC executor, capability-dispatched sampling, the patch layer. Every heavily-patched subsystem is a gap in vLLM's abstraction surface.

2. Architecture Layers

§2Architecture Layerssource: first_principles_software_arch §2-9 + agent1-3

2.1 EngineCore — the time-line owner

v1/engine/core.py:101 EngineCore. The heartbeat (core.py:576):

def step(self):
    scheduler_output = self.scheduler.schedule()          # 1. decide
    future = self.executor.execute_model(scheduler_output, non_block=True)  # 2. async dispatch
    model_output = future.result()                        # 3. wait
    engine_core_outputs = self.scheduler.update_from_output(scheduler_output, model_output)

EngineCore also owns: add/abort, pause/resume, sleep/wake, LoRA hot-plug, cache reset (reset_prefix_cache/reset_encoder_cache), DP coordination (step_with_batch_queue), spec-draft collection (post_step → take_draft_token_ids). It holds NO device/model/tensor — runs CPU-only, the ultimate control/data-plane split.

2.2 Scheduler — the pure decision function

v1/core/sched/scheduler.py:418. The design axiom (scheduler.py:420):

# There's no "decoding phase" nor "prefill phase" in the scheduler.
# Each request just has num_computed_tokens and num_tokens_with_spec …
# At each step, the scheduler tries to assign tokens to the requests so
# that each request's num_computed_tokens can catch up its
# num_tokens_with_spec. This is general enough to cover chunked prefills,
# prefix caching, speculative decoding, and "jump decoding."

Unified token-budget loop over RUNNING then WAITING, chunked via long_prefill_token_threshold, preemption when allocate_slots returns None. Holds no device/model/comm.

2.3 Worker — the device owner

v1/worker/worker_base.py+gpu_worker.py. One Worker per GPU/NPU. Responsibilities: init_device, load_model/reload_weights, determine_available_memory, kv_caches tensors, sleep/wake, LoRA add/remove/pin, execute_model, sample_tokens, health check. Does NOT hold Scheduler, makes no scheduling decisions, holds no request state — consumes SchedulerOutput statelessly. Worker holds ModelRunner but the two are separate: same device can run different models; same model can run on different devices (Ascend NPUWorker(NPUModelRunner) subclasses but keeps the interface).

2.4 ModelRunner — the forward executor

#stageinput → outputmeaning
1Request bookkeepingSchedulerOutput → req_statesdecisions → local state
2prepare_inputsreq_states → InputBatch{input_ids, positions, q_start_loc, seq_lens, logits_indices}request state → model input tensors
3prepare_attnreq_states+pool → block_tables[groups,reqs,blocks] + slot_mappings[groups,tokens]block ids → page-table walk
4model_state.prepare_attncommon_attn_metadata → attn_metadata[per-backend]common → HW-private metadata
5model forward / cudagraph replayinputs → hidden/logitstensors → compute

2.5 AttentionBackend — the only HW-sensitive op

Attention is the ONLY op whose memory-access pattern depends on sequence length + KV layout (GEMM/Norm/MoE/RoPE are all regular (N,d)→(N,d)). The triple: register_backend + Builder.build(common) + Impl.forward + KVCacheSpec family (FullAttentionSpec / MLASpec / RSWASpec / RaggedSpec). ModelRunner only sees KVCacheSpec, not concrete model — this decouples "model structure change" from "KV management".

2.6 Platform — device as interface

platforms/. 6 mandatory methods. Holds device capability/memory/stream/attn-backend-selection/graph-pool. Ascend NPUPlatform overrides only identity+backend-map+memory+compile hooks; its get_device_total_memory raises NotImplementedError (torch_npu global-init-only) — a canonical "interface promise vs device capability" mismatch.

2.7 Compilation — "record once, replay many"

compilation/+v1/worker/gpu/cudagraph_utils.py. Platform injects ACLGraphWrapper via get_static_graph_wrapper_cls(). See §6 for the 3-mode trade-off and ACL-specific constraints.

3. Execution Hot Path (Scheduler → ModelRunner → Sample)

§3Hot Pathsource: arch_spine §4 + agent1+agent2 + dsa_analysis

3.1 The page-table walk (slot_mapping kernel)

v1/worker/gpu/block_table.py:283 (_compute_slot_mappings_kernel)
block_indices  = positions // (block_size * CP_SIZE)
block_offsets  = positions %  (block_size * CP_SIZE)
block_numbers  = tl.load(block_table_ptr + req_state_idx*stride + block_indices)
slot_ids = block_numbers * block_size + block_offsets   <- physical address
This line is isomorphic to OS phys = ppn * PAGE_SIZE + page_offset: block_table=page table, block_id=PFN, slot_id=linear address. PAD_SLOT_ID = "invalid PTE". vLLM doing virtual-memory management on GPU HBM, formalised.

3.2 The 3-line heartbeat

def step(self):
    scheduler_output = self.scheduler.schedule()
    future = self.executor.execute_model(scheduler_output, non_block=True)
    engine_core_outputs = self.scheduler.update_from_output(scheduler_output, future.result())

3.3 SchedulerOutput — the Scheduler↔Worker contract

v1/core/sched/output.py: scheduled_new/resumed/running/preempted reqs, req_to_new_blocks, num_scheduled_tokens, scheduled_spec_decode_tokens, scheduled_encoder_inputs, finished_req_ids. Carries ONLY decisions (block ids + token counts) — no tensors — so it crosses process/node boundaries (PD disagg relies on this). 4 explicit categories (new/resumed/running/preempted) let Worker use simple if-else. Block allocation done in Scheduler side — Worker only consumes block ids.

3.4 ForwardContext — the model↔framework firewall

forward_context.py:132: attn_metadata[per-layer], slot_mapping[per-layer], dp_metadata, cudagraph_runtime_mode, batch_descriptor, is_padding, skip_compiled, +all_moe_layers/moe_layer_index (torch.compile string workaround). Model code (200+ files) reads only ForwardContext — changing scheduling/graph-mode/parallelism never touches model files.

3.5 allocate_slots → None — control-flow unification

while True:
    new_blocks = kv_cache_manager.allocate_slots(request, num_new_tokens)
    if new_blocks is not None: break
    preempted = self.running.pop()   # reclaim budget
    self._preempt_request(preempted)

Returning None (not raising) keeps preempt logic in the same while-loop as allocate logic.

4. KV-Cache Management — why 4 layers, not 1

§4KV 4-layer stacksource: arch_spine §2 + agent2 + dsa_analysis + community_deep_dive §4
LayerFileOwnsRate of change
KVCacheManagerv1/core/kv_cache_manager.py:114request-lifecycle ↔ block allocation (allocate_slots/free/get_computed_blocks)daily (policy)
KVCacheCoordinatorv1/core/kv_cache_coordinator.py:60multi-group (MLA+GQA+SWA): logical block id → per-group physical block idsweekly (model structure)
BlockPoolv1/core/block_pool.py:143free-list + content-hash cache (get_new_blocks/free_blocks/touch/evict)monthly (algorithm)
KVConnectordistributed/kv_transfer/kv_connector/v1/base.py:171cross-worker KV movement (PD disagg / offload / KV Pool)quarterly (topology)

4.1 BlockPool — pure metadata, content-hash

v1/core/block_pool.py:162: blocks = [KVCacheBlock(idx) for idx in range(num_gpu_blocks)], free_block_queue, cached_block_hash_to_block = BlockHashToBlockMap(). KVCacheBlock (kv_cache_utils.py:117) is pure metadata — no tensor. The actual bytes live in Worker-side kv_caches: list[torch.Tensor] (model_runner.py:490). This two-layer split lets prefix-cache/swap/sliding-window/compressed-MLA all renumber the same block_ids without touching the pool.

4.2 Coordinator subclasses

UnitaryKVCacheCoordinator (single group), HybridKVCacheCoordinator (MLA+GQA mixed, e.g. DeepSeek-V3), KVCacheCoordinatorNoPrefixCache. MLA's storage_block_size ≠ block_size mapping is encapsulated here — Manager only calls Coordinator's interface.

4.3 Why 4 layers — the MLA forcing function

v0 had a single BlockSpaceManager. MLA's storage_block_size ≠ block_size added a logical→physical mapping that would have scattered across allocate/free/prefix-cache. After the split, this mapping is encapsulated in Coordinator. "Multi-group mapping" changes are isolated to one layer.

Splitting manager↔coordinator: new KV layout (MLA) changes Coordinator only. Splitting coordinator↔blockpool: prefix-cache/eviction changes BlockPool only. Splitting manager↔connector: PD disagg/offload changes Connector only.

5. Parallel & Distributed (TP/PP/DP/EP/CP/EPLB)

§5Parallelsource: arch_spine §6b + agent4 + community_deep_dive §4-5
StrategySplitCommBubble/costvLLM location
TPper-layer matmul (hidden/head)per-layer all-reduce2M/rankTP_GROUP + ColumnParallelLinear
PPlayer segmentsP2P [b,h,d](p-1)/pPP_GROUP + IntermediateTensors
DPreplicabatch-desc synclinear scale, CUDA-graph sync neededdp_utils + cudagraph_sync_dp
EPMoE by expertall-to-all routingimbalance=hotspoteplb/ + distributed/moe/

These compose (production runs TP8+EP64+PP4+DP32 simultaneously). Scheduler does NOT know TP/EP — its granularity is "request", not "token on which card". Worker handles via model-internal ColumnParallelLinear/MoEDispatch; ModelRunner never calls comm directly. Ascend HCCL via distributed/pyhccl.py PyHcclCommunicator.

5.1 Context Parallel (PCP/DCP)

VariantWhenComm domainGoal
PCP (Prefill-CP)prefill phaseindependentsplit sequence across devices; reduce TTFT
DCP (Decode-CP)decode / chunked-prefillreuses TP domain (no extra devices)eliminate TP-domain KV redundancy → free HBM → more concurrency

cp_size = pcp_size × dcp_size; token-interleave storage via cp_kv_cache_interleave_size (default 1); block_size % cp_kv_cache_interleave_size == 0 required.

5.2 EPLB — Ascend's original MoE contribution

Expert-migration stack: EplbUpdator → policy (FlashLB Hungarian + numba tree-search, FlashTree, SwiftBalance) → D2DExpertWeightLoader → VllmEplbAdaptor. The only net-new subsystem from Ascend to upstream vLLM.

5.3 PD disagg — cutting the Worker boundary, no new module

P node owns Scheduler+Worker(P)+KVConnector(P→D); D node owns Scheduler+Worker(D)+KVConnector(D←P). Scheduler only sees KVCacheBlocks (ids), not which node holds the block — "request lifecycle ⟷ KV physical location" decoupling, the direct payoff of KVCacheManager being independent of Scheduler.

6. Compilation & Graph (CUDA/ACL Graph, Fusion, Quant)

§6Compilation & Graphsource: arch_spine §8 + agent3 + community_deep_dive §2 + stripped asci_docs

6.1 Three execution modes

ModeDynamic dimsHBMTTFTUse
FULLfully fixed (2^k pad)highslow (first-token record)pure decode, max throughput
PIECEWISEdynamic shapesmediumfastmixed prefill+decode, long context
Eager (NONE)fully dynamiclowfastestdebug, encoder-decoder (cross-attn changes every step)

Dispatch: v1/worker/gpu/cudagraph_utils.py CudagraphDispatcher, candidate key (rounded_num_tokens, num_active_loras); each recorded at warm-up, runtime looks up nearest case.

6.2 ACL Graph — why Ascend cannot just port CUDA Graph

Source: official docs/source/developer_guide/Design_Documents/ACL_Graph.md

Diff A — full replay needs backend-side update_graph_params() hook (NPU-only). Capture phase records per-graph task handle/event/workspace; replay frontend calls update_full_graph_params() → backend runs parameter refresh on update stream via torch.npu.graph_task_update_begin/end(); ExternalEvent enforces ordering. Key fact: an attn backend WITHOUT this hook CANNOT do full-graph replay. Implemented in vllm_ascend/attention/attention_v1.py, mla_v1.py, context_parallel/attention_cp.py, mla_cp.py.

Diff B — ACL capture can still be rejected by runtime resources. Capture sizes are measured, not estimated from CUDA. Tune cudagraph_capture_sizes / max_cudagraph_capture_size.

6.3 Mode normalization (stricter than upstream)

encoder-decoder forced PIECEWISE; use_inductor disabled on graph path; ASCEND_LAUNCH_BLOCKING=1 rejected when graph enabled; Xlite can disable full mode / fall back to FULL_DECODE_ONLY.

6.4 Fusion & Quant

70+ fusion passes in AscendCompiler/GraphFusionPassManager (AllReduce+RMSNorm, QK-Norm+Rope, AllGather-chunk-noop, NoOp, norm-quant). 10+ quant schemes (W4A4/W4A8/W8A8/PDmix/MXFP/FlatQuant). Rule of thumb: MoE→W4A8, dense→W8A8, extreme(EP off)→W4A4. W4A4∧EPLB incompatible = CANN kernel-coverage limit.

7. Ascend Overlay — DSA/SFA/KV Pool/PD/SRF/CPU-binding

§7Ascend Overlaysource: agent4 + community_deep_dive §3-5 + arch_ascend + stripped asci_docs + key_code/

7.1 Subsystem × mechanism map

SubsystemMechanismKey file
Platformsubclass Platform + config injectionplatform.py NPUPlatform (1255L)
Attention5 backends (ASCEND/MLA/SFA/DS_A/FA3)attention/*_v1.py
Custom opsCANN custom op + substitutionops/ 86 files
Quant10+ QuantConfig subclassesquantization/
CompilationACL Graph + 70 fusionacl_graph.py, AscendCompiler
CommHCCL wraps NCCLpyhccl.py PyHcclCommunicator
KV transportP2P mooncake + ascend_store poolkv_p2p/mooncake_connector + kv_pool/ascend_store
Schedulerrecompute + SRF + profiling-chunkcore/recompute_scheduler.py
EPLBwhole subsystem (Ascend original)eplb/
Patch60+ setattrpatch/

7.2 Three Ascend original innovations

  1. Schedule-level (roofline NPU): RecomputeScheduler (recompute_scheduler.py:98) replaces preemption's offload-to-CPU with drop-and-recompute. Also SRF + profiling-chunk.
  2. EPLB — the net-new vLLB contribution: FlashLB+FlashTree+SwiftBalance, 3-stage updator→policy→D2D migration.
  3. ACL Graph (§6.2) with update_graph_params hook requirement; GraphFusionPassManager 70 passes.

7.3 KV Pool (Ascend Store) — the memory tier

3 backends: Mooncake (Distributed Store + SSD offload), Memcache (MemFabric), Yuanrong (openEuler etcd+HugeTLB). Plus NVMe SSD offload. Mirror of OS cache→DRAM→swapfile. Tuning: kv_load_failure_policy=recompute (hybrid-attn like DSV4 not yet supported); lease TTL ≥ ASCEND_CONNECT_TIMEOUT+TRANSFORM; fabric mem A3 1GB-aligned; PYTHONHASHSEED consistent across nodes; warm-up 2-3× device-count of 8K-input/1-output requests.

7.4 SRF + CPU-binding + Netloader

SRF: anti head-of-line on P-node; threshold=P70-P85 prompt-len, long_max_wait=long-req P90 under strict-short-first. CPU-binding: default-on ARM since v0.18 (uses npu-smi topo to pick NUMA). Netloader: HCCL send/recv weight transfer, register_model_loader API.

7.5 Patch layer = diagnostic of "missing extension points"

Canonical examples: patch_fused_moe (no FusedMoE-factory-swap iface), patch_cudagraph (CudagraphDispatcher assumes CUDA-graph-only), patch_kv_cache_coordinator (internal state not exposed), patch_mla_prefill_backend (no MLA prefill backend-switch iface). Every heavily-patched subsystem is a candidate for a new upstream extension point.

8. Performance Optimisation Handbook (OS → allocator → HCCL → kernel → fusion)

§8Perf Handbooksource: community_deep_dive §1 + asci_docs/perf_*.md + docs/source/developer_guide/performance_and_debug/optimization_and_tuning.md
LayerKnobEffect
OSgovernor→performance; swap=0; auto-NUMA-bal off; sched_migration_cost_ns=50000host jitter ms→μs
Allocatorjemalloc/TCMallocpeak-throughput fragmentation reduced
torch_npu envmemory/scheduling togglesCANN best defaults
HCCL commAIV mode (AI vect core bypasses AI CPU); INTRA_ROCE_ENABLE; RDMA_TC/SL; BUFFSIZENPU-only layer: comm ms→sub-ms
Fusion70+ passesfewer launches + fewer intermediate HBM writes
"50% of the perf bottleneck is NOT in model forward — it is at the host ↔ NCCL/HCCL boundary."

Test practice: unit tests (tests/ut, CPU-runnable) + E2E regression (tests/e2e) + nightly CI (schedule_nightly_test_a2/a3.yaml). Profiling chain: msprobe (NPU kernel timeline) → service_profiling_guide → service_benchmark (recommend 2-3× device-count warm-up of 8K-in/1-out).

Feature-matrix key exclusions

PIECEWISE ⟷ FULL: mutually exclusive. DP+CP: only DCP supports DP. Flashcomm: prefill-only. W4A4∧EPLB/TP: ❌. MLAPO: decode-only. MM input + ACLGraph Full: ❌.

Supported models

20+ mainstream on A2/A3 with full TP+EP+PD-Disagg+Full-Graph: DeepSeek V3→V4, Qwen3, GLM5, Kimi-K2, MiniMax-M2. Gemma4/950 experimental. See docs/source/user_guide/support_matrix/.

9. Generic vLLM Hardware-Adaptation Playbook

§9Generic Playbooksource: agent4 Part B

9.1 8-step workflow

#GoalExtension point
1device discoveryPlatform.get_device_* + get_attn_backend_cls
2paged KVKVCacheSpec family + Manager + Coordinator + BlockPool (full I1 stack, reuse unchanged)
3attentionregister_backend (the ONLY must-replace)
4other kernelscustom op (ascend uses 4 paths: direct_register / torch_npu / Triton / CANN)
5worker/runnersubclass GPUModelRunner (ascend has 3 runners: v1 ACL / v2 piecewise / Xlite)
6commCommunicator wraps NCCL (ascend HCCL via ctypes)
7config injectioncheck_and_update_config + scheduler_cls string swap
8teststests/ut + tests/e2e

9.2 MUST / SHOULD / NICE

MUST (won't start): Platform / Attention / paged-KV / GEMM / comm / Worker.
SHOULD (halved without): ACL-graph / quant / Scheduler-tweak.
NICE (Ascend-tier): EPLB / KV-PD / recompute / Xlite.

9.3 Fork vs plugin vs patch

Fork when expansion >25% upstream. Plugin when Platform/Attention/KVConnector/QuantConfig/scheduler_cls have registration points. Patch = workaround; every patch is a break-point each major release.

9.4 7 risk categories

API drift, patch fragility, name leakage, meta omission, config explosion, multi-runner, test gap. Patch layer = the single largest risk surface.

10. Community Pulse (2026 Q2–Q3)

§1090-day pulsesource: community_deep_dive §6 + appendix_community.md

Window: vllm-ascend git log 2026-04-01..07-18, ~1060 commits.

TopicCommitsSignal
kv97KV full-stack (PD/Pool/CPU-offload) — absolute focus
A364new-gen HW ramp
quant61W4A4/W4A8/W8A8/MXFP diversity
spec53spec decode family (Eagle3/DFlash/DSpark/MTP/PCP)
31053310P is a separate HW line (not A3 subset)
PCP35prefill CP
eplb24Ascend original
MLA15DeepSeek compress
recompute14roofline NPU-side
Flashcomm11CANN fused-comm
disagg8PD disagg engineering

5 advanced principles (only visible in community activity)

  1. P1 comp/bandwidth ratio decides swap vs recompute (NPU recompute, GPU swap)
  2. P2 PD disagg projects roofline inter-node (chunked prefill vs PD disagg = two implementations of same insight)
  3. P3 KV-cache evolves cache → memory tier (HBM → extended pool → SSD offload, mirrors OS)
  4. P4 host-jitter = last 10% P99 after kernel fusion (CPU binding+msprobe+Netloader converge)
  5. P5 both ends of Python 95/5 compressed; eventual pressure to move scheduler to C++/Rust

Three-layer enforcement hierarchy

LevelvLLMAscend
L1 implement-to-existpaged-KV / single-step scheduler / PlatformHCCL↔NCCL / Platform shim / ACL Graph
L2 implement-to-competeprefix cache / chunked prefill / CPython 95/5recompute / KV Pool / SRF / quant diversity
L3 implement-to-winPD disagg / spec decodeCPU binding / profiling-chunk / Netloader / Flashcomm

11. References & Drill Anchors

§11Refs & Anchorssource: synthesised from all reports + file_map + stripped asci_docs

11.1 Key source anchors (file:line)

AnchorWhat
v1/engine/core.py:576EngineCore.step (3-line heartbeat)
v1/core/sched/scheduler.py:418schedule() unified loop
v1/core/kv_cache_manager.py:283allocate_slots (returns None on OOM)
v1/core/block_pool.py:283slot_id = block_number*size+offset
v1/worker/gpu/model_runner.py:1134execute_model 5-stage
v1/worker/gpu/block_table.py:283_compute_slot_mappings_kernel
v1/attention/backend.pyregister_backend / Builder / Impl
forward_context.py:132ForwardContext (model↔framework firewall)
compilation/cuda_graph.pyCUDAGraphRunner
kv_connector/v1/base.py:171KVConnectorBase_V1
platforms/interface.pyPlatform (6 mandatory methods)
ascend/platform.pyNPUPlatform
ascend/attention_v1.py @register_backendASCEND / ASCEND_MLA / DSA / SFA / FA3
ascend/acl_graph.pyACLGraphWrapper
ascend/core/recompute_scheduler.py:98RecomputeScheduler
ascend/eplb/EPLB stack (Ascend original)
ascend/kv_p2p/mooncake_connector.pyMooncakeConnector

11.2 External links

11.3 Raw reports (1:1 traceability)

All original reports preserved in /vllm_research/vllm_analysis_raw/ after this refactor.

vLLM 2db39c704 — Ascend b266da5d (90-day window 04-07/2026) — 2026-07-18 — Unified