vLLM 学习一:vLLM 架构

vLLM 入口(Entrypoints)

vLLM 主要提供两种推理模式,分别针对高吞吐量的离线批处理高并发的在线服务

  1. 离线推理模式 (Offline Inference)

    • 核心接口:直接使用 vllm.LLM 类。
    • 工作方式:用户在 Python 脚本中实例化 LLM 类,通过 llm.generate() 输入一批数据。该模式是同步执行的,旨在一次性处理大量数据,最大化吞吐量。
  2. 在线服务模式 (Online Serving)

    • 核心接口:通常通过命令行(vllm serve)启动 OpenAI-compatible API Server
    • 底层实现:在代码层面,API Server 并不直接使用 LLM 类,而是使用 vllm.engine.AsyncLLMEngine 类。
    • 工作方式:这是一个异步服务,能够处理来自客户端(如 ChatGPT 网页端或 App)的高并发 HTTP 请求,支持流式输出(Streaming),并提供与 OpenAI 完全兼容的 REST API 接口,也是最常用的方式。

下面是两种模式的示例图:

LLM 类

LLM 类提供了若干 Python API,用于进行离线推理,这种方式在场内的适配和部署场景中用的并不多,这里给出一个简单的示例:

from vllm import LLM, SamplingParams


def main():
    # 定义一个输入列表
    prompts = [
        "请介绍一下你自己",
        "The capital of France is",
        "The largest ocean is",
    ]

    # 定义采样参数
    sampling_params = SamplingParams(temperature=0.8, top_p=0.95)

    # 初始化一个 LLM 引擎
    llm = LLM(model="facebook/opt-125m")

    # 模型根据输入信息产生输出信息
    outputs = llm.generate(prompts, sampling_params)

    # 打印模型输出信息
    for output in outputs:
        prompt = output.prompt
        generated_text = output.outputs[0].text
        print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")


if __name__ == "__main__":
    main()

LLM 类需要若干参数,这些参数可以在这篇文章中查看03. vLLM 引擎参数,无论是离线推理模式还是在线服务模式,二者的参数基本一致。

LLM 类的代码可以在 vllm/entrypoints/llm.py 中找到。

OpenAI-compatible API Server

vLLM 的第二个主要接口是通过其 OpenAI 兼容的 API 服务进行在线推理。

可以使用 vllm serve 命令启动此服务器,这是新版本 vllm 的启动命令,推荐使用。

vllm serve <model>

vllm CLI 的代码可以在 vllm/entrypoints/cli/main.py 中找到。

旧版本的 vllm 直接使用 API server entrypoints,而不是通过 vLLM CLI 命令使用。例如:

python -m vllm.entrypoints.openai.api_server --model <model>

两种在线推理方式中,前者是对后者的高级封装,未来如果 vLLM 想支持除 OpenAI 以外的协议(比如专门的 gRPC 接口),只需要在 entrypoints 下新建文件夹,而不需要改动 cli 的基础架构。

LLM Engine

在 vLLM 的架构设计中,LLMEngine 类作为核心逻辑层,承载了调度管理与模型执行的底层职能。然而,面向用户的 LLM 类(离线推理接口) 并非通过继承机制扩展,而是使用了组合的方式,将 LLMEngine 实例化为内部成员变量。

OpenAI compatible server并不直接操作 LLMEngine类,而是操作 AsyncLLMEngine(为了支持异步并发),AsyncLLMEngine 内部也持有一个 LLMEngine 实例,作为其实际执行推理的核心。

这种设计实现了高层接口与底层引擎的解耦:高层模块仅作为逻辑入口,负责参数解析与任务封装,而具体的推理驱动则委托给内部持有的引擎实例来完成。


LLMEngine 类是 vLLM 引擎的核心组件。它负责接收来自客户端的请求并生成模型的输出。LLMEngine 包括输入处理、模型执行(可能分布在多个主机和/或 GPU 上)、调度和输出处理。

  • 输入处理:使用指定的分词器处理输入文本的分词。
  • 调度:选择在每个步骤中处理的请求。
  • 模型执行:管理语言模型的执行,包括跨多个 GPU 的分布式执行。
  • 输出处理:处理模型生成的输出,将语言模型的 token ID 解码为人类可读的文本。

LLMEngine 的代码可以在 vllm/engine/llm_engine.py 中找到。

AsyncLLMEngine

AsyncLLMEngine 类是 LLMEngine 类的异步封装。它使用 asyncio 创建一个后台循环,持续处理传入的请求。AsyncLLMEngine 专为在线服务设计,可以处理多个并发请求并将输出流式传输给客户端。

OpenAI compatible API server 使用 AsyncLLMEngine,代码可以在 vllm/engine/async_llm_engine.py 中找到。

此外,在 vllm/entrypoints/api_server.py 中还有一个演示用的 API server,作为一个更简单的示例供参考。

LLM Executor

在 vLLM 中,Executor一共有4种类型,由配置参数 --distributed-executor-backend决定,默认情况下为None,此时 vLLM 会根据你的分布式配置(world_size)和你所使用的平台(cuda、neuron、是否安装/初始化/配置了ray等)来自动决定该参数的的取值。

四种 Executor分别为:

  • mp:单机多卡
  • ray:多机多卡
  • uni:单卡
  • external_launcher:自定义的外部工具
  • [--distributed-executor-backend {ray,mp,uni,external_launcher}]

Executor位于vLLM架构的中层,它是连接上层LLMEngine和下层Worker的桥梁:

  • 向上:为LLMEngine提供统一的接口,处理模型执行、缓存管理等任务
  • 向下:管理工作进程,通过RPC机制发送任务并收集结果

所有Executor的基类为ExecutorBase,其定义了一系列基础操作,代码位于vllm/executor/executor_base.py

LLM Worker

Worker是指运行模型推理的核心进程,所有的 Worker都由 Executor统一管理。vLLM 使用单个进程来控制单个加速器设备(即一个 Worker对应一张卡)。在多卡环境中每张卡持有和计算模型的一部分(Shard),例如,如果用户将启动参数中的张量并行度和流水线并行度分别设置为 2,那么 vLLM 将会启动 4 个 Worker,它们通过通信集合(NCCL)协同完成一次完整的推理。

Worker 通过 ranklocal_rank 进行标识。

  • rank:全局唯一 ID,用于协调整个集群的任务编排。
  • local_rank:节点内 ID,用于绑定具体的 GPU 设备以及访问共享内存等本地资源。

Model Runner

每个Executor会实例化一个 Model Runner对象,该对象负责加载并运行模型(model),许多模型执行逻辑在此处,包括准备输入张量和捕获 cudagraph

Model

每个模型运行器对象包含一个模型对象,该对象是实际的 PyTorch 模型实例。请参见 huggingface_integration,以了解各种配置如何影响最终得到的Model类。

posted @ 2026-02-05 17:08  Groot_Liu  阅读(9)  评论(0)    收藏  举报