ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

vLLM 请求调度完全指南:高并发下如何接住几百个并发请求?

vLLM 请求调度完全指南:高并发下如何接住几百个并发请求? vLLM 请求调度完全指南高并发下如何接住几百个并发请求【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllmGPU 利用率钉在 95%新请求的首 token 却要等 8 秒。vLLM 的请求调度正是为解决这类高并发痛点而生用连续批处理做负载均衡、用 KV Cache 块做资源分配、靠抢占在内存吃紧时兜底。下面从一个请求的完整旅程拆解。一屏看懂 vLLM 调度系统的全貌把 vLLM 想象成一家只有一口灶GPU的餐厅调度器是传菜员每来一个请求就像一张点单它每“步”看一眼预算还剩多少决定哪些菜立刻下锅、哪些先记号。而每个请求占用的 KV Cache 块 ️就像车位——车请求走不了一定能立刻腾出车位车在就得占着。调度器每个引擎步骤只做一件事在“本步最多算多少 token”的预算内把 waiting 和 running 两个队列里的请求装进一个批。V1 引擎中不再有独立的 swapped 队列等待、运行、被抢占三条线全部收敛到这条主线上。宏观架构可参考下图跟踪一个请求从进队到被抢占的完整旅程请求生命周期只有三个主干状态定义在vllm/v1/request.py的RequestStatus到达 → 排队请求进入 waiting 队列。队列策略由policy决定fcfs先到先服务priority按优先级数值小的先走vllm/config/scheduler.py。这就是第一层负载均衡——队头顺序决定了谁先拿到 GPU。排队 → 预填充调度器先遍历 running 队列保证老请求不断档再看 waiting 队列。新请求要通过两道闸门本步剩余令牌预算、KV Cache 剩余块数。通过后才分配块、进入 running。预填充 → 解码长 prompt 不会一口气算完而是被切成多段分块预填充每段和一批解码请求混在同一个 forward 里。完成或被抢占满足停止条件就释放块、结束若后续请求挤不进来了调度器会挑 running 里的请求踢回 waiting清空它的 KV 块并重置进度腾地给新请求。源码入口在 vllm/v1/core/sched/scheduler.py其中schedule()方法就是上面这条线的实现。三大核心机制逐个讲清连续批处理与分块预填充长 prompt 为什么不再卡死短请求一句话类比传菜员不盯着“一桌菜齐了才端”而是“每口灶空出来就塞下一道菜”。连续批处理Continuous Batching让批次不再是固定名单——每步结束有请求退场新请求立刻补位分块预填充Chunked Prefill则把长 prompt 切成小块和别人的解码一起跑避免 2 万 token 的 prompt 独占一整个前向。# 每步调度伪逻辑自拟概括见 scheduler.py 真实实现 token_budget max_num_batched_tokens for req in running waiting: # 先保 running再填 waiting n min(req.remaining_tokens, token_budget) if kv_manager.can_allocate(req, n): schedule(req, n) token_budget - n这段循环就是“预算装箱”max_num_batched_tokens是每步的总容量谁排在前面谁先装。调它会发生什么调大max_num_batched_tokens吞吐上升、单步延迟略增调小则短请求 TTFT首 token 延迟更稳。默认已开启分块预填充long_prefill_token_threshold可给单个长请求设每步上限防止它一次吃满整锅预算。KV Cache 块管理与水印怎么在内存边缘稳住不抖动一句话类比KV Cache 是停车场车位按 16 个 token 一格编号请求的车停哪几格由块表记录水印Watermark就是“永远空出最后几格不让停车场贴满”。块分配逻辑在 vllm/v1/core/kv_cache_manager.py。水印的关键细节它只对 waiting/preempted 请求“放行”时起作用已在 running 的解码请求不受影响——保护的是“新客入场”不是“老客续住”。# 水印准入检查伪逻辑自拟概括 free kv_manager.num_free_blocks() need blocks_for(req) if req in (waiting, preempted): ok free - need watermark_blocks # 留余量 else: # running 请求 ok free needwatermark是 KV 块总数的比例默认 0.0关闭。调它会发生什么内存偏紧时开watermark0.01~0.05能显著减少“刚放行就驱逐、接着连锁抢占”的抖动开到 0.1 以上则空闲块被长期占用吞吐明显下降。抢占怎么选V1 为什么用“重算”而不是 Swap一句话类比Swapping 像把车临时挪去楼上的机械车库CPU 内存回来再挪回楼下而 vLLM V1 的选择是“清场重停”——直接释放车位请求回队首等下次进场时重新预填充。V1 的抢占路径很短伪代码概括自_preempt_requestdef _preempt(req): # 自拟伪代码 free_blocks(req) # 释放全部 KV Cache 块 req.num_computed_tokens 0 # 进度清零 req.status PREEMPTED # 放回 waiting 队首为什么放弃 SwapGPU↔CPU 的块搬运带宽是瓶颈长序列挪一次的成本常常比重算还高而且 V1 抢占后重新预填充时能命中前缀缓存实际重算量远小于表面进度前缀缓存见 docs/features/automatic_prefix_caching.md。V0 时代的双队列 swap 机制已被这条更简单的路径取代。调它会发生什么抢占次数可看监控里的preemptions指标。频繁抢占说明 KV 容量或准入太激进——优先加大 KV 池、开水印而不是加机器被抢占请求回到 waiting 队首所以它恢复时不会被新请求插队。高并发下的关键调优参数速查表参数含义默认值建议范围max_num_batched_tokens每步前向最多算的 token 数批处理容量20482048–16384max_num_seqs单步最多并发的序列数12864–512block_size一个 KV 块容纳的 token 数1616–64watermark准入时预留的 KV 块比例0.00–0.1long_prefill_token_threshold单步内单个长请求的预填充上限0关闭512–2048policy队列策略fcfs 或 priorityfcfs按业务max_num_queued_reqs在途请求上限超限直接 503 拒绝不限约 DP×max_num_seqsenable_chunked_prefill是否开启分块预填充True保持 True两组场景化配置# 场景一高并发短请求问答类 LLM(modelm, max_num_batched_tokens8192, max_num_seqs256, policyfcfs) # 大预算装满批fcfs 保证公平 # 场景二长序列生成文档类 LLM(modelm, max_num_batched_tokens4096, max_num_seqs64, long_prefill_token_threshold512, watermark0.02) # 限制单请求每步占用水印防驱逐抖动短请求场景把容量拉满换吞吐长序列场景收窄单请求每步占用并开水印用一点容量换稳定。结语vLLM 请求调度的本质是两道预算令牌数、KV 块加一条兜底线抢占重算把负载均衡和资源分配拆到了每一步、每个块。先盯住max_num_batched_tokens与 KV 容量两个旋钮再看抢占指标绝大多数高并发问题都能定位到参数层。更多设计细节见 docs/design/arch_overview.md 与 docs/usage/faq.md。【免费下载链接】vllmA high-throughput and memory-efficient inference and serving engine for LLMs项目地址: https://gitcode.com/GitHub_Trending/vl/vllm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表