1. vllm 的核心优势——PagedAttention

PagedAttention是vLLM最核心的技术创新,它解决了大型语言模型推理过程中的内存管理难题。

1.1 传统 attention 遇到的挑战

在标准Transformer推理中,存在两个关键阶段:

  • 预填充阶段(Prefill):处理输入提示,生成所有token的KV缓存
  • 解码阶段(Decode):生成新token,每次只处理一个新token但需要访问所有之前的KV缓存
    传统方法中,KV缓存以连续内存块分配,导致以下问题:
  • 内存浪费:预先为最大序列长度分配内存,即使实际序列更短
  • 内存碎片:不同长度的请求会导致严重的内存碎片
  • 批处理限制:不同长度序列很难在一个批次中高效处理
  • 并发瓶颈:同时处理的序列数量受到严格限制

1.2 PagedAttention 工作原理

PagedAttention引入了"分块存储"的概念:

  • 物理块(Physical Blocks):将GPU内存分成固定大小的物理块(如16个token)
  • 逻辑块(Logical Blocks):每个序列的KV缓存被分割成逻辑块
  • 块表(Block Table):维护逻辑块到物理块的映射关系,类似操作系统页表

核心数据结构

  1. 块表:每个激活序列维护一个块表,记录其逻辑块映射到哪些物理块
  2. 物理块池:所有可用物理块的集合,由内存管理器统一分配
  3. 块缓存(Block Cache):通过索引快速访问KV缓存值

注意力计算流程

  1. 将注意力查询(Q)与多个物理块中的键(K)计算相似度
  2. 通过块表找到当前序列对应的所有物理块
  3. 计算注意力权重并与对应的值(V)加权求和
  4. 生成新token并更新块表

内存管理策略

  • 按需分配:只为实际序列长度分配物理块,不再预分配最大长度
  • 细粒度控制:以块为单位分配内存,减少碎片
  • 共享物理块:不同请求可以共享相同的物理块(前缀相同时)
  • 内存回收:序列完成后立即回收物理块,供其他序列使用

2. 分布式执行逻辑

在 vllm/config.py 的 ParallelConfig__post_init__方法中,vLLM会根据以下条件自动选择使用Ray还是其他执行后端:

   if self.distributed_executor_backend is None and self.world_size > 1:
       from vllm.executor import ray_utils
       backend = "mp"  # 默认使用多进程
       ray_found = ray_utils.ray_is_available()
       if current_platform.is_neuron():
           backend = "uni"  # neuron使用单进程控制多设备
       elif (current_platform.is_cuda()
             and cuda_device_count_stateless() < self.world_size):
           # 如果本地GPU数量小于所需的world_size,必须使用Ray进行多节点部署
           if not ray_found:
               raise ValueError("Unable to load Ray which is "
                               "required for multi-node inference, "
                               "please install Ray with `pip install "
                               "ray`.") 
           backend = "ray"
       elif ray_found:
           # 如果Ray已初始化且存在placement group,使用Ray
           if self.placement_group:
               backend = "ray"
           else:
               from ray import is_initialized as ray_is_initialized
               if ray_is_initialized():
                   from ray.util import get_current_placement_group
                   if get_current_placement_group():
                       backend = "ray"
       self.distributed_executor_backend = backend

执行器的选择逻辑:

在 vllm/executor 文件夹下,vllm 一共有四种执行器
image.png

执行器描述
单进程执行器(UniProcExecutor)用途: 单GPU/单设备场景,所有计算在同一进程中
何时使用: 当模型适合单个GPU且world_size=1时
代码标识: distributed_executor_backend="uni"
特点: 最简单的执行器,无分布式开销
多进程执行器(MultiprocessingDistributedExecutor)用途: 单节点多GPU场景
何时使用: 当模型需要多个GPU但都在同一台机器上时
代码标识: distributed_executor_backend="mp"
特点: 使用Python原生的多进程通信;适用于单机器多GPU场景;每个GPU一个Python进程;相比Ray开销更小
Ray分布式执行器(RayDistributedExecutor)用途: 多节点分布式场景
何时使用: 当模型太大不适合单节点,或需要跨多节点部署时
代码标识: distributed_executor_backend="ray"
特点:
基于Ray分布式计算框架
支持跨节点部署
提供高级资源管理和容错特性
支持任务队列和弹性扩展
外部启动器执行器(External Launcher)用途: 与外部分布式框架集成的场景
何时使用: 当使用torchrun等外部工具管理分布式环境时
代码标识: distributed_executor_backend="external_launcher"
特点:
允许外部工具(如torchrun)来管理进程创建
vLLM只负责特定设备上的执行
适用于与现有分布式训练基础设施集成的场景

vLLM有一套智能的自动选择逻辑,基于以下因素选择合适的执行器:

  1. 硬件平台: 在不同平台上有不同的默认行为
    • 在Neuron硬件上默认使用uni
    • 在Intel XPU或TPU上强制使用ray
  2. GPU可用性:
    • 如果本地可用GPU数量小于所需的world_size,使用ray
    • 否则默认使用mp
  3. Ray环境:
    • 如果已存在Ray初始化环境或placement group,使用ray
    • 如果设置了placement_group参数,使用ray

3. Ray在vLLM中的核心价值

  1. 分布式资源管理

    • Ray提供了统一的资源管理层,自动处理GPU、CPU、内存等资源的分配
    • 支持跨节点动态调度,不需要手动指定哪个进程在哪个节点上运行
  2. 更高层次的抽象

    • 相比直接使用NCCL仅提供通信原语,Ray提供了任务、角色(Actor)的概念
    • 使vLLM能够更容易地表达复杂的工作流,如张量并行和流水线并行的组合
  3. 统一的有状态和无状态计算模型

    • Ray Actor模型适合管理持久化状态(如KV缓存、模型权重)
    • Ray任务模型适合处理无状态的操作(如请求调度、张量操作)
    • 这正好匹配了LLM推理中有状态(模型)和无状态(请求)的混合特性
  4. 内置容错机制

    • Ray提供自动的工作节点故障检测和恢复
    • 对于长时间运行的推理服务至关重要
  5. 通信层优化

    • Ray确实简化了NCCL的使用,但不仅限于此
    • vLLM通过Ray可以更容易地实现自定义的通信模式,如PagedAttention中的数据传输
  6. 部署灵活性

    • 从单机扩展到多机无需修改代码
    • 支持异构集群(不同GPU类型混合部署)
    • 与云平台和Kubernetes集成更简单
  7. 调度优化

    • Ray的调度器针对异步和并行任务进行了优化
    • 有助于vLLM实现连续批处理(continuous batching)和预填充(prefill)优化

如果vLLM直接使用NCCL而不是Ray:

  • 需要自行管理进程创建、终止和故障处理
  • 需要手动实现资源分配和节点间协调
  • 缺乏高级调度功能来优化推理请求处理
  • 扩展到新硬件平台(TPU、NeuronCore等)更困难

本质上,Ray让vLLM能够专注于模型推理的核心逻辑,而不必处理低级分布式系统的复杂性。这使得vLLM能够更高效地实现其PagedAttention和连续批处理等创新,同时保持对各种部署环境的适应性。