vLLM学习1

调用方式

一、vLLM 提供的两种调用方式

1. Offline Batched Inference(离线批处理)

  • 调用特点:一次性传入一批(batch)的请求,等待所有请求都处理完毕后,一次性返回推理结果。对用户而言,这是一个同步的过程:只有当这一批所有数据都推理完成,用户才能拿到结果。

  • 示例代码(基于vLLM官方示例):

    from vllm import LLM, SamplingParams# 1) 组织batch数据
    prompts = ["Hello, my name is","The president of the United States is","The capital of France is","The future of AI is",
    ]# 2) 采样参数
    sampling_params = SamplingParams(temperature=0.8, top_p=0.95)# 3) 初始化离线批处理实例,并加载指定模型
    llm = LLM(model="facebook/opt-125m")# 4) 推理
    outputs = llm.generate(prompts, sampling_params)# 5) 打印结果
    for output in outputs:print(f"Prompt: {output.prompt!r}, Generated text: {output.outputs[0].text!r}")
    
  • 背后原理

    1. 表面上是同步:用户会一次性提交一批请求(batch),等待所有请求都推理完成再返回。
    2. 实际上是“动态”:vLLM的核心引擎(LLMEngine)内部会根据当前GPU显存的使用情况,对batch做“动态”调度。在一个推理阶段(prefill或一次decode)里,如果显存无法容纳所有请求,vLLM会先让部分请求进入“running队列”,剩下的请求留在“waiting队列”里等待。
    3. 多阶段推理:当某些请求在一次推理阶段完成或结束(生成了结束符或达到最大长度),它们就会释放所占用的显存块。这样下一批等待的请求就能进入“running队列”,继续下一阶段推理。
    4. 对用户而言是透明的:用户只看到自己提交了一个batch,等所有结果都处理完后才拿到输出;但在内核引擎中,这个batch可能被分拆成多个子批次进行推理。

2. API Server For Online Serving(在线服务)

  • 调用特点:采用异步方式处理请求,随时可以接收新请求、并行处理多个请求;已完成的推理结果可以先行返回给客户端(尤其配合流式传输时,可以边生成边返回)。

  • vLLM 提供了两种在线API:

    1. OpenAI-Compatible API Server(官方推荐):兼容OpenAI的Completions和Chat API协议,使用方式与OpenAI API相同。
    2. Simple Demo API Server(官方已不再维护):仅适用于简单测试,不推荐在生产环境使用。
  • 示例命令

    (OpenAI-Compatible API):

    # 1) 启动服务
    python -m vllm.entrypoints.openai.api_server --model meta-llama/Llama-2-7b-hf# 2) 用curl发送请求(OpenAI风格)
    curl http://localhost:8000/v1/completions \-H "Content-Type: application/json" \-d '{"model": "meta-llama/Llama-2-7b-hf","prompt": "San Francisco is a","max_tokens": 7,"temperature": 0}'
    
  • 背后原理:

    1. 异步化处理:vLLM使用uvicorn + fastapi 实现一个异步服务器,内部封装了 AsyncLLMEngine
    2. 排队 + 调度:当多个请求同时到来,vLLM会先将请求放入一个异步队列,然后在内部调度器(Scheduler)的管理下,将请求动态加入“running队列”进行推理。
    3. 先完成先返回:只要有请求在当前推理阶段完成,就可以立即把结果返回给客户端,不需要等待其他请求一起结束。若开启流式输出,还能在生成过程中分段发送token给客户端。
    4. 同样使用PagedAttention:在线服务依然会利用PagedAttention进行显存优化;当显存不足时,还会做部分数据的swap到CPU或暂时排队等待,以提升吞吐。

二、LLMEngine:vLLM的内核引擎

img

无论是离线批处理还是在线服务,都依赖于同一个核心组件——LLMEngine。它的主要功能包括:

  1. add_request()
    • 将每个请求转换成vLLM内部的统一数据结构(如SequenceGroup),并加入调度器(Scheduler)的waiting队列中。
    • 离线批处理场景下,这个函数是“同步式”的:会依次处理batch中的各条数据。
    • 在线场景下,会被重写为异步版本(AsyncLLMEngine),以便在协程中对每个请求进行处理。
  2. step()
    • 执行一次推理阶段(prefill算1次推理,decode的每一步也算1次推理)。
    • 调度器(Scheduler)决定哪些请求可以进入“running队列”,并为它们分配所需的显存块(Physical KV blocks)。
    • 模型(带有PagedAttention)根据这些分配信息执行推理,生成新的token并更新KV缓存。
    • 如果有请求在本次推理阶段完成(如达到或其它终止条件),则释放对应显存块,并将该请求从running队列中移除。
  3. abort_request()
    • 如果在推理过程中客户端断开连接,或用户取消了请求,可以调用此方法中断推理,释放对应资源。

总结:只要理解了 add_request()step() 这两个函数的核心逻辑,就掌握了LLMEngine的大部分精髓。它们背后涉及到很多“排队、调度、显存分配、PagedAttention”的复杂逻辑,源码中会有大量的封装与嵌套。


三、离线批处理与在线服务的内核差异

  1. 离线批处理
    • 对用户来说:一次性输入所有数据 -> 一次性得到全部输出。
    • 对LLMEngine来说:内部依然是“动态批”调度,不断有请求完成并释放显存,再让新的请求进来,但对用户是不可见的,属于“内部黑箱”。
  2. 在线服务
    • 对用户来说:随时可以发送请求;完成的结果可以第一时间返回。
    • 对LLMEngine来说:依旧是同一个调度器;不同在于用户随时可能发来新请求或断开已有请求,因此需要用异步队列、异步I/O的方式处理。
    • 核心思路相同:都是把请求排队 -> 等到一个推理阶段到来时,把合适数量的请求放入“running队列” -> PagedAttention完成这批的计算 -> 释放已完成请求的显存 -> 重复。

代码整体架构

img

这张图展示了 vLLM 内部代码整体架构,可以把它拆分为“中央控制端(Centralized Controller)”和“分布式Worker”两大部分。LLMEngine 就位于中央控制端的进程里,负责调度和管理请求,而真正的模型推理(包括PagedAttention等核心逻辑)会在一个或多个分布式Worker进程上执行(每个GPU对应一个Worker)。以下是对各模块的更详细解读:


一、LLMEngine 与 Centralized Controller

这部分都在同一个CPU进程中(如图中左侧所示),它包含了:

  1. LLMEngine(vllm/engine/llm_engine.py)
    • 这是用户直接调用的接口层,用于接收请求(prompt)并将其转给调度器进行处理。
    • LLMEngine本身并不直接执行推理,而是协调Scheduler、BlockSpaceManager等组件,并通过网络或进程通信,把模型计算任务发送给下游的Worker进程。
  2. Scheduler(vllm/core/scheduler.py)
    • 调度器:决定每一个“推理阶段”(如prefill或decode的某一步)要处理哪些请求,并且以什么方式把这些请求打包交给Worker来执行。
    • 当有多个请求或多个batch同时到来时,Scheduler会根据显存使用情况和优先级策略决定如何将它们安排到running队列、waiting队列或swap到CPU内存。
    • 在运行完某个阶段后,如果有请求产生了新token或已经完成推理,就相应地更新这些请求的状态并做后续处理(例如释放显存块)。
  3. BlockSpaceManager(vllm/core/block_manager.py)
    • 块空间管理器:负责管理所有token KV缓存的“块”在显存/内存中的分布情况,以及它们的生命周期。
    • 它会与调度器配合,决定在每个推理阶段,需要为哪些请求分配新的缓存块或回收哪些已经不再使用的块。
  4. BlockAllocator(vllm/core/…)
    • 显存/CPU分配器:将具体的物理内存(包括GPU显存、CPU内存)分配给BlockSpaceManager所需要的KV缓存块。
    • 当GPU显存不足时,可能将部分块swap到CPU,以腾出空间给新的请求。
    • 对应地,BlockSpaceManager会记录块在GPU上或CPU上,并在需要计算时重新把块拉回GPU。

总结:Centralized Controller进程中,LLMEngine是对外的“门面”,Scheduler是核心的调度大脑,BlockSpaceManagerBlockAllocator则负责管理KV缓存块在不同硬件介质间的具体分配和回收。


二、Distributed Workers(分布式Worker 进程)

如图中右侧部分所示,vLLM可以在分布式环境中使用,每个Worker通常对应一块GPU(也可在CPU模式或Ray模式下运行)。当前版本主要是单主机多GPU的场景,后续可能扩展为更多分布式方案。下列是Worker内部的关键组件:

  1. Worker(vllm/worker/worker.py)
    • Worker是一个进程,里面包含了CacheEngineWorker.model等对象。
    • 当Centralized Controller决定某些请求要进行推理时,就会将这些请求对应的KV块和输入数据传给某个Worker,由它执行模型计算并返回结果(新token、注意力分数等)。
  2. CacheEngine(vllm/worker/cache_engine.py)
    • 负责与PagedAttention配合,在Worker本地对KV缓存进行读写操作。
    • 当收到Scheduler的指令后,CacheEngine会根据请求发送的数据ID或位置,把对应的KV块取出来(或者新建)并调用PagedAttention进行推理中的注意力计算。
  3. Worker.model(vllm/model_executor/models/…)
    • 真正加载了大语言模型权重的模块。
    • 当需要进行前向推理时,Worker调用它来计算每一步生成所需的logits、隐层状态等,内部再调用PagedAttention的相关逻辑做注意力机制。
  4. PagedAttention(vllm/model_executor/layers/…)
    • 在Worker的模型层中具体实现的“分页/分块式注意力”机制。
    • 它将传统的KV缓存细粒度地切分为多个Block,并在计算注意力时只加载、更新相关Block,避免重复计算和显存浪费。
    • 与CacheEngine、BlockAllocator共同配合,实现动态地分配、回收和复用KV缓存。

总结:分布式Worker相当于是实际执行大模型推理的“工作站”,里面包含模型缓存管理等功能,通过PagedAttentionCacheEngine实现对KV缓存的高效操作。每个Worker与中央控制(Scheduler)相互通信,将请求对应的工作内容取过来执行,然后返回结果。


三、集中式调度 + 分布式推理 的好处

  1. 统一调度,简化架构
    • 由于Scheduler和BlockSpaceManager都在主进程上进行集中管理,减少了多GPU之间的“谁分配什么资源” 的冲突和协商开销。
    • Worker只需专注于执行分配到的计算任务,无需关心整体系统状态。
  2. 灵活的显存管理
    • Centralized Controller可以全局掌握所有请求与所有GPU/CPU的使用情况,做全局调度;比如当某块GPU显存满了,可以直接把部分KV块swap到CPU或调度到其他GPU。
    • Worker仅保留自己当前需要用到的块,剩余部分由BlockAllocator/BlockSpaceManager在后台统一管理。
  3. 扩展为多Worker
    • 如果单GPU算力不足,可增加多个Worker进程,每个进程对应一块GPU或一组GPU,分担推理工作。
    • 在后续版本中,vLLM也有望支持更多分布式策略(如TP/PP并行),进一步提升推理吞吐。

四、代码阅读指南

  • vllm/engine/llm_engine.py
    入口:LLMEngineAsyncLLMEngine。用户调用接口层,和Scheduler/BlockSpaceManager配合完成推理。
  • vllm/core/scheduler.py
    核心调度逻辑所在,负责推理阶段的决策,让哪些请求进入执行队列、哪些swap到CPU等。
  • vllm/core/block_manager.py & vllm/core/block_allocator.py
    管理KV缓存块的创建、删除、swap和引用计数。
  • vllm/worker/worker.py
    定义Worker进程的核心流程,包括接受任务、调用模型执行、返回结果。
  • vllm/worker/cache_engine.py
    在Worker侧管理KV缓存块的读写与paged attention计算对接。
  • vllm/model_executor/
    这里存放模型相关的执行逻辑与PagedAttention的实现。

加载模型与预分配显存

下面的内容主要围绕 vLLM 在正式启动推理服务前,会做的两件初始化工作:

  1. 加载模型(将大模型权重加载到 Worker 上)
  2. 预分配显存(在 GPU/CPU 上提前创建一批 KV Cache 块)

这样,当真正有请求(prompt)到达时,vLLM 就能直接使用这些预分配好的缓存块,而无需在推理过程中再做大规模内存申请或分配,极大提高了服务的启动效率和稳定性。下面会分步骤为你详细讲解其中原理和流程。


一、加载模型

1.1 加载的时机与方式

  • 时机:在 vLLM 正式开始处理第一个请求之前,就会先把你指定的基础模型(base model)加载到 Worker 进程中。

  • 方式:默认情况下,vLLM 使用 HuggingFace 模型仓库(Model Hub)来下载并加载对应的模型权重。

    • 如果你在使用在线加载方式,只需在启动参数或环境变量中指定相应的模型名称(如 "facebook/opt-125m""meta-llama/Llama-2-7b-hf" 等),vLLM 便会从 HuggingFace 上自动拉取权重并初始化。
    • 也可以通过设置环境变量,把默认源改为其他仓库(如 ModelScope)。

    img

1.2 多 Worker 环境下的加载

  • 每个 Worker(对应一块 GPU 或者 CPU 进程)会各自加载同一份基础模型权重到本地显存或内存中。
  • 当进入推理阶段时,Worker 就可以直接对这些已加载好的模型权重做前向计算(forward),结合 PagedAttention 完成生成任务。

提示:如果模型比较大,加载过程会消耗一定时间和显存。为保证服务稳定,通常你会先在所有 Worker 上完成加载,然后才开始对外提供推理 API。


二、预分配显存

在模型加载完成后,vLLM 还会进行一次“模拟实验”或“内存探测(profile)”,借此估算自己能创建多少 KV Cache 物理块,并为后续真正的推理分配足够的缓存空间。图示中称之为 “Before serving requests - 2. Profile memory usage” 和 “3. Pre-allocate KV blocks”。

2.1 为什么要预分配?

  • 减少推理时的分配开销:如果把创建 KV Cache 的操作放到推理进行时才做,大规模的内存分配可能导致延迟抖动或显存碎片。
  • 让调度器(Scheduler)更好工作:调度器需要知道 GPU/CPU 剩余多少块可以使用,才好动态决定将多少请求同时放到“running队列”里。
  • 便于发现配置或显存不足问题:如果你给定的 max_num_seqsmax_num_batched_tokens 太大,导致需要分配的 KV Cache 块数量远超 GPU 真实承受能力,vLLM 能在初始化时就发现并报错,而不是推理时才崩溃。

2.2 关键参数

初始化 LLMEngine 时,用户通常会提供两个重要的配置项:

  1. max_num_seqs
    • 在一个推理阶段里,vLLM Engine 最多能处理的序列(seq)数量。
    • 默认为 256,意味着同时处理 256 条请求(或 256 条不同的上下文)是上限。
  2. max_num_batched_tokens
    • 在一个推理阶段里,vLLM Engine 最多能处理的 token 数量。
    • 默认为 2048,表示同时会处理的 token 数总量上限。

vLLM 会据此来估计:如果在一个推理阶段,有多条请求,每条请求的序列长度合计多少 token,需要大概多少块 KV Cache,GPU/CPU 能否容纳得下。

2.3 计算分配给 KV Cache 的总显存

在做内存 profiling 的过程中,vLLM 会先用一批“虚拟请求”来做一次假想的前向推理(prefill 或 decode),测量不使用 KV Cache时模型本身的显存占用是多少(包括模型权重 + 中间激活等)。然后再去算:

分配给KV cache显存 = gpu总显存 - 不使用KV cache做1次推理时的显存占用(包括模型本身和推理过程中的中间数据)

这一步相当于先排除模型必需的显存占用后,看看还剩多少“空闲”容量可以用来分配 KV 缓存。

2.4 计算每个 KV Cache 块的大小

  • block_size
    每个物理块包含多少个 token 的 KV 内容(vLLM 默认是 16 个 token)。
  • 其它参数
    包括 Transformer 层数、head 数、head_size 以及数据类型(fp16/fp32)等等。
  • 最终会得到类似这样一个公式:

KaTeX parse error: Expected 'EOF', got '_' at position 13: \text{cache_̲block_size} = \…

其中“ × 2 \times 2 ×2”是因为在多数实现里 KV 是分开存储的(Key 和 Value 都需要分配)。如果是 fp16(dtype_size=2 bytes),则还要代入这个数。

2.5 计算可分配的总块数

一旦知道可分配给 KV cache 的总显存单块大小,就能算得总块数
KaTeX parse error: Expected 'EOF', got '_' at position 11: \text{num_̲blocks} = \frac…

对于 CPU 端同理,只不过 CPU 内存通常比较大(默认上限可能写成 4GB、8GB 或用户自定义),可以用类似的逻辑算出可分配的块数(当 GPU 空间不够时,Scheduler 会把一部分块 swap 到 CPU)。

2.6 在 GPU 上创建预分配的空 Tensor

img

最后,vLLM 会调用类似 BlockAllocator._allocate_kv_cache() 这样的函数,在 GPU 或 CPU 上逐层(num_layers 次)创建这些空张量(torch.empty(...)),并将它们存放到一个列表里,组成 “KV Cache” 池。

  • 这些空张量就相当于分割好的“片段”,每个分片能容纳一部分 token 的键值对。
  • 当有新请求到来,需要一个 block 时,BlockManager/BlockAllocator 只要把一个空闲块分配给它,无需再进行张量创建。

优点

  • 减少了运行时的 Fragmentation(碎片化)风险。
  • 可以快速映射到调度策略,让 Scheduler 知道当前空闲块、在用块、swap 块的数量与位置,进行更精细的管理。

三、预分配带来的好处与注意点

  1. 启动后显存占用“突增”是正常现象
    • 由于 vLLM 把一部分空张量提前开辟好了,你可能会看到 GPU 显存一下子就用掉了相当大比例。但这些张量实际是空数据,只是占位;真正放入 Token KV 时才会写入内容。
  2. 参数调得过大可能导致 OOM
    • 如果你指定的 max_num_seqsmax_num_batched_tokens 太高,而 GPU 显存不足,vLLM 在初始化时就会报错或内存不足的问题,而不是推理时才发现。
    • 这其实是个安全机制,让你知道当前配置不可行。
  3. 调度器与预分配
    • 一旦 KV block 预分配完毕,Scheduler 就能准确地知道有多少块可用,并且在推理阶段分配/回收这些块给不同请求。如果用完了,新的请求就只能等,或者把不活跃的块swap到 CPU。
  4. 可能影响多进程部署
    • 在多进程(或多容器)中部署时,各自进程都要预分配一份 KV cache,会进一步增加显存占用,需要格外留意调优。

四、小结

  • 加载模型:先把大模型的权重加载到每个 Worker 上,保证 Worker 拥有完整的计算能力。
  • 预分配显存:
    1. 内存测量:通过一次模拟推理,估计模型本身占用多少显存,并计算剩余可用于 KV cache 的空间;
    2. 计算块大小 & 总块数:基于 block_size、头数、层数等模型结构,推断需要多少块;
    3. 在 GPU/CPU 上创建空 Tensor:一下子把这批块都预先分配好,供后续推理阶段快速使用。

这两步完成后,vLLM 才算真正“就绪”,能够在请求到来时立即投入推理,无需临时分配更多大块内存,从而减少延迟、提高吞吐与稳定性。

从这部分内容也能看出,vLLM 在设计上十分注重实际系统工程需求:

  • 启动时就对显存做充分的准备;
  • 运行时则配合调度器和 PagedAttention,以“块”为单位执行分配与回收,实现弹性、灵活的高并发推理。

Scheduler调度

下面这部分内容讲的是 vLLM推理阶段如何利用调度器(Scheduler)对请求进行分配、执行、以及在显存不足时如何处理“swap”等操作。简单来说,调度器需要在每一个推理步骤(Prefill 或 Decode 的某一时刻)动态地决定哪些请求进入运行、哪些需要等待、哪些请求要被暂时Swap到CPU内存。下面会分几个要点为你详细拆解。


1. 三种队列:Waiting / Running / Swapped

1)Waiting队列

  • 刚刚到达、尚未开始推理或者中途需要继续等待显存的请求,会被放在等待队列里。
  • 当调度器检测到有空闲的KV缓存块或GPU显存足够时,就可以把这些请求从Waiting队列拉到Running队列里执行。

2)Running队列

  • 当前正在GPU上执行推理(prefill或decode)的请求。
  • 这些请求已经被分配了相应的KV缓存块(Block),可以进行一步或多步的前向计算。
  • 如果请求完成生成,或者中途需要释放资源,调度器会将它从Running队列移出。

3)Swapped队列

  • 当GPU显存紧张、KV缓存块无法满足新的token生成时,调度器可能会把部分正在运行的请求(尤其是“后到达”或“优先级较低”的请求)从GPU“换出”(swap)到CPU内存里,以释放GPU空间给其他请求继续运行。
  • 被swap出去的请求,其KV缓存也会被移到CPU上保存。等待下一次调度时,如果GPU显存再度可用,这些请求可重新加载回到GPU并恢复推理。

提示:Swapped队列在前面章节的示例图里未出现,这里才正式提出,表示vLLM在高并发、显存不足的情况下会使用“swap”策略。


2. 预备知识:后来先抢占 (Preemption)

在 vLLM 的调度策略里,有一项关键手段叫**“后来先抢占”**(Preemption),大致含义是:

如果一个新的请求到来(或正在等待中),需要分配KV缓存,但 GPU 上已没有空闲块可用,调度器会从 Running队列里“挑出最晚加入的请求”(或优先级更低的请求)将其 Swap 到 CPU,把腾出来的块让给新的(或优先级更高的)请求继续推理**。

这是典型的“后进先出”式抢占策略,目的是:

  1. 尽快满足新请求或更高优先级请求的需求(尤其是在在线服务模式下,对新的交互请求响应速度至关重要)。
  2. 被swap出去的请求也并非放弃,只是暂时中断;等到GPU显存重新腾出块后,再将它们从Swapped队列移回Running。

3. 调度器在每一步做什么?

正如图示“At every step, the scheduler”所示,每一个推理步骤(包括一次prefill或一次decode)开始时,调度器要做的事情主要有:

  1. 决定本次要运行的请求集合
    • 如果GPU上还有空闲的KV缓存块,调度器就从Waiting队列里取请求加到Running队列;
    • 如果没有可用块,且有新请求需要空间,则可能触发Swap,把一些正在Running的请求移到Swapped,以腾出块给新请求。
  2. 调用BlockSpaceManager和BlockAllocator
    • 为新加入Running队列的请求分配实际的KV块;
    • 处理块共享(多个请求可能共享某些前缀块);
    • 回收或删除已经完成的KV块;
    • 对被Swap或被抢占的请求,其KV块会移动到CPU或被标记为“swapped out”。
  3. 更新请求的状态
    • 已完成生成(到达或最大长度)的请求,从Running队列移除,释放块。
    • 中途被Swap到CPU的请求,改到Swapped队列;
    • 其它仍在进行的请求,继续保留在Running队列,以便下一步decode阶段接着计算。

4. 处理流程示例

可以用一个简单的示例来说明:

  1. 有新的请求A到达
    • 如果GPU上还有多余块,调度器把请求A从Waiting -> Running,并在BlockAllocator中为它分配若干物理块。
  2. 这时又来了请求B,而GPU已无可用块
    • 调度器查看Running队列,找到最晚加入或优先级低的请求X,将它从Running -> Swapped,并把对应KV缓存块swap到CPU内存。
    • 释放的块就能分配给请求B。
    • 请求X暂时在Swapped队列等待,下次调度看有没有机会回到GPU。
  3. 下一次解码阶段时
    • 如果GPU上又有空闲块(比如某个请求Y已经完成生成,释放了块),调度器就可以从Swapped队列拉回请求X(从Swapped -> Running),把它的KV缓存重新搬回GPU上,让它继续未完成的解码。
  4. 重复这一过程,直到所有请求都完成或被abort。

5. 优势与注意点

  1. 充分利用显存
    • 当有空闲块就多接收新的请求,加速吞吐;
    • 当显存吃紧时,就对暂时不急或后到的请求进行Swap,保障系统不会崩溃或OOM。
  2. 保证性能与响应
    • “后来先抢占”优先给新请求或更高优先级请求留出显存,可以减少高优先级请求的等待。
    • 但也意味着被Swap出去的请求要等一段时间才能回来继续解码,性能上会受点影响。
  3. Swap带来的I/O开销
    • 每次Swap都需要将KV缓存数据从GPU转移到CPU,对带宽和速度有一定损耗。
    • 这在高并发场景下是必要的折衷:总比让请求一直等待或者触发OOM要好。
  4. 队列状态的监控
    • 在实际部署时,可以观察到Scheduler日志里waiting/running/swapped三类队列的规模变化;
    • 如果Swapped队列长期过大,可能需要减小并行度或增加GPU资源。

6. 小结

通过这部分内容,你可以看到在 vLLM 里,“调度器”(Scheduler)发挥了至关重要的角色——在每个推理阶段,决定哪些请求可以用GPU继续生成,哪些请求要放在waiting或swap。这一切都围绕着“KV Cache块”这种核心资源展开:

  • 有空闲块 → 请求能进“running”,
  • 无空闲块 → 可能触发“swap”以释放块,
  • 完成或终止 → 回收块并移出队列。

同时,“后来先抢占(Preemption)”进一步让vLLM在GPU显存紧张时能优雅地处理新请求并避免系统崩溃,从而使得在线推理服务在高并发、大模型、有限显存的情况下依旧能维持可观的吞吐与响应速度。

总而言之,这就是图中展示的调度流程:当请求到来 -> LLMEngine将其加到Scheduler等待 -> 每步推理(prefill/decode)之前,Scheduler根据可用块分配或swap -> Worker执行运算 -> 重复直到请求结束。这也是 vLLM 能在实践中高效运行的关键所在。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/70639.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringSecurity请求流转的本质

1. SpringSecurity核心源码分析 分析SpringSecurity的核心原理,那么我们从哪开始分析?以及我们要分析哪些内容? 系统启动的时候SpringSecurity做了哪些事情?第一次请求执行的流程是什么?SpringSecurity中的认证流程是怎么样的?1.1 系统启动 当我们的Web服务启动的时候,…

聊一聊vue如何实现角色权限的控制的

大家好,我是G探险者。 关于角色与权限控制,通常是分为两大类:一种是菜单权限;一种是操作权限。 菜单权限是指,每个角色对应着可以看到哪些菜单,至于每个菜单里面的每个按钮,比如增删改查等等这类…

HTML之JavaScript DOM操作元素(2)

HTML之JavaScript DOM操作元素(2) 4.增删元素var element document.createElement("元素名") 创建新元素父元素.appendChild(子元素) 在父元素中追加子元素父元素.insertBefore(新元素,参照元素) 在特定元素之前新增元…

解决华硕主板的Boot界面无法设置M.2的系统启动盘问题

一、问题描述 当我们的华硕主板电脑开机后,发现电脑无法正常进入Windows系统界面,直接显示PXE网络网络信息;且知道我们进入到BIOS界面也无法找到选择系统盘,界面只显示【UEFI:PXE IP4 Intel(R) Ethernet】、【UEFI:PXE IP6 Intel(…

音视频封装格式:多媒体世界的“容器”与“桥梁”

一、音视频封装格式的核心概念 音视频封装格式(容器)是一种将编码后的视频、音频、字幕等数据按规则整合的文件格式,其本质是多媒体数据容器,核心作用包含: 同步多轨道数据:通过时间戳(PTS/DTS)实现音画同步。组织数据流:统一管理视频流、音频流、字幕流等,并存储元…

Jenkins 配置 Credentials 凭证

Jenkins 配置 Credentials 凭证 一、创建凭证 Dashboard -> Manage Jenkins -> Manage Credentials 在 Domain 列随便点击一个 (global) 二、添加 凭证 点击左侧 Add Credentials 四、填写凭证 Kind:凭证类型 Username with password: 配置 用…

Unity 3D模型边缘锯齿严重

Unity开发3D游戏时候,模型边缘会显示严重锯齿,这需要设置抗锯齿,同时也会增加显卡负担,是适配不同硬件的自定义配置选项 摄像机对象检查器中找到[渲染]设置"抗锯齿"为FXAA或者SMAA项目设置->图形->点选正在使用的渲染管线->定位到管线文件后,查看管线的检查…

Docker:Docker从入门到精通(一)- Docker简介

一、前言 通过本专栏的学习,我们将了解   1. 掌握Docker基础知识,能够理解Docker镜像与容器的概念   2. 完成Docker安装与启动   3. 掌握Docker镜像与容器相关命令   4. 掌握Tomcat Nginx 等软件的常用应用的安装   5. 掌握docker迁移与备份相…

【面试系列】Java开发--AI常见面试题

文章目录 1、实际工作或学习中用过哪些Ai工具1.1、AI编程1.2、AI对话聊天1.3、AI图像工具1.4、AI办公工具 2、谈谈你知道的AI领域的一些常见词汇及其含义的理解? 例如AIGC、LLM、DeepLearning分别是什么意思?2.1、AIGC(Artificial Intelligen…

在VSCode中接入deepseek

注册就送14元2000万tokens。 https://cloud.siliconflow.cn/i/rnbA6i6U各种大模型 下面介绍我是如如接入vscode的 左边生成一个key,呆会vscode要用,不然401. 打开vscod,电脑能上网。下插件。 下好要配置 点它一下。 要配置,全…

【Ubuntu】GPU显存被占用,但显示没有使用GPU的进程

文章目录 一、问题描述二、解决方案2.1 寻找问题进程2.2 尝试杀死相关进程2.3 投放核弹,一键全杀2.4 再次查看GPU使用情况 参考资料 一、问题描述 今天使用服务器的时候发现gpu被占了很多内存,但是使用 nvidia-smi 命令并没有发现占这么多显存的进程&am…

基于Python+django+mysql旅游数据爬虫采集可视化分析推荐系统

2024旅游推荐系统爬虫可视化(协同过滤算法) 基于Pythondjangomysql旅游数据爬虫采集可视化分析推荐系统 有文档说明 部署文档 视频讲解 ✅️基于用户的协同过滤推荐算法 卖价就是标价~ 项目技术栈 Python语言、Django框架、MySQL数据库、requests网络爬虫…

Redis 如何实现消息队列?

在当今的分布式系统架构中,消息队列起着至关重要的作用,它能够帮助系统实现异步通信、解耦组件以及缓冲流量等功能。Redis,作为一款高性能的键值对存储数据库,也为我们提供了便捷的方式来构建消息队列。今天,咱们就深入…

【多线程-第三天-NSOperation的练习-tableView异步下载网络图片-下载操作缓存池 Objective-C语言】

一、下载操作缓存池 1.下面我们来看操作缓存池,我们先演示一下问题,看看为什么要加这么一个操作缓存池,什么是操作缓存池,不用管呢,我们先来看啊,首先有什么问题, 看这个问题之前,我这儿写一个touch,点击屏幕的时候调用, 额,不能点击屏幕啊,因为现在屏幕点不着,我…

【2025深度学习环境搭建-1】在Win11上用WSL2和Docker解锁GPU加速

建议有: 较新的win11电脑,GPU是nvidia一点点Linux基础一点点Docker基础 一、安装WSL2 【控制面板】》【程序】》【启用或关闭Windows功能】 打开三个功能:【Hyper-V】【Virtual Machine Platform】【适用于Linux的Windows子系统】 可能看…

深入探索 DeepSeek 在数据分析与可视化中的应用

在数据驱动的时代,快速且准确地分析和呈现数据对于企业和个人都至关重要。DeepSeek 作为一款先进的人工智能工具,凭借其强大的数据处理和可视化能力,正在革新数据分析的方式。 1. 数据预处理与清洗 在进行数据分析前,数据预处理…

C#基础:类的三大特性 之 封装

一、封装、继承、多态关系说明 封装、继承、多态这三大特性是相互关联的,封装和继承几乎都是为多态而准备的。 封装是基础,继承是关键,多态性是补充。 多态性存在于继承性之中,它是继承性的进一步扩展,没有继承就没…

vscode无法预览Markdown在线图片链接

问题:在VSCode中,打开MarkDown文件,存在在线图片链接, 但是在预览时却无法显示。 原因:因为Visual Studio Code中的MarkDown默认配置中只允许载入安全内容 解决方法: 1、输入快捷键 Ctrl Shift P 打开…

mongodb的并发优化

MongoDB的锁模式 MongoDB的锁设计 MongoDB的高性能表现离不开它的多粒度锁机制。多粒度主要可以针对不同层级的数据库对象进行枷锁,通过避免全局性的互斥来提升并发能力。从整个数据库层面看,MongoDB的并发锁的分层如下图所示: 从上往下是一…

Python 环境管理介绍

pip pip 是 Python 的标准包管理工具&#xff0c;用于安装和管理 Python 软件包。它允许你从 Python 包索引&#xff08;PyPI&#xff09;下载并安装第三方库&#xff0c;并能自动解决依赖问题。 第三方库的安装与卸载 pip install <package>pip uninstall <packag…