简介在上一篇中我们沿着一次模型调用认识了输入处理、Prefill、KV Cache、Decode 和输出返回等环节。对于普通的自回归生成模型需要先处理已有输入再利用缓存逐步预测后续 token最后由服务将生成结果转换成文本并返回。但是理解一个请求怎样生成回答还不足以解释多个请求怎样高效地共同运行。假设课程问答系统已经向整个班级开放。学生甲正在等待模型继续生成实验提交要求学生乙又提交了一份实验手册希望模型整理操作步骤过了一会学生丙也提出了一个简短的问题只想确认提交时间。三个请求都需要经历前面介绍的生成过程但它们到达的时间不同输入长度不同所处的计算阶段也不同。此时推理引擎需要解决的问题就变成了怎样让新请求开始计算同时继续推进已有请求并为这些计算保存必要的状态下面以 vLLM V1 的典型 GPU 文本生成服务为例重点观察学生乙的请求。为了便于逐轮分析我们将计算规模缩小假设乙有12 个输入 token丙在第二轮开始前到达有3 个输入 token甲已经进入 Decode并在第二轮计算后结束生成。服务每轮最多安排8 个新 token 的计算最多允许3 个请求参与。这些数字只是教学示例并不代表真实实验手册的长度也不是实际部署参数的推荐值。本节假设模型已经加载三个请求使用同一个模型每个请求只生成一条回答采用保留完整历史 KV 的普通自回归生成方式。暂时不考虑前缀缓存共享、推测解码和多机部署等情况并先假设缓存容量足够。接下来我们不按技术名称分别讨论而是跟着乙的请求从进入服务一直走到结果返回观察请求调度、输入分块和缓存管理怎样在同一个执行过程中相互配合。请求接入与调度2.1 记录请求状态首先在学生乙提交实验手册后应用先整理系统提示词、课程资料和问题再通过 API 客户端向 vLLM 发送请求。服务完成消息格式处理与分词得到模型使用的 token ID然后将请求交给引擎推进。根据我们前面的学习可以知道在 vLLM 的架构中API 服务层负责 HTTP 请求接入、输入处理与结果返回引擎核心负责运行调度器、管理 KV Cache并协调 GPU Worker 执行模型。因此请求被接收并不等于它已经立即开始模型计算。为了让一个请求能够跨越多轮计算引擎还需要持续记录它的状态。例如请求的输入有多长已经处理到哪个位置当前生成了哪些 token以及是否已经结束。vLLM 的请求对象中就包含输入、输出和已计算 token 数等信息。对于刚刚进入的乙可以先将其状态理解为**输入共有 12 个 token已处理 0 个尚未生成回答等待获得计算机会。**这些状态不是额外的业务内容而是引擎后续安排工作的依据。否则即使输入被分成了多轮处理服务也不知道下一轮应该从哪里继续。2.2 连续批处理逐轮调整在乙的输入到达时甲仍然在生成回答也就是在 decode 阶段。如果程序采用“处理完甲的整个请求再处理乙”的方式乙就只能一直等待。即使将多个请求提前组成一个固定批次只要必须等这个批次全部结束才能加入新请求仍然会出现类似的问题。但是前面已经知道甲的回答是通过多轮计算逐步生成的。因此推理引擎可以将安排工作的时机从“整个请求结束以后”细化到“准备下一轮模型计算时”。这种以迭代为单位重新安排任务的思路使新请求不必始终等待当前批次全部完成。例如下一轮可以继续推进甲的 Decode同时开始处理乙的输入。甲不需要让出整个生成任务乙也不需要等甲的整段回答全部结束。这种在执行过程中持续调整批次成员让新请求加入、让已完成请求退出的机制就是连续批处理Continuous Batching。在 vLLM 中它通过调度器与模型执行循环共同实现而不是请求需要额外经过的一个处理阶段。这里的“加入”发生在后续计算安排中不是把新请求临时插入一个已经运行到一半的 GPU 算子。调度器仍然需要先形成一份明确的执行安排再交给模型执行。因此乙进入服务后首先获得的是一种新的可能性**不必等待甲完成整个请求而是等待资源允许的某一轮计算。**不过能够加入并不等于乙的全部输入都应该一次处理完。接下来还需要决定这一轮究竟给乙安排多少计算2.3 分块 Prefill按预算推进假设本轮最多安排 8 个新 token 的计算。甲已经进入 Decode在本节讨论的普通逐 token 生成过程中需要处理刚刚生成的 1 个 token。为甲安排这一步后本轮还剩下 7 个 token 的预算。乙有 12 个输入 token因此可以先处理其中的 7 个将剩余 5 个留到后续轮次。本轮安排可以概括为甲Decode 1 个 token乙Prefill 7 个 token合计 8 个 token。这里的“8 个 token”指的是本轮新送入模型处理的位置数量既可以包含输入中的 token也可以包含此前刚刚生成、现在需要继续处理的 token。它不代表本轮一定生成 8 个回答 token也不包括将历史 KV Cache 中的所有位置重新计算一遍。在 vLLM 中max_num_batched_tokens等配置用于限制一次迭代的处理规模max_num_seqs则限制一次迭代中处理的序列数量。在本节每个请求只生成一条回答的场景中可以将后者理解为本轮参与计算的请求数量上限。将同一个请求的 Prefill 分成多个部分根据预算安排到不同轮次中完成就是分块 PrefillChunked Prefill。vLLM 的优化文档描述了一种典型安排优先推进待执行的 Decode再利用剩余预算处理 Prefill如果输入无法全部放入本轮预算就只安排其中一部分。这样甲可以继续生成乙也能开始处理输入而不是为了处理乙的长输入让其他请求长时间得不到推进。需要注意这里的分块不是将实验手册拆成几个独立问题。乙仍然只提交了一次请求后续各块也必须接着前面的计算状态继续处理。至此调度器已经将两种机制结合起来了**连续批处理让乙能够加入分块 Prefill 则让调度器控制乙加入后这一轮推进多少。**但这份计算安排还需要满足另一个条件计算产生的 K、V必须有地方保存。首轮计算与缓存3.1 检查计算与缓存条件乙本轮准备处理 7 个输入 token。模型在各注意力层计算这些 token 时会产生后续还要使用的 K、V。如果没有足够空间保存这些结果后面的输入处理和生成就无法按预期继续推进。因此调度器不能只检查 token 预算还需要与KV Cache 管理器配合检查请求已有的缓存容量并按需申请新的缓存位置。vLLM 的缓存管理接口会根据请求及本轮新增 token 数为计算提供相应的存储槽位。这意味着所谓“本轮安排乙处理 7 个 token”实际上包含了两项相互关联的判断这一轮是否有足够的计算预算处理它们这一轮是否有足够的缓存空间保存它们产生的状态如果第一项满足第二项不满足这份安排仍然不能直接执行。调度器可能需要减少本轮接纳的工作或者让部分请求继续等待。于是问题进一步落到了缓存怎样管理这些空间是否容易分配后续增长时是否容易扩展请求结束后是否容易重新利用3.2 PagedAttention分页缓存假设采用一种简单方式每个请求进入后都为它预留一整段连续的 KV Cache 空间。如果预留得很大请求最后却只生成很短的回答就会有较多空间未被使用如果预留得较小后续缓存增长时又需要考虑如何扩展。多个请求不断加入和结束还可能使空闲空间分散形成不容易利用的碎片。这类空间浪费会限制能够同时运行的请求数量。PagedAttention 所针对的就是动态增长的 KV Cache 在分配与访问方面的问题。PagedAttention 的关键思路是让一个请求的 KV Cache 按固定大小的块组织并允许这些块存放在不连续的物理位置。请求通过映射关系找到各块注意力计算再根据这些映射访问需要的 K、V。这样就不必要求每个请求始终占据一整段连续区域。为了观察这一过程假设每个缓存块可以容纳4 个 token 对应的 K、V 数据。实际模型会在相应注意力层维护缓存这里将它们统一简化为“每个块容纳多少个位置”。乙本轮准备处理 7 个输入 token至少需要两个这样的块。可以安排为乙的逻辑块上下文位置物理块首轮写入逻辑块 0第 14 个位置物理块 7第 14 个输入 token 的 K、V逻辑块 1第 58 个位置物理块 2第 57 个输入 token 的 K、V第 8 个位置暂空从乙的上下文顺序看前 7 个输入仍然按照原来的次序排列但在物理存储中相关数据分布在物理块 7 和物理块 2。乙的**块表Block Table**记录了“逻辑块 0 对应物理块 7、逻辑块 1 对应物理块 2”。因此物理位置不连续并不意味着上下文顺序被打乱。这里讨论的是一种按需分配的简化过程。实际引擎还可能提前预留部分空间示例中的块数用于说明存储需求与增长关系不是某个具体版本的运行日志。3.3 执行计算并写入 KV完成空间安排后缓存块中并不会自动出现正确的 K、V。分配空间与产生计算结果是两件不同的事情。接下来由 GPU Worker 及模型执行组件处理本轮任务甲执行一次 Decode乙处理前 7 个输入 token。模型权重已经加载完成不需要因为乙加入就重新加载一份模型。对于甲模型使用甲自己的历史缓存处理它最新生成的 token。而对于乙模型按照乙的输入位置执行 Prefill并将产生的 K、V 写入刚才准备好的位置。执行组件除了需要知道“这轮有哪些 token”还需要知道它们属于哪个请求、位于各自上下文的什么位置以及应该读写哪些缓存区域。因此多个请求共同参与计算不等于将它们拼成一段共同对话。甲与乙使用同一个模型但各自的序列边界和缓存映射仍然保留。注意力计算按照这些信息访问各自的上下文。从资源利用的角度看组织更多有效工作共同执行有机会改善单个请求逐 token 生成时计算规模较小的问题。但这不意味着批次越大越好也不意味着混合计算完全没有相互影响。不同请求仍然共同承担本轮执行的耗时。因此在第一轮完成后乙的状态变为12 个输入 token 中已经处理 7 个还剩 5 个前 7 个输入对应的 KV Cache 已经建立但尚未完成输入处理不能开始正式回答。到这里三个机制已经作用在同一项任务上调度器让乙加入并为它安排部分输入缓存管理器提供相应块GPU 按映射执行计算并保存状态。执行结果随后又成为下一轮调度的依据。Prefill 阶段4.1 重新安排第二轮第二轮开始前学生丙提交了一个简短问题。完成输入处理后丙共有 3 个输入 token 等待计算。此时甲仍然需要继续生成乙还有 5 个输入 token 尚未处理丙则刚刚进入等待状态。调度器不需要继续沿用上一轮的请求组合而是根据新的请求状态和资源条件形成下一轮安排。在本例中可以安排为甲Decode 1 个 token乙Prefill 5 个 token丙Prefill 2 个 token合计 8 个 token。这一轮乙能够完成剩余输入丙也开始获得计算机会。丙的输入虽然较短但本轮剩余预算只有 2因此仍然有 1 个 token 留到下一轮处理。这说明Chunked Prefill 的分块大小不一定提前固定也不要求每块都一样长。同一个请求这一轮处理多少可以随其他请求的状态和剩余预算变化。vLLM V1 可以用“请求 ID → 本轮处理 token 数”的形式表示这样的调度安排。调度器并不是先单独执行一次“连续批处理”再执行一次“输入分块”。在形成这一份安排时它已经同时决定了参与者与各自的计算量。4.2 按需增加缓存块乙第一轮已经处理了 7 个输入 token。在每块容纳 4 个位置的示例中第一个块已经填满第二个块还剩一个空位。现在乙要继续处理第 812 个输入 token。其中第 8 个位置可以使用第二个块中剩余的空间第 912 个位置则需要增加一个新的缓存块。假设新分配的是物理块 12那么乙的块表就可以扩展为逻辑块 0 → 物理块 7逻辑块 1 → 物理块 2逻辑块 2 → 物理块 12。此前保存的数据不需要为了保持连续而搬到另一块更大的区域。新块可以来自其他空闲位置已有块仍然保留原来的内容。这样的按需扩展正是分页式管理支持持续生成的方式。同时也要看到PagedAttention 并没有压缩每个 token 本来需要保存的 K、V 数据。它主要改善的是空间如何分配和利用而不是让相同上下文所需的计算状态凭空减少。对于本轮调度来说它提供的支持非常具体乙可以在保留前 7 个输入计算结果的情况下为后面 5 个输入继续取得存储位置。4.3 接续上下文计算缓存位置准备完成后乙开始处理第 812 个输入 token。这时模型不会把它们当成一段全新的、只有 5 个 token 的输入。前 7 个输入已经形成的 K、V 仍然保留后面的输入会结合这些历史结果继续计算。这里除了缓存内容还需要保持正确的位置信息。第 8 个输入仍然位于原上下文的第 8 个位置不能因为它被安排到新一轮就重新当作第 1 个位置。缓存位置的管理正是为了让后续 token 接着已经处理的上下文继续推进。因此分块 Prefill 并不是简单地“把文本分段送进去”。它需要同时保留同一个请求的身份、已经完成的计算状态以及后续 token 在原上下文中的位置。这也解释了它与 KV Cache 的关系如果不保留前面已经完成的状态后续就可能需要重新计算此前的输入失去按轮次接续执行的意义。需要注意复用历史缓存不代表这一轮只看后面的 5 个 token。它们仍然需要利用前面的上下文只是通过已有 K、V 继续参与注意力计算而不是重新生成历史位置的 K、V。4.4 选出首个输出 token当第 812 个输入 token 处理完毕后乙的完整输入已经参与模型计算。接下来可以根据最后一个输入位置的预测结果选择第一个输出 token。更具体地说模型前向计算先产生对候选 token 的预测分数再依据生成策略进行选择。例如可以选取分数最高的 token也可以按照相应的概率分布采样。最后得到的仍然是token ID而不是已经排版好的中文回答。假设乙选出的第一个输出 token ID 是645。这里的数字仅用于观察数据流不指定它在某个真实分词器中的文字含义。此时需要区分两个结果一方面12 个输入 token 对应的 KV Cache 已经建立另一方面第一个输出 token645刚刚被选出。645自身的 K、V 还没有因为“被选出”就自动产生。它需要在下一轮作为新输入送入模型后才会形成自己的计算状态。这时如果采用流式返回服务已经可以开始处理当前可输出的内容但只要尚未满足停止条件乙仍然需要继续参与后续调度。得到第一个输出 token不是引擎调度的终点而是这个请求开始进入 Decode 的位置。Decode 阶段5.1 资源释放按照示例设定甲在第二轮计算后结束生成。此时乙已经获得第一个输出 token丙还有 1 个输入 token 尚未处理。下一轮可以调整为乙Decode处理645丙Prefill处理剩余 1 个输入 token甲不再参与。甲退出后不仅不再占用后续计算名额它所占用且不再被引用的缓存块也可以重新进入可分配状态。vLLM 的缓存池会通过引用计数和空闲块管理支持这些块的回收与再次分配。这时连续批处理与缓存管理的配合就更加直接了即调度器将甲移出后续计算缓存管理器让甲的可回收空间重新可用下一轮安排再依据更新后的资源条件形成。如果只调整批次成员却不回收不再需要的缓存服务仍然可能因空间不足而难以接纳新任务。反过来如果缓存已经可用但执行方式仍然要求等待固定批次全部结束新请求也可能继续等待。因此请求退出、缓存回收和后续任务加入是同一个循环中的连续变化。5.2 复用缓存继续生成第三轮开始时乙已有 12 个输入 token 对应的缓存。模型将645作为新的输入通过乙的缓存映射读取前面 12 个位置的 K、V结合当前 token 继续计算。处理645时产生的新 K、V也要保存下来随后再选出下一个输出 token。假设下一个输出 token ID 是822这一步可以理解为**处理645复用已有 KV → 保存645对应的新 K、V → 选出822。**这里仍然存在同样的先后关系这一轮被送入模型的是645所以新增的是645的缓存822只是本轮刚选出的结果需要下一轮再处理。在缓存容量方面乙此前已经保存 12 个输入位置正好占满 3 个块。现在需要保存第 13 个位置因此执行前需要再准备一个缓存块。假设缓存管理器分配了物理块 5那么乙就可以将645对应的 K、V 写入这个新块的第一个位置。这个块可以来自缓存池中的其他空闲区域也可以来自甲结束后回收的资源不必与乙原有的块相邻。所以这一轮并不是“调度器在调度、PagedAttention 在做另一件事”而是**调度器决定乙处理645缓存管理器为新增状态提供位置模型执行组件再按照映射读取历史缓存并写入新结果。**三者围绕同一次计算协同完成工作。5.3 缓存增长与块分配第三轮完成后乙已经得到822丙也完成了输入处理并得到自己的第一个输出 token。而到了第四轮乙和丙都可以进入 Decode。对于乙模型处理822复用已有缓存继续选择下一个 token例如415。此时乙的缓存从 13 个位置增加到 14 个位置。但第四个缓存块中还有空位所以不必再次分配新块只需要在已有容量中写入新增结果。每处理一个新 token缓存内容可能继续增长只有现有容量不足时才需要扩展新的物理块。将前四轮放在一起可以得到下面这张表。表中的缓存块数按照每块容纳 4 个位置计算只表示本例的最低容量需求。轮次本轮安排乙输入进度乙输出 ID乙缓存位置块数第 1 轮甲 Decode 1乙 Prefill 7712尚无输出72第 2 轮甲 Decode 1随后结束乙 Prefill 5丙 Prefill 21212645123第 3 轮乙 Decode 1丙 Prefill 11212645, 822134第 4 轮乙 Decode 1丙 Decode 11212645, 822, 415144可以看到请求组合、每轮输入量、输出 token 和缓存容量是在同一条执行时间线上共同变化的。乙的输入跨两轮完成之后又通过多轮 Decode 持续生成甲的结束影响了后续批次成员也改变了缓存池的可用资源丙则在乙尚未回答完时就开始并完成了自己的输入处理。这里的共同计算也不是让一个请求一次生成多个尚未知晓的 token。在普通自回归生成中每个请求仍然遵守自身的先后依赖只是不同请求的当前工作可以组织在一起执行。5.4 预算不必用满虽然第三轮和第四轮都只处理了 2 个新 token没有用满 8 个 token 的预算。但是这不意味着调度错误。预算是允许安排的上限不是每轮必须完成的指标。此时乙和丙各有一个新 token 等待处理不能为了凑满 8 个就让普通自回归模型提前处理尚未生成的未来 token。同样有剩余 token 预算也不代表一定能够继续接纳请求。如果缓存条件不满足请求仍然可能需要等待。对于分块 PrefillvLLM 还可以在接纳新请求时检查完整输入是否能够容纳而不只是检查第一小块能否放下以避免过度接纳造成缓存反复紧张。这里还需要注意token 预算并不是严格的时间预算。不同上下文长度、不同阶段和不同批次组合可能产生不同的执行耗时。因此Chunked Prefill 的分块并不是越小越好。较小的块能够限制长输入在单轮中带来的工作量但也可能增加执行轮次较大的块能够更快推进输入却可能拉长其他请求等待下一次输出的时间。实际需要在输入处理、持续生成和整体处理能力之间权衡。本节的示例重点展示这种安排怎样发生并不能仅凭轮次数量或 token 数量直接推算实际加速倍数。流式返回与回收6.1 计算与流式返回并行前面主要观察了调度器、模型执行和缓存的变化。但对于乙来说第二轮得到第一个输出 token 后服务就已经可以开始处理已有输出而不必等到所有 Decode 全部结束。模型产生的是 token ID。服务需要使用分词器进行反分词Detokenization将这些编号转换成可读文本再按照接口格式组织响应。这个步骤处理的是已经生成的结果不会再次运行模型去重新组织答案。如果采用流式返回后续每当有新的可输出内容服务就可以继续发送增量结果应用接收后更新页面。一次返回的文本片段不必恰好对应一个 token实际输出还会受到反分词、缓冲及服务配置的影响。因此运行到这里服务并不是简单地“模型全部算完再开始处理网络返回”而是可以一边推进后续计算一边处理已有输出。vLLM V1 将 API 服务与引擎核心等工作分开组织使分词、反分词和流式响应等处理有机会与核心执行循环重叠减少这些外围工作对模型执行的阻碍。对于应用来说乙仍然只有最初的那一次调用。它不需要为了获得822或415再发送新的请求也不需要接收和管理服务内部的 KV Cache。这里需要区分两种“复用”模型内部复用 KV Cache是为了减少重复计算应用持续接收同一次请求的响应则是结果交付方式。两者发生在同一个生成任务中但承担不同职责。6.2 请求结束与资源回收当乙生成结束标记、匹配指定停止内容或者达到最大输出 token 数时服务会根据相应条件结束这次生成。应用除了读取文本也应关注结束原因因为达到长度上限时回答可能尚未完整表达。引擎确认乙不再需要继续执行后就不再为它安排后续 Decode。其可回收的缓存块也会重新变为可分配资源供丙或其他新请求使用。这里的“归还”主要指归还给推理引擎内部的缓存池。在预分配缓存池的配置下请求结束后可用块数量可以增加但模型进程整体占用的显存不一定立即下降。因此一个请求完成后发生的不只是“用户收到答案”还包括服务内部的一次资源更新计算任务减少了可用缓存增加了等待中的请求又可能获得新的执行机会。乙的一次调用到这里结束但引擎的循环仍然继续根据新状态安排下一轮执行模型更新缓存与请求再继续安排后续工作。总结沿着学生乙的请求可以看到vLLM 并没有改变“先处理输入再逐步生成回答”的基本过程而是进一步解决了这个过程怎样在多个请求之间灵活安排怎样获得必要的缓存支持以及怎样将完成后的资源继续用于其他任务。乙刚刚进入时调度器可以将它加入后续计算不必等待甲的整段回答结束这体现了连续批处理。安排乙的输入时又可以根据本轮预算先处理一部分这体现了分块 Prefill。为了执行这些工作缓存管理器需要提供相应的存储位置模型则依据分页映射读写 KV Cache。执行结束后输入进度、输出结果和缓存使用情况又共同影响下一轮调度。因此更符合运行逻辑的主线是请求进入 → 根据状态安排本轮参与者与计算量同时确认缓存条件 → 执行模型并读写缓存 → 更新状态、处理已有输出 → 继续下一轮 → 请求结束后回收资源。Continuous Batching、Chunked Prefill 和 PagedAttention 并不是这条链上三个互不相关的步骤。连续批处理使参与者能够变化分块 Prefill 使计算量能够分轮安排分页式缓存管理与访问则支持这些变化持续执行。它们在同一轮任务中相互配合也会在后续轮次中反复发挥作用。还需要保留一个边界KV Cache 的计算复用本身不是 vLLM 独有的能力分页管理也不会让显存容量变得无限。这些机制希望减少的是不必要的等待、过大的单轮输入计算以及缓存预留和分配中的浪费而不是保证所有请求在任何条件下都同时变快。理解了这一过程后续再学习部署配置与性能评估就能把参数和现象对应起来限制每轮 token 数影响的是计算安排调整请求数量上限影响的是参与规模改变缓存容量影响的是哪些任务能够被接纳和持续推进。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】