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}")
-
背后原理:
- 表面上是同步:用户会一次性提交一批请求(batch),等待所有请求都推理完成再返回。
- 实际上是“动态”:vLLM的核心引擎(LLMEngine)内部会根据当前GPU显存的使用情况,对batch做“动态”调度。在一个推理阶段(prefill或一次decode)里,如果显存无法容纳所有请求,vLLM会先让部分请求进入“running队列”,剩下的请求留在“waiting队列”里等待。
- 多阶段推理:当某些请求在一次推理阶段完成或结束(生成了结束符或达到最大长度),它们就会释放所占用的显存块。这样下一批等待的请求就能进入“running队列”,继续下一阶段推理。
- 对用户而言是透明的:用户只看到自己提交了一个batch,等所有结果都处理完后才拿到输出;但在内核引擎中,这个batch可能被分拆成多个子批次进行推理。
2. API Server For Online Serving(在线服务)
-
调用特点:采用异步方式处理请求,随时可以接收新请求、并行处理多个请求;已完成的推理结果可以先行返回给客户端(尤其配合流式传输时,可以边生成边返回)。
-
vLLM 提供了两种在线API:
- OpenAI-Compatible API Server(官方推荐):兼容OpenAI的Completions和Chat API协议,使用方式与OpenAI API相同。
- 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}'
-
背后原理:
- 异步化处理:vLLM使用uvicorn + fastapi 实现一个异步服务器,内部封装了
AsyncLLMEngine
。 - 排队 + 调度:当多个请求同时到来,vLLM会先将请求放入一个异步队列,然后在内部调度器(Scheduler)的管理下,将请求动态加入“running队列”进行推理。
- 先完成先返回:只要有请求在当前推理阶段完成,就可以立即把结果返回给客户端,不需要等待其他请求一起结束。若开启流式输出,还能在生成过程中分段发送token给客户端。
- 同样使用PagedAttention:在线服务依然会利用PagedAttention进行显存优化;当显存不足时,还会做部分数据的swap到CPU或暂时排队等待,以提升吞吐。
- 异步化处理:vLLM使用uvicorn + fastapi 实现一个异步服务器,内部封装了
二、LLMEngine:vLLM的内核引擎
无论是离线批处理还是在线服务,都依赖于同一个核心组件——LLMEngine。它的主要功能包括:
- add_request()
- 将每个请求转换成vLLM内部的统一数据结构(如SequenceGroup),并加入调度器(Scheduler)的waiting队列中。
- 离线批处理场景下,这个函数是“同步式”的:会依次处理batch中的各条数据。
- 在线场景下,会被重写为异步版本(
AsyncLLMEngine
),以便在协程中对每个请求进行处理。
- step()
- 执行一次推理阶段(prefill算1次推理,decode的每一步也算1次推理)。
- 调度器(Scheduler)决定哪些请求可以进入“running队列”,并为它们分配所需的显存块(Physical KV blocks)。
- 模型(带有PagedAttention)根据这些分配信息执行推理,生成新的token并更新KV缓存。
- 如果有请求在本次推理阶段完成(如达到或其它终止条件),则释放对应显存块,并将该请求从running队列中移除。
- abort_request()
- 如果在推理过程中客户端断开连接,或用户取消了请求,可以调用此方法中断推理,释放对应资源。
总结:只要理解了
add_request()
和step()
这两个函数的核心逻辑,就掌握了LLMEngine的大部分精髓。它们背后涉及到很多“排队、调度、显存分配、PagedAttention”的复杂逻辑,源码中会有大量的封装与嵌套。
三、离线批处理与在线服务的内核差异
- 离线批处理
- 对用户来说:一次性输入所有数据 -> 一次性得到全部输出。
- 对LLMEngine来说:内部依然是“动态批”调度,不断有请求完成并释放显存,再让新的请求进来,但对用户是不可见的,属于“内部黑箱”。
- 在线服务
- 对用户来说:随时可以发送请求;完成的结果可以第一时间返回。
- 对LLMEngine来说:依旧是同一个调度器;不同在于用户随时可能发来新请求或断开已有请求,因此需要用异步队列、异步I/O的方式处理。
- 核心思路相同:都是把请求排队 -> 等到一个推理阶段到来时,把合适数量的请求放入“running队列” -> PagedAttention完成这批的计算 -> 释放已完成请求的显存 -> 重复。
代码整体架构
这张图展示了 vLLM 内部代码整体架构,可以把它拆分为“中央控制端(Centralized Controller)”和“分布式Worker”两大部分。LLMEngine 就位于中央控制端的进程里,负责调度和管理请求,而真正的模型推理(包括PagedAttention等核心逻辑)会在一个或多个分布式Worker进程上执行(每个GPU对应一个Worker)。以下是对各模块的更详细解读:
一、LLMEngine 与 Centralized Controller
这部分都在同一个CPU进程中(如图中左侧所示),它包含了:
- LLMEngine(vllm/engine/llm_engine.py)
- 这是用户直接调用的接口层,用于接收请求(prompt)并将其转给调度器进行处理。
- LLMEngine本身并不直接执行推理,而是协调Scheduler、BlockSpaceManager等组件,并通过网络或进程通信,把模型计算任务发送给下游的Worker进程。
- Scheduler(vllm/core/scheduler.py)
- 调度器:决定每一个“推理阶段”(如prefill或decode的某一步)要处理哪些请求,并且以什么方式把这些请求打包交给Worker来执行。
- 当有多个请求或多个batch同时到来时,Scheduler会根据显存使用情况和优先级策略决定如何将它们安排到running队列、waiting队列或swap到CPU内存。
- 在运行完某个阶段后,如果有请求产生了新token或已经完成推理,就相应地更新这些请求的状态并做后续处理(例如释放显存块)。
- BlockSpaceManager(vllm/core/block_manager.py)
- 块空间管理器:负责管理所有token KV缓存的“块”在显存/内存中的分布情况,以及它们的生命周期。
- 它会与调度器配合,决定在每个推理阶段,需要为哪些请求分配新的缓存块或回收哪些已经不再使用的块。
- BlockAllocator(vllm/core/…)
- 显存/CPU分配器:将具体的物理内存(包括GPU显存、CPU内存)分配给BlockSpaceManager所需要的KV缓存块。
- 当GPU显存不足时,可能将部分块swap到CPU,以腾出空间给新的请求。
- 对应地,BlockSpaceManager会记录块在GPU上或CPU上,并在需要计算时重新把块拉回GPU。
总结:Centralized Controller进程中,LLMEngine是对外的“门面”,Scheduler是核心的调度大脑,BlockSpaceManager与BlockAllocator则负责管理KV缓存块在不同硬件介质间的具体分配和回收。
二、Distributed Workers(分布式Worker 进程)
如图中右侧部分所示,vLLM可以在分布式环境中使用,每个Worker通常对应一块GPU(也可在CPU模式或Ray模式下运行)。当前版本主要是单主机多GPU的场景,后续可能扩展为更多分布式方案。下列是Worker内部的关键组件:
- Worker(vllm/worker/worker.py)
- Worker是一个进程,里面包含了CacheEngine、Worker.model等对象。
- 当Centralized Controller决定某些请求要进行推理时,就会将这些请求对应的KV块和输入数据传给某个Worker,由它执行模型计算并返回结果(新token、注意力分数等)。
- CacheEngine(vllm/worker/cache_engine.py)
- 负责与PagedAttention配合,在Worker本地对KV缓存进行读写操作。
- 当收到Scheduler的指令后,CacheEngine会根据请求发送的数据ID或位置,把对应的KV块取出来(或者新建)并调用PagedAttention进行推理中的注意力计算。
- Worker.model(vllm/model_executor/models/…)
- 真正加载了大语言模型权重的模块。
- 当需要进行前向推理时,Worker调用它来计算每一步生成所需的logits、隐层状态等,内部再调用PagedAttention的相关逻辑做注意力机制。
- PagedAttention(vllm/model_executor/layers/…)
- 在Worker的模型层中具体实现的“分页/分块式注意力”机制。
- 它将传统的KV缓存细粒度地切分为多个Block,并在计算注意力时只加载、更新相关Block,避免重复计算和显存浪费。
- 与CacheEngine、BlockAllocator共同配合,实现动态地分配、回收和复用KV缓存。
总结:分布式Worker相当于是实际执行大模型推理的“工作站”,里面包含模型与缓存管理等功能,通过PagedAttention和CacheEngine实现对KV缓存的高效操作。每个Worker与中央控制(Scheduler)相互通信,将请求对应的工作内容取过来执行,然后返回结果。
三、集中式调度 + 分布式推理 的好处
- 统一调度,简化架构
- 由于Scheduler和BlockSpaceManager都在主进程上进行集中管理,减少了多GPU之间的“谁分配什么资源” 的冲突和协商开销。
- Worker只需专注于执行分配到的计算任务,无需关心整体系统状态。
- 灵活的显存管理
- Centralized Controller可以全局掌握所有请求与所有GPU/CPU的使用情况,做全局调度;比如当某块GPU显存满了,可以直接把部分KV块swap到CPU或调度到其他GPU。
- Worker仅保留自己当前需要用到的块,剩余部分由BlockAllocator/BlockSpaceManager在后台统一管理。
- 扩展为多Worker
- 如果单GPU算力不足,可增加多个Worker进程,每个进程对应一块GPU或一组GPU,分担推理工作。
- 在后续版本中,vLLM也有望支持更多分布式策略(如TP/PP并行),进一步提升推理吞吐。
四、代码阅读指南
- vllm/engine/llm_engine.py:
入口:LLMEngine
和AsyncLLMEngine
。用户调用接口层,和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 在正式启动推理服务前,会做的两件初始化工作:
- 加载模型(将大模型权重加载到 Worker 上)
- 预分配显存(在 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)。
- 如果你在使用在线加载方式,只需在启动参数或环境变量中指定相应的模型名称(如
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_seqs
、max_num_batched_tokens
太大,导致需要分配的 KV Cache 块数量远超 GPU 真实承受能力,vLLM 能在初始化时就发现并报错,而不是推理时才崩溃。
2.2 关键参数
初始化 LLMEngine 时,用户通常会提供两个重要的配置项:
- max_num_seqs
- 在一个推理阶段里,vLLM Engine 最多能处理的序列(seq)数量。
- 默认为 256,意味着同时处理 256 条请求(或 256 条不同的上下文)是上限。
- 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
最后,vLLM 会调用类似 BlockAllocator._allocate_kv_cache()
这样的函数,在 GPU 或 CPU 上逐层(num_layers 次)创建这些空张量(torch.empty(...)
),并将它们存放到一个列表里,组成 “KV Cache” 池。
- 这些空张量就相当于分割好的“片段”,每个分片能容纳一部分 token 的键值对。
- 当有新请求到来,需要一个 block 时,BlockManager/BlockAllocator 只要把一个空闲块分配给它,无需再进行张量创建。
优点:
- 减少了运行时的 Fragmentation(碎片化)风险。
- 可以快速映射到调度策略,让 Scheduler 知道当前空闲块、在用块、swap 块的数量与位置,进行更精细的管理。
三、预分配带来的好处与注意点
- 启动后显存占用“突增”是正常现象
- 由于 vLLM 把一部分空张量提前开辟好了,你可能会看到 GPU 显存一下子就用掉了相当大比例。但这些张量实际是空数据,只是占位;真正放入 Token KV 时才会写入内容。
- 参数调得过大可能导致 OOM
- 如果你指定的
max_num_seqs
和max_num_batched_tokens
太高,而 GPU 显存不足,vLLM 在初始化时就会报错或内存不足的问题,而不是推理时才发现。 - 这其实是个安全机制,让你知道当前配置不可行。
- 如果你指定的
- 调度器与预分配
- 一旦 KV block 预分配完毕,Scheduler 就能准确地知道有多少块可用,并且在推理阶段分配/回收这些块给不同请求。如果用完了,新的请求就只能等,或者把不活跃的块swap到 CPU。
- 可能影响多进程部署
- 在多进程(或多容器)中部署时,各自进程都要预分配一份 KV cache,会进一步增加显存占用,需要格外留意调优。
四、小结
- 加载模型:先把大模型的权重加载到每个 Worker 上,保证 Worker 拥有完整的计算能力。
- 预分配显存:
- 内存测量:通过一次模拟推理,估计模型本身占用多少显存,并计算剩余可用于 KV cache 的空间;
- 计算块大小 & 总块数:基于 block_size、头数、层数等模型结构,推断需要多少块;
- 在 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,把腾出来的块让给新的(或优先级更高的)请求继续推理**。
这是典型的“后进先出”式抢占策略,目的是:
- 尽快满足新请求或更高优先级请求的需求(尤其是在在线服务模式下,对新的交互请求响应速度至关重要)。
- 被swap出去的请求也并非放弃,只是暂时中断;等到GPU显存重新腾出块后,再将它们从Swapped队列移回Running。
3. 调度器在每一步做什么?
正如图示“At every step, the scheduler”所示,每一个推理步骤(包括一次prefill或一次decode)开始时,调度器要做的事情主要有:
- 决定本次要运行的请求集合
- 如果GPU上还有空闲的KV缓存块,调度器就从Waiting队列里取请求加到Running队列;
- 如果没有可用块,且有新请求需要空间,则可能触发Swap,把一些正在Running的请求移到Swapped,以腾出块给新请求。
- 调用BlockSpaceManager和BlockAllocator
- 为新加入Running队列的请求分配实际的KV块;
- 处理块共享(多个请求可能共享某些前缀块);
- 回收或删除已经完成的KV块;
- 对被Swap或被抢占的请求,其KV块会移动到CPU或被标记为“swapped out”。
- 更新请求的状态
- 已完成生成(到达或最大长度)的请求,从Running队列移除,释放块。
- 中途被Swap到CPU的请求,改到Swapped队列;
- 其它仍在进行的请求,继续保留在Running队列,以便下一步decode阶段接着计算。
4. 处理流程示例
可以用一个简单的示例来说明:
- 有新的请求A到达
- 如果GPU上还有多余块,调度器把请求A从Waiting -> Running,并在BlockAllocator中为它分配若干物理块。
- 这时又来了请求B,而GPU已无可用块
- 调度器查看Running队列,找到最晚加入或优先级低的请求X,将它从Running -> Swapped,并把对应KV缓存块swap到CPU内存。
- 释放的块就能分配给请求B。
- 请求X暂时在Swapped队列等待,下次调度看有没有机会回到GPU。
- 下一次解码阶段时
- 如果GPU上又有空闲块(比如某个请求Y已经完成生成,释放了块),调度器就可以从Swapped队列拉回请求X(从Swapped -> Running),把它的KV缓存重新搬回GPU上,让它继续未完成的解码。
- 重复这一过程,直到所有请求都完成或被abort。
5. 优势与注意点
- 充分利用显存
- 当有空闲块就多接收新的请求,加速吞吐;
- 当显存吃紧时,就对暂时不急或后到的请求进行Swap,保障系统不会崩溃或OOM。
- 保证性能与响应
- “后来先抢占”优先给新请求或更高优先级请求留出显存,可以减少高优先级请求的等待。
- 但也意味着被Swap出去的请求要等一段时间才能回来继续解码,性能上会受点影响。
- Swap带来的I/O开销
- 每次Swap都需要将KV缓存数据从GPU转移到CPU,对带宽和速度有一定损耗。
- 这在高并发场景下是必要的折衷:总比让请求一直等待或者触发OOM要好。
- 队列状态的监控
- 在实际部署时,可以观察到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 能在实践中高效运行的关键所在。
相关文章:
vLLM学习1
调用方式 一、vLLM 提供的两种调用方式 1. Offline Batched Inference(离线批处理) 调用特点:一次性传入一批(batch)的请求,等待所有请求都处理完毕后,一次性返回推理结果。对用户而言&#x…...
ABC 385
目录 C. Illuminate Buildings D. Santa Claus E. Snowflake Tree C. Illuminate Buildings dp[ i ][ j ]:选择的 i 个建筑,间隔为 j。这样只需要两层循环就可以了,o(n^2) 其实本质只是个一维 dp,但我还需…...
綫性與非綫性泛函分析與應用_1.例題(下)-半母本
第1章 實分析與函數論:快速回顧(下) 五、基數;有限集和無限集相關例題 例題1:集合基數的判斷 判斷集合和集合B=\{a,b,c,d,e\}的基數關係。 解析: 可以構造一個雙射,例如,,,,。 所以,兩個集合具有相同的基數。 例題2:可數集的證明 證明整數集是可數集。 解析: …...
49 set与map的模拟实现
目录 一、源码及框架分析 二、模拟实现map和set (一)复用红黑树的框架,并支持insert (二)支持迭代器的实现 (三)map支持 [ ] (四)整体代码实现 一、源码及框架分析…...
鸿蒙NEXT应用App测试-通用测试
注意:大家记得学完通用测试记得再学鸿蒙专项测试 https://blog.csdn.net/weixin_51166786/article/details/145768653 注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章…...
LangChain 技术入门指南:探索语言模型的无限可能
在当今的技术领域,LangChain 正逐渐崭露头角,成为开发语言模型应用的强大工具。如果你渴望深入了解并掌握这一技术,那么就跟随本文一起开启 LangChain 的入门之旅吧! (后续将持续输出关于LangChain的技术文章,有兴趣的同学可以关注…...
UE5销毁Actor,移动Actor,简单的空气墙的制作
1.销毁Actor 1.Actor中存在Destory()函数和Destoryed()函数 Destory()函数是成员函数,它会立即标记 Actor 为销毁状态,并且会从场景中移除该 Actor。它会触发生命周期中的销毁过程,调用 Destroy() 后,Actor 立即进入销毁过程。具体…...
STM32基础篇(二)------GPIO
GPIO简介 GPIO(General Purpose Input Output)通用输入输出口 可配置为8种输入输出模式 引脚电平:0V~3.3V,部分引脚可容忍5V 输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等 输入…...
亲测Win11电脑可以安装LabVIEW的版本,及2015、2018、2020版本直接的区别
下面是我电脑的信息 设备名称 DESKTOP-04HHS8S 处理器 13th Gen Intel(R) Core(TM) i5-13500H 2.60 GHz 机带 RAM 16.0 GB (15.7 GB 可用) 设备 ID 82798104-C565-4167-A21E-5EB5DEFAA541 产品 ID 00331-20300-00000-AA678 系统类型 64 位操作系统, 基于 …...
Idea2024中搭建JavaFX开发环境并创建运行项目
Idea2024中搭建JavaFX开发环境并创建运行项目 本文以Java语言为例演示如何创建JavaFX开发项目和部署开发环境,读者可以根据个人实际灵活选择相关参数。 一、项目创建与环境搭建步骤 新建JavaFX项目,选择适合项目实际的语言、系统和JDK。 项目设置-设置…...
认知重构 | 自我分化 | 苏格拉底式提问
注:本文为 “认知重构 | 自我分化” 相关文章合辑。 心理学上有一个词叫:认知重构(改变 “非黑即白,一分为二” 的思维方式) 原创 心理师威叔 心理自救 2024 年 10 月 26 日 19:08 广东 你有没有过这样的时候&#x…...
MFC开发:如何创建第一个MFC应用程序
文章目录 一、概述二、MFC 的主要组件三、创建一个MFC窗口四、控件绑定消息函数 一、概述 MFC 是微软提供的一个 C 类库,用于简化 Windows 应用程序的开发。它封装了 Windows API,提供面向对象的接口,帮助开发者更高效地创建图形用户界面&am…...
nodejs:vue 3 + vite 作为前端,将 html 填入<iframe>,在线查询英汉词典
向 doubao.com/chat/ 提问: node.js js-mdict 作为后端,vue 3 vite 作为前端,编写在线查询英汉词典 后端部分(express js-mdict ) 详见上一篇:nodejs:express js-mdict 作为后端ÿ…...
基于 Python Django 的校园互助平台(附源码,文档)
博主介绍:✌Java徐师兄、7年大厂程序员经历。全网粉丝13w、csdn博客专家、掘金/华为云等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇🏻 不…...
玩转 Java 与 Python 交互,JEP 库来助力
文章目录 玩转 Java 与 Python 交互,JEP 库来助力一、背景介绍二、JEP 库是什么?三、如何安装 JEP 库?四、JEP 库的简单使用方法五、JEP 库的实际应用场景场景 1:数据处理场景 2:机器学习场景 3:科学计算场…...
【Linux】基于UDP/TCP服务器与客户端的实现
目录 一、UDP (一)Server.hpp (二)Server.cpp (三)Client.hpp (四)Client.cpp (五)User.hpp 二、TCP (一)多进程版本的服务器与…...
Unity for Python —— 强大的 Python 脚本支持提升 Unity 编辑器效率
内容将会持续更新,有错误的地方欢迎指正,谢谢! Unity for Python —— 强大的 Python 脚本支持提升 Unity 编辑器效率 TechX 坚持将创新的科技带给世界! 拥有更好的学习体验 —— 不断努力,不断进步,不断探索 Tec…...
【Dubbo+Zookeeper】——SpringBoot+Dubbo+Zookeeper知识整合
🎼个人主页:【Y小夜】 😎作者简介:一位双非学校的大二学生,编程爱好者, 专注于基础和实战分享,欢迎私信咨询! 🎆入门专栏:🎇【MySQL࿰…...
家用路由器的WAN口和LAN口有什么区别
今时今日,移动终端盛行的时代,WIFI可以说是家家户户都有使用到的网络接入方式。那么路由器当然也就是家家户户都不可或缺的设备了。而路由器上的两个实现网络连接的基础接口 ——WAN 口和 LAN 口,到底有什么区别?它们的功能和作用…...
Python--函数入门
1. 函数基础概念 1.1 什么是函数 定义:函数是一段可重复调用的代码块,用于封装特定功能。 核心作用: 代码重用:减少重复代码的编写。增强可读性:通过命名和模块化让代码逻辑更清晰。 1.2 函数的定义与调用 def 函…...
EasyRTC低延迟通信与智能处理:论嵌入式WebRTC与AI大模型的技术融合
在当今数字化时代,实时通信的需求日益增长,视频通话作为一种高效、直观的沟通方式,广泛应用于各个领域。WebRTC技术的出现,为实现浏览器之间的实时音视频通信提供了便捷的解决方案。而基于WebRTC技术的EasyRTC视频通话SDK…...
《操作系统 - 清华大学》 8 -6:进程管理:进程状态变化模型
进程状态及其转换全解析 在操作系统中,进程有着特定的生命周期和多种状态变化。不考虑进程结束时,进程主要有三个基本状态。 运行态:即进程正在占用CPU执行任务。总结:运行态表示进程当前正在使用CPU。就绪状态:进程…...
大语言模型中的 Token如何理解?
在大语言模型中,Token 是文本处理的基本单元,类似于“文字块”,模型通过将文本分割成Token来理解和生成内容。举一个形象一点的例子,可以理解为 AI 处理文字时的“最小积木块”。就像搭乐高时,每块积木是基础单位一样&…...
信息学奥赛一本通 1522:网络 | OpenJudge 百练 1144:Network
【题目链接】 ybt 1522:网络 OpenJudge 百练 1144:Network 【题目考点】 1. 图论:割点 【解题思路】 每个交换机是一个顶点,如果两地点之间有电话线连接,那么两顶点之间有一条无向边,该图是无向图。 初始时任何地…...
3分钟快速本地部署deepseek
DeepSeek简介 DeepSeek 是杭州深度求索人工智能基础技术研究有限公司开发的一系列大语言模型,背后是知名量化资管巨头幻方量化3。它专注于开发先进的大语言模型和相关技术,拥有多个版本的模型,如 DeepSeek-LLM、DeepSeek-V2、DeepSeek-V3 等…...
Linux系统管理与编程01:准备工作
0 准备工作 0.1 安装VMWare Workstation pro17 到百度搜一下,到处都是。安装好VMWare Workstation pro17(以下简称VW)。 图0- 1 安装过程略。 0.2下载CentOS7.6 图0- 2 选择minimal版本。 0.3下载yum库文件 下载阿里云yum库文件https:…...
常用的几种编码方式
常见的编码方式有多种,每种编码方式都有其特定的用途和特点。以下是几种常见的编码方式: ASCII(美国信息交换标准代码) 用途:主要用于表示英文字符及控制字符。特点:使用7位二进制数表示字符,能…...
WebXR教学 03 项目1 旋转彩色方块
一、项目结构 webgl-cube/ ├── index.html ├── main.js ├── package.json └── vite.config.js二、详细实现步骤 初始化项目 npm init -y npm install three vite --save-devindex.html <!DOCTYPE html> <html lang"en"> <head><…...
从零开始的网站搭建(以照片/文本/视频信息通信网站为例)
本文面向已经有一些编程基础(会至少一门编程语言,比如python),但是没有搭建过web应用的人群,会写得尽量细致。重点介绍流程和部署云端的步骤,具体javascript代码怎么写之类的,这里不会涉及。 搭…...
netcore 启用gzip压缩及缓存
public void ConfigureServices(IServiceCollection services) {....// 配置gzip 与 br的压缩等级为最优services.Configure<BrotliCompressionProviderOptions>(options > {options.Level CompressionLevel.Optimal;});services.Configure<GzipCompressionProvid…...
c++入门-------命名空间、缺省参数、函数重载
C系列 文章目录 C系列前言一、命名空间二、缺省参数2.1、缺省参数概念2.2、 缺省参数分类2.2.1、全缺省参数2.2.2、半缺省参数 2.3、缺省参数的特点 三、函数重载3.1、函数重载概念3.2、构成函数重载的条件3.2.1、参数类型不同3.2.2、参数个数不同3.2.3、参数类型顺序不同 前言…...
elf_loader:一个使用Rust编写的ELF加载器
本文介绍一个使用Rust实现的ELF加载器。 下面是elf_loader的仓库链接: github: https://github.com/weizhiao/elf_loaderhttps://github.com/weizhiao/elf_loader crates.io: https://crates.io/crates/elf_loaderhttps://crates.io/cra…...
postman调用ollama的api
按照如下设置,不需要设置key 保持长会话的方法 # 首次请求 curl http://localhost:11434/api/generate -d {"model": "deepseek-r1:32b","prompt": "请永久记住:110,1-12,之后所有数学计算必…...
鸿蒙5.0实战案例:基于ArkUI的验证码实现
往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录) ✏️ 鸿蒙(HarmonyOS)北向开发知识点记录~ ✏️ 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ ✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景&#…...
通俗理解什么是云原生?
by deepseek。 一、核心理念:云原生到底是什么? 1. 一句话定义 云原生(Cloud Native) 是一种构建和运行应用程序的方法论,它利用云计算的优势(弹性、分布式、自动化),让软件从设计…...
基于PSO粒子群优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a/matlab2024b 3.部分核心程序 (完整版代码包含详细中文注释和操作步骤视频…...
什么是完全前向保密(PFS)?
在当今数字化时代,信息安全至关重要。而密码学中的完全前向保密(Perfect Forward Secrecy,简称PFS)技术,已经成为保障信息安全的关键一环。如果没有完全前向保密,一旦长期密钥被泄露,攻击者就可…...
Oracle备库srvctl start丢失某个原有的service_names的案例
最近在测试主备环境中使用srvctl添加新的service之后,srvctl start发现其中一个原本用于主备同步的service丢失了。 原始的参数文件中的service_names参数值如下(数据库中service_names的值也一样,省略查看步骤): [oraclesmartdbstb01 202502…...
重学SpringBoot3-怎样优雅停机
更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞??收藏评论 重学SpringBoot3-怎样优雅停机 1. 什么是优雅停机?2. Spring Boot 3 优雅停机的配置3. Tomcat 和 Reactor Netty 的优雅停机机制 3.1 Tomcat 优雅停机3.2 Reactor Netty 优…...
SkyWalking集成Kafka实现日志异步采集经验总结
SkyWalking日志异步采集架构 【重点知识】 1、【Agent】kafka-reporter-plugin-x.x.x.jar包放plugins目录后必走kafka(kafka没有正确配置就会报错) 2、【Agent】异步如不开启数据压缩,日志数据较大,pod多、业务大时容易造成网络…...
图论 之 BFS
文章目录 3243.新增道路查询后的最短距离1311.获取你好友已观看的视频 BFS:广度优先搜索(BFS) 是一种常用的算法,通常用于解决图或树的遍历问题,尤其是寻找最短路径或层级遍历的场景。BFS 的核心思想是使用队列(FIFO 数…...
rust学习笔记5-所有权机制
rust核心就是所有权机制,是其内存管理的核心特性,旨在消除内存安全问题(如空指针、悬垂指针、内存泄漏等)而无需依赖垃圾回收(GC) 1.首先看一下语义模型 当声明一个变量 let a "32";它的语义模…...
网站快速收录:如何优化网站404页面?
优化网站404页面是提升用户体验和SEO效果的重要一环。以下是一些优化404页面的建议: 一、设计友好的404页面 简洁明了的提示信息:使用清晰的语言告诉用户该页面不存在或已被删除,避免使用过于技术化的术语。 提供导航链接:在40…...
关于order by的sql注入实验
实验描述 本实验基于sqli-lab的第46关进行测试 本关的sql 语句为$sql "SELECT * FROM users ORDER BY $id" 利用sort进行sql注入,我们可以利用报错注入,延时注入来爆出数据 1.报错注入 1.手工测试 爆出数据库 ?sort(extractvalue(1, c…...
Docker(Nginx)部署Vue
简介:目标使用docker将vue生成的dist文件,结合nginx生成镜像,然后运行; 1、首选确保vue项目正确运行,并能正确打包dist文件; 2、查看已经生成的dist文件 3、将dist文件打包为rar文件或者zip文件…...
从函数到神经网络
一、从函数到神经网络 所有一切的前提是,你要相信这个世界上的所有逻辑和知识,都可以用一个函数来表示。Functions describe the world ! 比如输入物体的质量和加速度,根据牛顿第二定律,就可以得到物体施加的力,这就是…...
Python 字符串格式化 print
Python 字符串格式化 print flyfish 1. 使用百分号(%)操作符进行字符串格式化 百分号(%)操作符是 Python 中比较传统的字符串格式化方式,它的使用方式类似于 C 语言中的 printf 函数。 # 格式化整数 num 10 print…...
LabVIEW 中的 Bluetooth.llb 库
Bluetooth.llb 库位于C:\Program Files (x86)\National Instruments\LabVIEW 2019\vi.lib\Platform目录,它是 LabVIEW 平台下用于蓝牙通信相关操作的重要库。该库为 LabVIEW 开发者提供了一系列工具,用于实现设备间的蓝牙连接、数据传输与交互等功能&…...
MySQL | MySQL库、表的基本操作01
MySQL库、表的基本操作01 一、库操作1.1 查看数据库1.2 创建数据库1.3 选择数据库1.4 查看创建数据库的SQL语句1.5 修改数据库1.6 删除数据库 二、表操作2.1 创建数据表2.2 查看表2.3 查看表结构2.4 查看创建数据库的SQL语句2.5 修改表2.6 删除表 ⚠️MySQL版本 8.0 一、库操作…...
抖音试水AI分身;腾讯 AI 战略调整架构;百度旗下小度官宣接入DeepSeek...|网易数智日报
抖音试水AI分身,字节旗下AI智能体平台扣子已与抖音打通,相关功能内测中 2月19日消息,钛媒体App独家获悉,字节旗下AI智能体开发平台扣子(Coze)已与抖音打通,抖音创作者可在扣子智能体平台打造AI分…...