当前位置: 首页 > news >正文

备案网站多长时间站群cms建站系统免费

备案网站多长时间,站群cms建站系统免费,发广告,做优化网站深入解析 vLLM#xff1a;高性能 LLM 服务框架的架构之美#xff08;一#xff09;原理与解析 深入解析 vLLM#xff1a;高性能 LLM 服务框架的架构之美#xff08;二#xff09;调度管理 1. vLLM 调度器结构与主要组件 在 vLLM 中#xff0c;调度器的结构设计围绕任务…深入解析 vLLM高性能 LLM 服务框架的架构之美一原理与解析 深入解析 vLLM高性能 LLM 服务框架的架构之美二调度管理 1. vLLM 调度器结构与主要组件 在 vLLM 中调度器的结构设计围绕任务的状态管理和内存资源的优化利用展开。为此它将任务划分为不同的状态队列并通过缓存管理和内存调度来保证任务处理的高效性。下面详细介绍调度器的核心组成部分waiting、running 和 swapped 三个状态队列的作用及设计。 图 1: vLLM 调度器结构图 vLLM 调度器依赖三个状态队列来管理任务的不同阶段 waiting 队列waiting 队列用于存放新加入的任务或已完成预填充阶段但等待解码的任务。调度器会从 waiting 队列中取出任务判断其是否可以分配资源如果资源允许则将其移至 running 队列。 running 队列running 队列包含当前正在处理的任务通常是在解码阶段。调度器会根据当前资源情况和任务优先级决定是否抢占任务将其暂时移出 GPU 以腾出资源。抢占的任务会被转移到 swapped 队列中。 swapped 队列swapped 队列用于存放因资源不足而被暂时从 GPU 移至 CPU 的任务。调度器会定期检查 swapped 队列如果资源允许则将任务重新加载到 GPU继续运行。 相关实现在 vllm/engine/scheduler.py 中。 2. 初始化与请求队列的管理 调度器的初始化和请求队列管理是 vLLM 高效运行的关键。这部分主要实现在 vllm/engine/scheduler.py 中的 Scheduler 类。 Scheduler 的初始化过程集中在解析配置项、创建 BlockSpaceManager 和初始化状态队列以确保调度器能够动态、高效地管理多任务请求。初始化过程中涉及三个主要配置 scheduler_config包含调度器行为相关的设置如任务优先级、调度策略等。cache_config定义内存分配策略、GPU 与 CPU 缓存的使用等。lora_config可选用于配置 LoRA 模型的特定要求如并行度和内存需求。 # File: vllm/core/scheduler.py class Scheduler:def __init__(self,scheduler_config: SchedulerConfig,cache_config: CacheConfig,lora_config: Optional[LoRAConfig] None,pipeline_parallel_size: int 1,output_proc_callback: Optional[Callable] None,) - None:self.scheduler_config scheduler_configself.cache_config cache_configself.lora_config lora_config# 根据版本及配置选用不同的 BlockSpaceManagerversion selfattn if not (scheduler_config.task embedding or cache_config.is_attention_free) else placeholderBlockSpaceManagerImpl BlockSpaceManager.get_block_space_manager_class(version)# 配置 GPU 和 CPU 块的数量num_gpu_blocks cache_config.num_gpu_blocks // pipeline_parallel_sizenum_cpu_blocks cache_config.num_cpu_blocks // pipeline_parallel_size# 初始化 BlockSpaceManager 以管理内存块self.block_manager BlockSpaceManagerImpl(block_sizecache_config.block_size,num_gpu_blocksnum_gpu_blocks,num_cpu_blocksnum_cpu_blocks,sliding_windowcache_config.sliding_window,enable_cachingcache_config.enable_prefix_caching)# 初始化请求的状态队列self.waiting: Deque[SequenceGroup] deque()self.running: Deque[SequenceGroup] deque()self.swapped: Deque[SequenceGroup] deque()# 用于记录完成请求的 IDself._finished_requests_ids: List[str] []self.output_proc_callback output_proc_callbackself.cache_id 0self._async_stopped: List[SequenceGroup] []每个新请求在进入调度队列前需要被解析并转换成 SequenceGroup 实例。这一步骤的关键在于为请求分配适当的 token 数、调度优先级、资源需求等信息然后将其分配至 waiting、running 或 swapped 队列。 SequenceGroup一个请求可能包含多个序列如生成任务的多个解码路径。SequenceGroup 用于管理请求的多个序列并跟踪该组序列的状态。add_seq_group 方法将一个新请求包装为 SequenceGroup并添加到 waiting 队列。 一个新请求在进入调度器后会首先经过 add_seq_group 的包装流程生成 SequenceGroup 实例并加入 waiting 队列。假设一个请求需要生成文本的多种可能性调度器会解析该请求并通过 add_seq_group 将其加入等待队列等待资源分配。 3. 调度流程与任务分配策略 vLLM 的调度系统设计堪称一件精妙的艺术品。它通过精心设计的状态转换机制,优雅地解决了大规模并发请求下的资源调度难题。在 vllm/engine/scheduler.py 的 Scheduler 类中,调度器通过 _schedule 方法作为总指挥,协调着整个系统的运转。 调度器会根据当前系统负载和请求特征,自适应地选择最优的调度策略。在标准场景下使用 _schedule_default,而在需要处理大批量请求时,则会切换到专门优化的 _schedule_chunked_prefill 模式。这种灵活的策略选择确保了系统在不同负载下都能保持最佳性能。 整个调度过程可以优雅地分为三个阶段: 预填充阶段(Prefill Phase) 这是请求处理的第一个关键阶段。当新请求到达时,调度器首先评估其资源需求,包括所需的 KV Cache 空间和计算资源。系统会为请求生成初始的注意力缓存,为后续的解码做好准备。这个阶段就像是为任务搭建舞台,布置好所有必要的道具。 解码阶段(Decode Phase) 这是生成过程的核心阶段。调度器在这个阶段需要精确地分配计算资源,确保每个请求都能得到持续的服务。通过细粒度的资源管理,系统能够在保证响应速度的同时,最大化 GPU 利用率。解码阶段的任务会被放入 running 队列,接受调度器的持续监控和管理。 交换阶段(Swap Phase) 为了处理资源竞争,调度器实现了优雅的任务交换机制。当系统资源紧张时,调度器会识别优先级较低的任务,将它们暂时转移到 CPU 内存(swapped 队列),为急需资源的高优先级任务让路。这种动态调度机制确保了系统资源的最优利用,同时保证了服务质量。 这三个阶段通过精密的协作,构成了一个流畅的任务处理管道。调度器通过维护 waiting、running 和 swapped 三个队列的状态平衡,实现了类似操作系统页面调度的高效内存管理。每个阶段都配备了完善的监控和容错机制,确保了整个系统的稳定性和可靠性。 值得一提的是,vLLM 的调度系统还实现了优先级抢占、动态批处理等高级特性,这些机制共同保证了系统在高负载下依然能够提供稳定且高效的服务。整个调度过程就像一场精心编排的交响乐,每个组件都恰到好处地配合,共同奏响高性能服务的乐章。 3.1 scheduler 调度生命周期 图 2: vLLM 调度器状态队列示意图 5 3.2 _schedule_default调度逻辑 _schedule_default 方法是 vLLM 调度系统的指挥中心,它通过精心设计的流程来协调各类请求的处理。让我们逐步解析这个复杂而优雅的调度过程: (1) 预算初始化与资源盘点 # File: vllm/core/scheduler.py # 初始化调度预算 budget SchedulingBudget(token_budgetself.scheduler_config.max_num_batched_tokens,max_num_seqsself.scheduler_config.max_num_seqs, ) # 统计当前运行任务的资源占用 for seq_group in self.running:budget.add_num_seqs(seq_group.request_id,seq_group.get_max_num_running_seqs())这就像交通管理员在早高峰前先统计可用车道和当前道路占用情况。系统会创建一个预算对象,记录最大可处理的 token 数和序列数,并统计当前正在运行的任务占用的资源。 (2) 优先级调度策略 # File: vllm/core/scheduler.py # 如果没有交换出的请求,则处理新的预填充请求 if not self.swapped:prefills self._schedule_prefills(budget,curr_loras,enable_chunkingFalse)# 当启用优先级策略且无预填充任务时,执行优先级抢占 if len(prefills.seq_groups) 0 and self.scheduler_config.policy priority:self._schedule_priority_preemption(budget)这类似于交通管理系统的优先车道管理。系统优先处理已被交换出去的紧急任务,就像先让救护车通行。如果没有紧急任务,则开始处理新到达的请求。当采用优先级策略时,还会考虑是否需要让高优先级任务抢占资源。 (3) 解码任务调度 # File: vllm/core/scheduler.py # 仅在无预填充任务时调度解码任务 if len(prefills.seq_groups) 0:running_scheduled self._schedule_running(budget,curr_loras,enable_chunkingFalse)# 仅在无抢占和交换出时尝试恢复交换任务if len(running_scheduled.preempted) len(running_scheduled.swapped_out) 0:swapped_in self._schedule_swapped(budget, curr_loras)这就像管理正常行驶的车辆。只有在处理完紧急情况后,系统才会调度常规的解码任务。如果道路通畅(没有任务被抢占或交换出),还会尝试让一些临时停靠的车辆(被交换出的任务)重新上路。 (4) 状态更新与队列管理 # File: vllm/core/scheduler.py # 更新等待队列 self.waiting.extendleft(running_scheduled.preempted) # 更新运行队列 if len(prefills.seq_groups) 0:self.running.extend([s.seq_group for s in prefills.seq_groups]) self.running.extend(running_scheduled.decode_seq_groups_list) # 更新交换队列 self.swapped.extend(running_scheduled.swapped_out)这类似于实时更新交通状态。系统会更新各个队列的状态:被抢占的任务回到等待队列,新的任务进入运行队列,需要暂时让路的任务进入交换队列。 (5) 结果整合与输出 # File: vllm/core/scheduler.py return SchedulerOutputs(scheduled_seq_groupsscheduled_seq_groups,num_prefill_groupsnum_prefill_groups,num_batched_tokensbudget.num_batched_tokens budget.num_cached_tokens,blocks_to_swap_inswapped_in.blocks_to_swap_in,blocks_to_swap_outrunning_scheduled.blocks_to_swap_out,... )最后,系统会生成一份完整的调度报告,包含了所有需要执行的操作:哪些任务要执行,哪些内存块需要交换,以及各类统计信息。这就像交通指挥中心生成的实时路况报告,为下一个调度周期提供决策依据。 通过这种精密的调度机制,vLLM 能够在保证公平性的同时,最大化系统的吞吐量和响应速度。整个过程就像一个训练有素的交通指挥系统,让每个请求都能得到恰当的处理,保证了整个服务的高效运转。 3.3 预填充阶段的精密编排 预填充阶段就像一个精心设计的入场管理系统,需要确保每个请求都能得到合适的处理。让我们通过几个关键步骤来理解这个过程: (1) 初始检查与资源评估 # File: vllm/core/scheduler.py waiting_seqs seq_group.get_seqs(statusSequenceStatus.WAITING) assert len(waiting_seqs) 1, (Waiting sequence group should have only one prompt sequence.) num_new_tokens_uncached, num_new_tokens_cached (self._get_num_new_uncached_and_cached_tokens(seq_group, SequenceStatus.WAITING, enable_chunking, budget))这就像检票员在入场时检查门票。系统首先确认每个等待组只包含一个提示序列,然后计算需要处理的新token数量,区分哪些需要重新计算(uncached),哪些可以直接使用缓存(cached)。 (2) 容量限制检查 # File: vllm/core/scheduler.py prompt_limit self._get_prompt_limit(seq_group) if num_new_tokens prompt_limit:logger.warning(Input prompt (%d tokens) is too long and exceeds limit of %d, num_new_tokens, prompt_limit)for seq in waiting_seqs:seq.status SequenceStatus.FINISHED_IGNOREDignored_seq_groups.append(seq_group)waiting_queue.popleft()continue这类似于场馆的容量管理。如果一个请求太大(token数超过限制),就像一个太大的团队无法进入会场一样,系统会将其标记为已忽略,并移出等待队列。 (3) 内存分配评估 # File: vllm/core/scheduler.py can_allocate self.block_manager.can_allocate(seq_group, num_lookahead_slotsnum_lookahead_slots) if can_allocate AllocStatus.LATER:break elif can_allocate AllocStatus.NEVER:logger.warning(Input prompt (%d tokens) lookahead slots (%d) is too long,num_new_tokens, num_lookahead_slots)这就像检查场地是否有足够的座位。系统会评估是否有足够的内存块来容纳这个请求。如果暂时没有空间(LATER),就等待下次尝试;如果永远无法容纳(NEVER),则将请求标记为无法处理。 (4) LoRA 资源管理 # File: vllm/core/scheduler.py if self.lora_enabled:if (lora_int_id 0 and lora_int_id not in curr_lorasand len(curr_loras) self.lora_config.max_loras):leftover_waiting_sequences.appendleft(seq_group)waiting_queue.popleft()continue这类似于特殊设备的分配管理。如果请求需要使用LoRA(一种特殊的模型适配技术),系统会检查是否还有可用的LoRA槽位。如果没有,该请求会被暂时搁置。 (5) 预算控制 # File: vllm/core/scheduler.py if (budget.num_batched_tokens self.scheduler_config.max_num_batched_tokens):breaknum_new_seqs seq_group.get_max_num_running_seqs() if num_new_tokens_uncached 0 or not budget.can_schedule(num_new_tokensnum_new_tokens_uncached,num_new_seqsnum_new_seqs, ):break这就像控制场地的实时容量。系统会严格监控已分配的资源是否达到上限,包括总token数和序列数,确保不会超出系统的处理能力。 (6) 资源分配与状态转换 # File: vllm/core/scheduler.py waiting_queue.popleft() self._allocate_and_set_running(seq_group)seq_groups.append(ScheduledSequenceGroup(seq_groupseq_group,token_chunk_sizenum_new_tokens)) budget.add_num_batched_tokens(seq_group.request_id,num_batched_tokensnum_new_tokens_uncached,num_cached_tokensnum_new_tokens_cached, )这是最后的入场阶段。当所有检查都通过后,系统会正式为请求分配资源,将其状态更新为运行中,并记录相应的资源使用情况。 (7) passed_delay均衡 模型在做推理时waiting 队列中是源源不断有 seq_group 进来的一旦 vLLM 选择调度 waiting 队列它就会停下对 running/swapped 中 seq_group 的 decode 处理转而去做 waiting 中 seq_group 的 prefill也即vLLM 必须在新来的 seq_group 和已经在做推理的 seq_group 间取得一种均衡既不能完全不管新来的请求也不能耽误正在做推理的请求。_passed_delay 就是用来做这个判断的。 # File: vllm/core/scheduler.py def _passed_delay(self, now: float) - bool:if self.prev_prompt:self.last_prompt_latency now - self.prev_timeself.prev_time, self.prev_prompt now, Falseif self.scheduler_config.delay_factor 0 and self.waiting:earliest_arrival_time min([e.metrics.arrival_time for e in self.waiting])passed_delay ((now - earliest_arrival_time) (self.scheduler_config.delay_factor * self.last_prompt_latency)or not self.running)else:passed_delay Truereturn passed_delayprev_prompt 和 prev_time 用于记录上一个请求的执行时间从而动态计算 last_prompt_latency 以调整调度速率。这种延迟控制机制可以防止过度调度减少 GPU 负载。 当延迟条件满足时_schedule_prefills 会获取 waiting 队列中第一个请求的 token 数量并通过 _get_num_new_tokens 方法来确定这个请求所需的 token 数量。随后该 token 数量与 _get_prompt_limit 限制值进行比较以确保请求不会超出模型的最大 token 负载。 # File: vllm/core/scheduler.py num_new_tokens self._get_num_new_tokens(seq_group, SequenceStatus.WAITING, enable_chunking, budget) if num_new_tokens self._get_prompt_limit(seq_group):ignored_seq_groups.append(seq_group)self.waiting.popleft()continue若 can_allocate 返回 AllocStatus.LATER表明当前 GPU 资源不足调度器将等待下次机会若返回 AllocStatus.NEVER则说明该请求太大无法分配调度器将忽略该请求并将其移出等待队列。 (8) 资源分配与状态转换 # File: vllm/core/scheduler.py def _allocate_and_set_running(self, seq_group: SequenceGroup) - None:self.block_manager.allocate(seq_group)for seq in seq_group.get_seqs(statusSequenceStatus.WAITING):seq.status SequenceStatus.RUNNINGallocate 函数通过 block_manager 的内存管理功能为请求在 GPU 上分配所需的内存空间从而确保其可以顺利进入解码阶段。 通过这种细致的分层管理,vLLM能够高效地处理大量并发请求,既确保了资源的最优利用,又保证了每个请求都能得到公平的处理机会。整个预填充阶段就像一个精密的入场管理系统,通过多重检查和平衡机制,确保系统的稳定运行和最佳性能。 3.4 解码阶段的精密调度 解码阶段是 vLLM 处理请求的核心环节就像一条高效的生产线需要精确地控制每个环节的运转。让我们深入理解这个复杂而优雅的过程 (1) 初始化与缓存清理 # File: vllm/core/scheduler.py ret: SchedulerRunningOutputs \self._scheduler_running_outputs_cache[self.cache_id].get_object() ret.blocks_to_swap_out.clear() ret.blocks_to_copy.clear() ret.decode_seq_groups.clear() ret.prefill_seq_groups.clear()这就像生产线开始新的班次前的准备工作。系统会清理所有临时状态为新一轮调度做好准备。通过使用对象池(cache)来复用对象避免频繁创建新对象带来的性能开销。 (2) 资源评估与任务获取 # File: vllm/core/scheduler.py running_queue self.running while running_queue:seq_group running_queue[0]num_uncached_new_tokens, _ (self._get_num_new_uncached_and_cached_tokens(seq_group, SequenceStatus.RUNNING, enable_chunking, budget))这类似于生产线上的任务评估。系统会检查每个正在运行的任务组评估其资源需求。特别的是在解码阶段我们不需要考虑缓存的 tokens因为它们在预填充阶段就已经处理完毕。 (3) 异步处理保护 # File: vllm/core/scheduler.py if self.use_async_output_proc and seq_group.seqs[0].get_len() self.scheduler_config.max_model_len:self._async_stopped.append(seq_group)continue这就像生产线上的安全检查点。当使用异步处理器时系统会检查序列长度是否超出限制以防止内存溢出。这种保护机制确保了系统的稳定性。 (4) 资源竞争处理 # File: vllm/core/scheduler.py while not self._can_append_slots(seq_group, enable_chunking):# 确定牺牲者序列if running_queue:victim_seq_group running_queue.pop() # 选择优先级最低的序列组else:victim_seq_group seq_group # 没有其他可抢占的序列抢占当前序列cont_loop False这类似于生产线上的资源调度。当资源不足时系统需要决定哪些任务需要暂时让出资源。它会优先选择优先级较低的任务组作为牺牲者就像在繁忙时段将部分生产线暂时切换到更紧急的订单。 (5) 抢占执行与状态转换 # File: vllm/core/scheduler.py if do_preempt:preempted_mode self._preempt(victim_seq_group, blocks_to_swap_out)if preempted_mode PreemptionMode.RECOMPUTE:preempted.append(victim_seq_group)else:swapped_out.append(victim_seq_group)这就像生产线上的任务切换。系统会根据具体情况决定是将任务暂存(swap out)还是标记为需要重新计算(recompute)。这种灵活的处理机制确保了资源的最优利用。 (6) 任务调度与资源分配 # File: vllm/core/scheduler.py self._append_slots(seq_group, blocks_to_copy, enable_chunking) scheduled_seq_group.seq_group seq_group if is_prefill:scheduled_seq_group.token_chunk_size num_running_tokensprefill_seq_groups.append(scheduled_seq_group) else:scheduled_seq_group.token_chunk_size 1decode_seq_groups.append(scheduled_seq_group)这类似于生产线上的实际加工过程。系统会为任务分配所需的资源槽位并根据任务类型预填充或解码设置不同的处理参数。解码任务通常每次只处理一个 token而预填充任务可能会批量处理多个 tokens。 (7) 资源统计更新 # File: vllm/core/scheduler.py budget.add_num_batched_tokens(seq_group.request_id, num_running_tokens) if enable_chunking:num_running_seqs seq_group.get_max_num_running_seqs()budget.add_num_seqs(seq_group.request_id, num_running_seqs)这就像生产线上的资源使用统计。系统会实时更新资源使用情况包括已批处理的 tokens 数量和运行中的序列数。当启用分块处理时还需要额外更新序列数统计。 通过这种精密的调度机制vLLM 能够在保证公平性的同时最大化系统的吞吐量和响应速度。整个解码阶段就像一条精心设计的智能生产线通过灵活的资源调度和任务管理确保了系统的高效运转。 3.5 交换阶段的精密调度 交换阶段是 vLLM 内存管理的关键环节就像一个智能仓储系统需要在 CPU 和 GPU 内存之间灵活调度资源。让我们深入理解这个复杂而精密的过程 (1) 初始化与资源准备 # File: vllm/core/scheduler.py blocks_to_swap_in: List[Tuple[int, int]] [] blocks_to_copy: List[Tuple[int, int]] [] decode_seq_groups: List[ScheduledSequenceGroup] [] prefill_seq_groups: List[ScheduledSequenceGroup] [] infeasible_seq_groups: List[SequenceGroup] []这就像仓库管理员准备工作清单。系统会初始化各种任务列表包括需要从 CPU 加载到 GPU 的内存块、需要复制的数据块以及不同类型的任务组。 (2) 可行性评估 # File: vllm/core/scheduler.py is_prefill seq_group.is_prefill() alloc_status self.block_manager.can_swap_in(seq_group,self._get_num_lookahead_slots(is_prefill, enable_chunking)) if alloc_status AllocStatus.LATER:break elif alloc_status AllocStatus.NEVER:logger.warning(Failing the request %s because theres not enough kv cache blocks,seq_group.request_id)这类似于仓库管理员评估货物存放可能性。系统会检查是否有足够的 GPU 内存来容纳被交换出的任务。如果暂时没有空间(LATER)就等待下次机会如果永远无法容纳(NEVER)则将任务标记为无法执行。 (3) LoRA 资源检查 # File: vllm/core/scheduler.py if self.lora_enabled:if (lora_int_id 0 and (lora_int_id not in curr_loras)and len(curr_loras) self.lora_config.max_loras):leftover_swapped.appendleft(seq_group)swapped_queue.popleft()continue这就像检查特殊设备的可用性。如果任务需要使用 LoRA 适配器系统会检查是否有可用的 LoRA 槽位。如果没有该任务会被暂时保留在交换队列中。 (4) 资源预算评估 # File: vllm/core/scheduler.py num_new_seqs seq_group.get_max_num_running_seqs() num_new_tokens_uncached, num_new_tokens_cached (self._get_num_new_uncached_and_cached_tokens(seq_group, SequenceStatus.SWAPPED, enable_chunking, budget))if num_new_tokens_uncached 0 or not budget.can_schedule(num_new_tokensnum_new_tokens_uncached,num_new_seqsnum_new_seqs):break这类似于评估仓库的剩余容量。系统会计算任务所需的资源包括新序列数量和token数量确保在预算范围内才进行调度。 (5) 执行交换操作 # File: vllm/core/scheduler.py swapped_queue.popleft() self._swap_in(seq_group, blocks_to_swap_in) self._append_slots(seq_group, blocks_to_copy, enable_chunking)这就像实际执行货物搬运。系统会将任务从 CPU 内存移回 GPU并为其分配必要的计算资源。这个过程包括数据传输和内存分配两个关键步骤。 (6) 任务分类与资源记录 # File: vllm/core/scheduler.py if is_prefill:prefill_seq_groups.append(ScheduledSequenceGroup(seq_group,token_chunk_sizenum_new_tokens_uncached num_new_tokens_cached,)) else:decode_seq_groups.append(ScheduledSequenceGroup(seq_group, token_chunk_size1))这类似于货物分类入库。系统会根据任务类型预填充或解码将其放入相应的处理队列并设置适当的处理参数。 (7) 资源统计更新 # File: vllm/core/scheduler.py budget.add_num_batched_tokens(seq_group.request_id,num_batched_tokensnum_new_tokens_uncached,num_cached_tokensnum_new_tokens_cached, ) budget.add_num_seqs(seq_group.request_id, num_new_seqs)这就像更新仓库库存记录。系统会更新资源使用统计包括已使用的token数量和序列数确保资源使用始终在可控范围内。 通过这种精密的交换机制vLLM 实现了 CPU 和 GPU 内存之间的高效协同既保证了资源的充分利用又确保了任务的连续性。整个交换阶段就像一个智能仓储系统通过灵活的调度策略实现了计算资源的最优配置。 4. 资源管理与调度策略 4.1 预算管理系统设计 SchedulingBudget 类是 vLLM 资源管理的核心组件它就像一个精密的预算管理系统负责追踪和控制系统的资源使用。让我们深入理解它的设计 (1) 核心资源指标 # File: vllm/core/scheduler.py dataclass class SchedulingBudget:token_budget: int # 总的token预算max_num_seqs: int # 最大序列数限制_num_cached_tokens: int 0 # 已缓存的token数_num_batched_tokens: int 0 # 实际批处理的token数_num_curr_seqs: int 0 # 当前序列数这就像企业的预算系统定义了关键的资源限制总预算(token_budget)、人员限制(max_num_seqs)以及当前的资源使用状况。系统通过这些指标来确保资源使用不会超出限制。 (2) 请求追踪机制 _request_ids_num_batched_tokens: Set[str] field(default_factoryset) _request_ids_num_curr_seqs: Set[str] field(default_factoryset)这类似于预算系统中的交易记录追踪。系统使用集合来记录已经处理过的请求ID避免重复计算同一个请求的资源消耗。这种设计特别适合处理分布式环境下的资源统计。 (3) 调度可行性检查 # File: vllm/core/scheduler.py def can_schedule(self, *, num_new_tokens: int, num_new_seqs: int):assert num_new_tokens 0assert num_new_seqs ! 0return (self.num_batched_tokens num_new_tokens self.token_budgetand self.num_curr_seqs num_new_seqs self.max_num_seqs)这就像预算审批过程。在添加新的任务前系统会检查是否有足够的资源来处理它。检查包括两个方面 token数量是否在预算范围内序列数是否超过系统限制 (4) 资源分配与回收 # File: vllm/core/scheduler.py def add_num_batched_tokens(self, req_id: str,num_batched_tokens: int,num_cached_tokens: int 0):if req_id in self._request_ids_num_batched_tokens:returnself._request_ids_num_batched_tokens.add(req_id)self._num_batched_tokens num_batched_tokensself._num_cached_tokens num_cached_tokensdef subtract_num_batched_tokens(self, req_id: str, num_batched_tokens: int):if req_id in self._request_ids_num_batched_tokens:self._request_ids_num_batched_tokens.remove(req_id)self._num_batched_tokens - num_batched_tokens这类似于预算的分配和回收流程 add_num_batched_tokens为新请求分配资源同时记录请求ID避免重复计算subtract_num_batched_tokens在请求完成或被中断时回收资源 (5) 序列数管理 # File: vllm/core/scheduler.py def add_num_seqs(self, req_id: str, num_curr_seqs: int):if req_id in self._request_ids_num_curr_seqs:returnself._request_ids_num_curr_seqs.add(req_id)self._num_curr_seqs num_curr_seqsdef subtract_num_seqs(self, req_id: str, num_curr_seqs: int):if req_id in self._request_ids_num_curr_seqs:self._request_ids_num_curr_seqs.remove(req_id)self._num_curr_seqs - num_curr_seqs这就像人力资源管理系统负责跟踪当前正在处理的序列数量 添加新序列时会检查是否已经计入统计移除序列时会相应减少计数 (6) 资源状态查询 # File: vllm/core/scheduler.py property def num_batched_tokens(self):return self._num_batched_tokensproperty def remaining_token_budget(self):return self.token_budget - self.num_batched_tokens这类似于预算系统的报表功能提供了查询当前资源使用状况的接口 已使用的token数量剩余可用的token预算当前序列数等关键指标 通过这种精密的预算管理机制vLLM 能够准确地追踪和控制系统资源的使用情况确保系统在高负载下依然能够稳定运行。整个预算管理系统就像一个高效的企业财务系统通过严格的资源控制和灵活的分配策略实现了计算资源的最优利用。 4.2 优先级调度和抢占策略的精密实现 优先级调度和抢占机制是 vLLM 处理资源竞争的核心策略让我们深入理解这个精密的调度过程 (1) 队列初始化与优先级排序 waiting_queue self.waiting running_queue deque(sorted(self.running, keyself._get_priority)) blocks_to_swap_out: List[Tuple[int, int]] [] force_preemption_count 0这就像应急指挥中心的初始准备工作 获取当前等待的请求队列将运行中的任务按优先级排序准备记录需要暂时撤离的资源初始化强制抢占计数器 (2) 优先级反转检测 if waiting_queue:seq_group waiting_queue.popleft()num_new_seqs seq_group.get_max_num_running_seqs()num_new_tokens_uncached, _ (self._get_num_new_uncached_and_cached_tokens(seq_group, SequenceStatus.WAITING, False, budget))这类似于应急响应中的情况评估 检查是否有等待中的请求评估新请求的资源需求序列数和token数准备进行优先级比较 (3) 抢占条件评估 # File: vllm/core/scheduler.py while running_queue and self._get_priority(running_queue[-1]) self._get_priority(seq_group):can_allocate self.block_manager.can_allocate(seq_group)if (num_new_tokens_uncached 0and can_allocate AllocStatus.OKand budget.can_schedule(num_new_tokensnum_new_tokens_uncached,num_new_seqsnum_new_seqs,)):break这就像应急处理中的资源调配决策 检查是否存在优先级反转低优先级任务占用资源而高优先级任务等待评估是否有足够的资源来处理新请求如果资源充足则无需进行抢占 (4) 受害者选择与资源回收 # File: vllm/core/scheduler.py vseq_group running_queue.pop() num_running_tokens_uncached, _ (self._get_num_new_uncached_and_cached_tokens(vseq_group, SequenceStatus.RUNNING, False, budget)) budget.subtract_num_batched_tokens(vseq_group.request_id, num_running_tokens_uncached) num_running_seqs vseq_group.get_max_num_running_seqs() budget.subtract_num_seqs(vseq_group.request_id, num_running_seqs)这类似于应急情况下的资源重新分配 选择优先级最低的运行中任务作为受害者计算需要回收的资源数量从预算中扣除这些资源更新序列计数 (5) 抢占执行与状态转换 self._preempt(vseq_group, blocks_to_swap_out) waiting_queue.appendleft(vseq_group) force_preemption_count 1这就像执行应急预案 执行实际的抢占操作将任务从 GPU 移出将被抢占的任务放回等待队列前端记录抢占次数以进行监控 (6) 队列重排序与状态更新 waiting_queue.appendleft(seq_group) waiting_queue deque(sorted(waiting_queue, keyself._get_priority)) self.waiting waiting_queue self.running running_queue这类似于应急处理后的现场恢复 将触发抢占的请求放回等待队列重新按优先级排序所有等待的请求更新系统的队列状态 通过这种精密的优先级调度和抢占机制vLLM 能够在资源竞争激烈的情况下保证高优先级任务的及时处理同时尽可能减少对低优先级任务的影响。整个机制就像一个高效的应急响应系统通过合理的资源调配和任务管理确保了系统的公平性和效率。 4.3 抢占机制的精密实现 vLLM 的抢占机制提供了两种处理模式重新计算(Recompute)和交换(Swap)。这种灵活的设计让系统能够根据不同场景选择最优的处理策略。让我们深入理解这个精密的抢占过程 (1) 抢占模式选择 if self.user_specified_preemption_mode is None:if seq_group.get_max_num_running_seqs() 1:preemption_mode PreemptionMode.RECOMPUTEelse:preemption_mode PreemptionMode.SWAP这就像应急预案的选择过程 默认情况下系统会根据序列组的特征自动选择最优策略对于单序列任务优先选择重新计算模式因为它的开销较小对于多序列任务如束搜索由于当前不支持重新计算会选择交换模式 (2) 用户自定义模式处理 elif self.user_specified_preemption_mode swap:preemption_mode PreemptionMode.SWAP else:preemption_mode PreemptionMode.RECOMPUTE这类似于应急响应中的人工干预 系统允许用户指定特定的抢占模式如果用户明确要求使用交换模式系统会遵循这个选择其他情况下默认使用重新计算模式 (3) 性能监控与警告机制 if self.num_cumulative_preemption % 50 0:logger.warning(Sequence group %s is preempted by %s mode because there is not enough KV cache space. This can affect the end-to-end performance. Increase gpu_memory_utilization or tensor_parallel_size to provide more KV cache memory. total_num_cumulative_preemption%d, seq_group.request_id,preemption_mode, self.num_cumulative_preemption 1)这就像系统的健康监控 每50次抢占操作会触发一次警告提醒管理员系统可能需要调整资源配置建议增加GPU内存利用率或张量并行度来缓解抢占压力记录累计抢占次数以便跟踪系统状态 (4) 抢占执行 if preemption_mode PreemptionMode.RECOMPUTE:self._preempt_by_recompute(seq_group) elif preemption_mode PreemptionMode.SWAP:self._preempt_by_swap(seq_group, blocks_to_swap_out) else:raise AssertionError(Invalid preemption mode.)这类似于应急预案的实际执行 重新计算模式放弃当前进度后续需要从头计算交换模式将数据暂存到CPU内存保留计算进度严格的错误检查确保只执行有效的抢占模式 通过这种精密的抢占机制vLLM 实现了资源的灵活调度 通过自动选择最优抢占模式最小化性能开销提供用户自定义选项满足特定场景需求内置监控机制及时发现系统瓶颈支持多种抢占策略适应不同的任务特征 这种设计就像一个智能的应急处理系统既能自动选择最优方案又保留了人工干预的可能同时通过持续监控确保系统的健康运行。 5. vLLM 调度系统总结 vLLM 的调度系统是一个精心设计的多层次架构通过多个协同工作的组件实现了高效的资源管理和任务调度。让我们从整体到细节来回顾这个系统。 5.1 核心架构设计 调度系统的基础建立在三个关键队列之上。waiting 队列负责存放新到达的请求running 队列管理正在执行的任务而 swapped 队列则暂存被交换出的任务。这种三队列设计为系统提供了灵活的任务状态管理能力使其能够有效应对各种负载情况。 5.2 调度流程的精密编排 整个调度过程分为三个主要阶段每个阶段都有其独特的职责。在预填充阶段系统会对新请求进行资源评估检查容量限制和内存可用性同时进行 LoRA 资源管理最后执行预算控制和资源分配。 进入解码阶段后系统的重点转向管理运行中任务的资源使用。这包括处理异步任务和长度限制执行资源竞争处理以及维护任务状态和资源统计。 在交换阶段系统负责在 CPU 和 GPU 内存间进行任务迁移。它会评估交换操作的可行性执行数据传输和资源重分配并及时更新系统状态和资源记录。 5.3 资源管理的创新机制 系统通过 SchedulingBudget 类实现了精确的资源控制。这个类不仅维护着 token 和序列数预算还负责追踪请求级别的资源使用。它提供了完整的资源分配和回收机制并通过实时监控确保系统资源的高效利用。 5.4 优先级调度与抢占策略 为了处理资源竞争系统实现了两种抢占模式。Recompute 模式适用于单序列任务因其开销较小而被优先选用。而 Swap 模式则适用于多序列任务它能够保留计算进度虽然开销较大但更适合某些特定场景。 这种灵活的抢占机制确保了高优先级任务能够及时获得资源同时也保证了系统资源的最优利用和任务处理的连续性。通过精心的设计系统在处理资源竞争时既保证了效率又维护了公平性。 5.5 性能优化与监控 在性能优化方面系统采用了多项创新机制。对象池的复用有效减少了内存分配开销延迟控制机制避免了过度调度而批处理优化则显著提高了系统吞吐量。同时完善的实时监控和警告机制确保了系统运行的稳定性。 通过这些精密的设计vLLM 的调度系统实现了资源的高效利用、任务的灵活管理、服务的可靠保障和性能的持续优化。这种多层次、多维度的调度架构使 vLLM 能够在处理大规模并发请求时保持稳定高效的性能为 LLM 服务提供了可靠的基础设施支持。 6. 参考资料 [1] vLLM Team, vLLM Documentation, vLLM Official Documentation, 2024. [Online]. Available: https://docs.vllm.ai/en/latest/ [2] vLLM Project Contributors, vLLM: Easy, Fast, and Cheap LLM Serving, GitHub Repository, 2024. [Online]. Available: https://github.com/vllm-project/vllm [3] vLLM Team, Serving LLMs at Scale with vLLM, vLLM Blog, Jun. 2023. [Online]. Available: https://blog.vllm.ai/2023/06/20/vllm.html [4] vLLM Community, vLLM Discussions, GitHub Discussions, 2024. [Online]. Available: https://github.com/vllm-project/vllm/discussions [5] Y. Feng, vLLM Diagram Overview, Personal Blog, Sep. 2024. [Online]. Available: https://fy2462.**github**.io/2024/09/vllm-diagram-overview/ [6] PaddleJitLab, vLLM Source Code Analysis: Scheduler, GitHub Repository, 2024. [Online]. Available: https://github.com/PaddleJitLab/CUDATutorial/blob/develop/docs/16_vllm_source_code/03_scheduler.md
http://www.hkea.cn/news/14525195/

相关文章:

  • 做网站打广告图片素材北京网站建设认知
  • 域名注册网站免费网站排名应该怎么做
  • 如何给网站做关键字怎么找网站站长
  • 重庆中小企业网站建设公司ppt哪个网站做的好
  • 湖南宁乡建设局网站两学一做微网站交流
  • 个人网站方案建设书网站seo快速优化
  • 网站建设要哪些seo网络软件开发专业是做什么的
  • 网站建设优化服务策划响应式网站建设准备
  • 山东省建设工程质量监督总站网站网页设计模板图片
  • 网站名称填写什么深圳高端设计公司名单
  • 简单的网站源码新东方烹饪学校学费价目表
  • 为什么要建设门户网站长兴县建设局网站
  • 网络维护网站美工惠州网站建设哪家强
  • 加盟网网站建设标签下载wordpress
  • php做的静态网站怎么加密个人智慧团建系统登录
  • 有口碑的番禺网站建设ui设计职业培训机构
  • 建网站解决方案seo网站推广价格
  • 专门做网站的公司与外包公司有哪些新乡市工程建设信息网
  • 自己怎么做网站优化西安手机网站建设公司排名
  • 佛山建网站哪家好网站网站开发逻辑
  • cms建站仓储网站开发
  • 成都营销型网站建设公司广州新闻报道
  • 做 个收废品网站做百度推广怎么做才能有电话
  • 有哪些网站做的很好wordpress压缩数据库查询
  • 网站建设需要材料关于旅游案例的网站
  • 建设部网站投诉如何注册遵义住房和城乡建设局网站
  • 如何在学校网站上做链接免费公司介绍网站怎么做
  • 经典网站赏析信息化工作总结 网站建设
  • 嵊州建设银行取款网站大兴建设网站公司
  • 佛山做推广网站的怎样推广才能让更多人看到