通过系统压测 vLLM 理解推理性能,同时深度阅读 nano-vllm 的 1400 行源码,掌握推理引擎的核心实现。
下次课前 (一周)
使用 KV Cache 公式 2 × L × H_kv × D × T × B,完成以下计算:
使用 vLLM benchmark 工具,完成评测矩阵:
| 变量 | 取值 |
|---|---|
| 模型 | Qwen2.5-0.5B, (Qwen2.5-7B 如显存允许) |
| 输入长度 | 128, 512, 1024 |
| 输出长度 | 128, 256 |
| 请求速率 | 1, 4, 8, 16, 32 |
绘制三张曲线图并分析:
阅读 nanovllm/engine/sequence.py (84 行),回答:
SequenceStatus 有哪些状态?画出状态转换图block_table 是什么类型?它的长度由 num_blocks 属性决定,写出 num_blocks 的计算公式is_prefill 标志在何时设为 True / False?num_cached_tokens 和 num_scheduled_tokens 的区别是什么?last_block_num_tokens 如何计算?在 model_runner.py:prepare_decode() 中如何被使用?阅读 nanovllm/engine/scheduler.py (93 行),回答:
schedule() 方法中,Prefill 阶段和 Decode 阶段如何区分?(代码中的 if/else 分支条件)running 队列的哪一端 pop?为什么要 appendleft 到 waiting?postprocess() 中,hash_blocks() 调用在 append_token() 之前还是之后?为什么?num_completion_tokens == max_tokens,它会进入什么状态?它的 Block 会被立即回收吗?阅读 nanovllm/engine/block_manager.py (121 行),回答:
compute_hash() 的 prefix 参数有什么作用?为什么需要链式哈希?can_allocate() 返回值 -1 表示什么?返回值 ≥ 0 表示什么?allocate() 中,已缓存的 Block 和新增 Block 的处理逻辑有何不同?ref_count 如何支持 Copy-on-Write?当两个 Sequence 共享一个 Block 时,ref_count 的变化过程是怎样的?hash_blocks() 为什么只 hash num_cached_tokens 到 num_cached_tokens + num_scheduled_tokens 范围?阅读 nanovllm/layers/attention.py + engine/model_runner.py::prepare_prefill/ prepare_decode,完成:
slot_mapping 的构建过程(以 2 个 Sequence, block_size=256 为例)slot_mapping 只有一个值 — 为什么?它的计算公式是什么?block_tables 的 shape 是 [num_seqs, max_blocks_per_seq] — 为什么需要 padding 到相同长度?attention.py 中,Prefill 使用 flash_attn_varlen_func,Decode 使用 flash_attn_with_kvcache — 两个函数的区别是什么?(查看 flash_attn 文档)store_kvcache_kernel (Triton kernel) 中 slot == -1 的判断有什么作用?阅读 nanovllm/engine/llm_engine.py + engine/model_runner.py::capture_cudagraph,完成:
LLMEngine.step() 的三步流程是什么?画出数据流图 (schedule → run → postprocess)generate() 如何知道所有序列都已完成?is_finished() 的判断条件是什么?graph_bs = [1, 2, 4, 8, 16, 32, ...] — 为什么需要多个不同 batch size 的 graph?enforce_eager=True 时,CUDA Graph 是否生效?为 nano-vllm 添加一个新功能 (任选一):
priority 字段,Scheduler 优先调度高优先级序列generate() 返回前,打印每个 Sequence 的 TTFT / TPOT / total tokensadd_request() 的多轮对话 API,自动携带历史 KV Cache| 维度 | 权重 | 要求 |
|---|---|---|
| 任务 1 (KV Cache 计算) | 15% | 公式正确、计算准确、有分析 |
| 任务 2 (压测) | 20% | 有完整的评测数据和图表分析 |
| 任务 3-5 (源码分析) | 35% | 正确回答所有问题,分析深入 |
| 文档质量 | 15% | 代码注释清晰、报告结构完整 |
| 进阶任务 (任务 6-8) | 15% | 完成至少一项进阶任务 |