尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

vllm学习笔记之调度器/抢占/分块预填充(scheduler/preempt/chunked prefill):用 TaoToken 统一 Key 跑通配置骨架

发布时间:2026/9/29 22:57:05

资讯中心
01
ARTICLE

vllm学习笔记之调度器/抢占/分块预填充(scheduler/preempt/chunked prefill):用 TaoToken 统一 Key 跑通配置骨架

vllm学习笔记之调度器/抢占/分块预填充(scheduler/preempt/chunked prefill):用 TaoToken 统一 Key 跑通配置骨架
1. 从一次本地推理卡顿说起为什么要啃 vLLM 调度器如果你在本地跑过 vLLM 的离线推理脚本大概率遇到过这种场景几个短 prompt 秒回突然塞进去一个 8K 长文本整个服务像被按了暂停键后面排队的请求全部干等。这不是模型慢而是调度器在 prefill 阶段被一个长请求独占了 GPU。vLLM 的 scheduler、preempt抢占、chunked prefill分块预填充这三个机制就是专门解决这类资源竞争问题的。这篇笔记面向正在调试本地推理服务的同学把 vLLM 从LLM.generate()到Scheduler.schedule()的调用链拆开重点落在三件事请求怎么进 waiting queue、KV cache 不够时怎么抢占、长 prefill 怎么被切成 chunk 交错执行。同时我会给出一套可复制的配置骨架并用 TaoToken 统一 Key 把模型对话和接入文档串起来方便你在学习源码的同时有一套能跑通的验证环境。读完你应该能自己改max_num_batched_tokens、观察调度日志、判断抢占是否频繁发生。需要先说明vLLM 的调度逻辑在 V0 和 V1 之间有差异本文以当前主流的 V1 引擎行为为主涉及 V0 的地方会单独标注。源码路径以vllm/v1/core/sched/scheduler.py为参考不同版本行号会变但函数名和状态机基本稳定。2. TaoToken 前置统一 Key 与配置骨架准备在深入调度器之前先把验证环境搭好。学习源码时经常需要一边跑推理一边调模型接口做对照如果每个模型都单独配一套 Key 和 base_url配置会非常散。TaoToken 提供统一 Key把模型对话、coding plan、API Keys 管理收敛到一个入口适合这种「边学边验证」的场景。你需要准备的东西不多一个可用的 API Key以及两个配置文件骨架。下面这份config.toml是我在本地调试时用的结构把模型服务地址和调度相关参数分开避免改调度参数时误动接入配置。# config.toml - 本地推理 统一 Key 接入骨架 [server] host 0.0.0.0 port 8000 # vLLM OpenAI 兼容服务的基础地址 base_url http://127.0.0.1:8000/v1 [taotoken] # 统一 Key从控制台获取后填入环境变量更安全 api_key_env TAOTOKEN_API_KEY # 模型对话入口用于对照验证 chat_endpoint https://taotoken.net/api # 接入文档排障时对照参数 doc_ref https://taotoken.net/api [scheduler] # 调度核心参数下面会逐个解释 max_num_batched_tokens 8192 max_num_seqs 64 enable_chunked_prefill true gpu_memory_utilization 0.90 preemption_mode recompute对应的settings.json用于客户端侧把请求参数和调度观察开关放一起{ model: facebook/opt-125m, sampling: { temperature: 0.8, top_p: 0.95, max_tokens: 256 }, scheduler_probe: { log_schedule_each_step: true, log_preempt_events: true, log_chunk_boundaries: true }, taotoken: { api_key_env: TAOTOKEN_API_KEY, console_ref: https://taotoken.net/api } }把 Key 写进环境变量别硬编码进文件export TAOTOKEN_API_KEY你的统一Key这里有个容易踩的点base_url指向本地 vLLM 服务而 TaoToken 的chat_endpoint用于模型对话对照。两者不要混用本地推理走本地端口需要对照云端模型行为时再切到统一 Key 的入口。API Keys 的创建和管理在控制台完成接入文档里有完整的参数说明排障时优先查文档而不是猜。3. 可复制配置调度器、抢占与分块预填充参数详解这一节把配置骨架里的每个调度参数讲清楚你改完能直接观察行为变化。3.1 请求如何进入 scheduler 的 waiting queue从LLM.generate()开始追。generate()内部调用_validate_and_add_requests()再到_add_request()最终走到llm_engine.add_request()。这条链上做了三件事input_preprocessor.preprocess()预处理 prompt_add_processed_request()创建Sequence和SequenceGroup最后scheduler.add_seq_group()把请求塞进 waiting queue。关键状态定义在SequenceStatus里class SequenceStatus(enum.IntEnum): WAITING 0 RUNNING 1 SWAPPED 2 FINISHED_STOPPED 3 FINISHED_LENGTH_CAPPED 4 FINISHED_ABORTED 5 FINISHED_IGNORED 6请求刚进来是 WAITING被调度选中后通过_allocate_and_set_running()变成 RUNNING同时block_manager.allocate()给它分配 KV block。SWAPPED 是抢占后可能进入的状态注意注释里写的SWAPPED 之后的状态都算 finished。3.2 schedule() 与两种调度路径Scheduler.schedule()是核心入口它调用_schedule()挑选本轮执行的 sequence group返回SchedulerOutputs里面包含 batch、调度信息、以及哪些 KV block 需要 swap in/out/copy。调度分两条路径路径函数行为默认_schedule_default()一次性处理整个 prefill顺序 prefill decode分块_schedule_chunked_prefill()拆分 prefill交错执行 prefill 和 decode动态调整 chunk size_schedule_running()负责处理 running 队列_schedule_prefills()负责 prefill 阶段的 sequence group。开启 chunked prefill 后调度策略会先批量处理所有待执行的 decode 请求max_num_batched_tokens还有空余时才安排 prefill装不下就自动分块。3.3 抢占触发条件与模式抢占发生在「要为新的序列分配 KV block但缓存池没有足够空闲块」时。默认在 V1 中抢占模式是 RECOMPUTE 而非 SWAP也就是被抢占的任务丢弃 KV cache等资源恢复后从头 prefill 重算。为什么要有抢占三个原因GPU 显存和 KV cache 有限避免头阻塞长 prompt 不能把新请求全堵死提升系统稳健性动态腾缓存保证服务质量。这跟传统 GPU scheduler 处理 3D compute workload 的抢占思想类似只不过 vLLM 抢占的是 KV cache block 资源。调优方向很明确提高gpu_memory_utilization给 KV 更多空间减小max_num_seqs或max_num_batched_tokens降低每批 KV 需求增大tensor_parallel_size或pipeline_parallel_size腾出显存。3.4 chunked prefill 的计算量账分块处理理论上不改变总计算量FFN 部分每个 chunk 线性相加总和一致。变化在 attention以一个 8K prompt 为例直接 prefill 复杂度 O(N²) 约 64M。切成 4 个 2K chunk 后第一个 chunk 4M第二个 12M第三个 20M依次类推。从第二个 chunk 起每个 attention kernel 都要重新读取之前所有 token 的 KV 对。如果切成 N 个 chunk第一个 chunk 的 KV cache 会被读 N 次第二个 N-1 次。所以 chunked prefill 是否划算取决于 FFN 和 attention 的占比。prompt 越长attention 占比越高N² 增长分块带来的额外读取开销越明显。但换来的是 decode 请求被优先处理ITL 改善GPU 利用率提升。4. 验证请求观察调度日志与抢占行为配置改完得能验证。下面这套动作可以让你直接看到调度器在干什么。4.1 启动服务并确认 chunked prefill 生效python -m vllm.entrypoints.openai.api_server \ --model facebook/opt-125m \ --max-num-batched-tokens 8192 \ --max-num-seqs 64 \ --enable-chunked-prefill \ --gpu-memory-utilization 0.90启动日志里会打印类似Chunked prefill is enabled with max_num_batched_tokens8192的行。如果没看到说明参数没生效检查--enable-chunked-prefill是否拼写正确。4.2 用统一 Key 对照验证模型行为本地服务起来后用 TaoToken 的模型对话入口做对照确认请求参数一致curl -s https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: facebook/opt-125m, messages: [{role: user, content: Hello, my name is}], temperature: 0.8, top_p: 0.95 }返回结构里能看到生成的 token 和 finish_reason。这一步的目的是确认你的采样参数和本地推理脚本一致避免因为参数差异误判调度行为。4.3 构造长 prompt 触发分块与抢占写一个脚本先发 16 个 4K 长度的 prompt总 token 64K 超过 8192 的 batch 上限观察是否被切成多轮 prefillfrom vllm import LLM, SamplingParams prompts [请详细解释调度器原理。 * 200 for _ in range(16)] sampling_params SamplingParams(temperature0.8, top_p0.95, max_tokens64) llm LLM( modelfacebook/opt-125m, max_num_batched_tokens8192, max_num_seqs64, enable_chunked_prefillTrue, gpu_memory_utilization0.90, ) outputs llm.generate(prompts, sampling_params) for i, out in enumerate(outputs): print(f[{i}] {out.outputs[0].text[:40]!r})跑的时候盯日志重点看三类信息每步调度的 batch 大小、是否有 preempt 事件、chunk 边界在哪里。如果看到preempt字样说明 KV cache 不够有任务被抢占重算。4.4 调整参数对比抢占频率把max_num_batched_tokens从 8192 降到 2048再跑一次同样的脚本。理论上 batch 变小每轮 KV 需求降低抢占应该减少但 TTFT 会变差。反过来调到 16384TTFT 改善但抢占可能增多。这个对比能让你直观感受到吞吐和延迟的 tradeoff。5. 本篇常见错排查启动报错找不到 chunked prefill 参数确认 vLLM 版本老版本参数名可能是--enable-chunked-prefill或通过EngineArgs传入。V1 引擎默认行为有变化先看版本对应的文档。日志里 preempt 频繁刷屏说明 KV cache 长期不足。优先提高gpu_memory_utilization其次降max_num_seqs。如果模型本身很大考虑开 tensor parallel。chunked prefill 开了但 TTFT 反而变差这是正常 tradeoff。长 prompt 被切块后它的 TTFT 会变大换来的是其他短请求的 ITL 改善。如果你的场景全是长请求、没有并发短请求可以关掉 chunked prefill。统一 Key 请求返回 401检查TAOTOKEN_API_KEY环境变量是否导出成功echo $TAOTOKEN_API_KEY确认非空。Key 的管理和重置在控制台完成接入文档里有鉴权头的完整格式。本地服务和 TaoToken 入口混淆本地推理走127.0.0.1:8000模型对话对照走统一 Key 入口。两者模型名可能相同但后端不同排查问题时先确认请求打到了哪个地址。改了 config.toml 但行为没变vLLM 服务启动参数优先级高于配置文件如果你用命令行传了参数配置文件里的同名字段会被覆盖。统一在一处改。6. 把学习笔记落成可复现配置调度器这块最容易陷入「读源码读懂了但一跑就懵」的状态。我的做法是固定一套配置骨架每次只改一个参数用日志验证行为变化。max_num_batched_tokens和gpu_memory_utilization这两个是最值得反复调的前者直接影响 chunk 切分粒度后者决定 KV cache 池大小和抢占频率。如果你要长期做编码类任务或者搭 Agent建议把统一 Key 的 Coding Plan 用起来把模型调用和本地推理的配置分开管理避免学习环境和生产环境互相污染。接入文档里有完整的参数对照表排障时先查文档再动配置。模型对话入口适合快速验证采样参数API Keys 管理入口负责 Key 的生命周期控制台则是看用量和调额度的地
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。