上一篇文章中我们介绍了 vLLM 调度器的预处理工作,我们已经知道了在进行调度之前,数据会被预处理然后用 SequenceGroup 对象进行封装。在这篇文章中,我们将会介绍 vLLM 调度器的具体调度策略。
本系列的代码基于 vLLM 的 0.6.3 版本介绍
vLLM 调度器是一个专为优化生成式模型而设计的调度器。与普通的任务调度器相比,它不仅要管理多个请求的排队和处理,还要动态分配 GPU 和 CPU 内存、控制数据的加载与交换,确保系统在不同负载下均能高效运行。
本文将通过详细的源码解析,逐步带领读者深入理解 vLLM 调度器的设计与实现。我们将从基础概念、核心组件、调度策略以及资源管理等多方面展开,通过实例和源码逐步揭示调度器如何在实际应用中高效管理请求。
在生成式模型的运行过程中,调度器的核心任务是高效地管理资源(主要是 GPU 和 CPU 内存)和控制请求的执行顺序。生成式模型通常需要处理多个并发请求,特别是在大规模部署环境中,这些请求可能来自不同的用户或任务,并且拥有不同的处理需求和优先级。
vLLM 调度器的设计旨在优化多任务环境中的 GPU 和 CPU 资源利用率。调度器通过以下几种机制来实现该目标:
vLLM 调度器主要处理两种类型的请求:
调度器会根据请求类型的不同,将它们放置在相应的队列中并进行优先级控制。通过对这两种请求进行分离处理,调度器可以更好地管理模型的生成过程。
在多任务环境中,调度器为每个请求分配优先级。在 vLLM 中,优先级主要由任务的重要性和到达时间决定。优先级调度确保高优先级的任务不被低优先级的任务阻塞,以便资源分配更加合理。
def _get_priority(self, seq_group: SequenceGroup) -> Tuple[Optional[int], float]:
""" 获取 SequenceGroup 的优先级:首先根据用户定义的优先级值,其次按到达时间排序。 """ return seq_group.priority, seq_group.arrival_time
上面的代码段展示了调度器如何获取 SequenceGroup 的优先级:首先考虑用户指定的优先级值,其次按照到达时间排序。这一逻辑帮助调度器将高优先级任务快速安排到合适的计算队列中。