vLLM 的高性能配置

来源

我们将讨论的 vLLM 引擎参数:

  • max-num-batched-tokens
  • max-model-len
  • gpu-memory-utilization
  • enable-prefix-caching
  • enable-chunked-prefill
  • enforce-eager

max-model-len:

简而言之:根据实际使用的最大 token 数量(输入 + 输出)

  • 默认情况下,模型的最大长度等于您所使用模型的最大上下文长度。例如,对于 llama 3 8B instruct 模型,该值为 8192。
  • 如果您可以确定您使用场景下的最大上下文长度,并且该长度小于模型的最大上下文长度,建议将此参数设置为该值。
  • 这不仅可以防止在加载或使用模型时出现内存不足错误,还能帮助您更好地调整其他参数,如 max-num-batched-tokens 和 gpu-memory-utilization。
  • 该值包含输入和输出 token 的总数,因此,如果您的场景中总 token 数量不超过 2046,建议将此参数设置为该值。

max-num-batched-tokens:

简而言之:从 max-model-len 开始,然后尝试将其值翻倍:max-model-len * 2,再 * 3……直到出现内存不足错误或 驱逐警告。选择一个能提供良好性能的值。如果您使用 enable-chunked-prefill,建议从较小值(如 128)开始尝试不同值。详见下文说明。

  • 请注意,此参数表示 token 数量,而非批次大小。
  • 每个请求必须经过预填充(计算输入 token 的 KV 值并将其分配到 KV 缓存块)阶段,然后进入解码阶段,该阶段通过递归前向计算逐个生成 token。
  • 因此,该参数的最小值等于您设置的用于预填充的最大模型长度(除非您使用 chunked-prefill,稍后将详细说明)。
  • 包含的 token 数量越多,预填充次数越多,第一个 token 生成速度越快。vLLM 默认调度器更偏好预填充。
  • 因此,较大的批次大小有助于提高吞吐量,但这并非在所有情况下都适用,因为吞吐量和延迟还取决于 GPU 计算资源与内存的配比(详见 chunked-prefill 部分),且预填充通常需要大量计算资源,因此很快就会达到我们能保存的最大 token 数量。
  • 因此,建议从 max-model-len 开始,尝试将其翻倍,观察性能变化,直到出现内存不足错误或驱逐警告(如 此处 所述),以选择合适的批次 token 数量。然后尝试应用此理论,以理解您的系统如何运行。

enable-prefix-caching:

简而言之:除非您使用 enable-chunked-prefill,否则请启用它。

  • 它缓存已计算的 KV 值以供后续使用,可节省大量时间。
  • 如果您的请求大部分输入保持不变,您将比输入中仅有少量 token 保持不变的情况获得更显著的性能提升。
  • 如果启用了 enable-chunked-prefill,此参数无效(截至本文发布时)。

gpu-memory-utilization:

简而言之:越大越好,除非出现内存不足错误。默认值为 0.9。

  • 为 KV 缓存分配的 GPU 内存越多,性能越高。
  • 如果您遇到内存不足错误,或 GPU 正在执行其他需要减少此值的任务,请降低该值。

enforce-eager:

简而言之:如果内存不足,请启用此功能。

  • 使用时不会生成 CUDA 图,可能会影响性能,但可节省用于构建图的内存。
  • 在某些配置下,CUDA 图对性能影响不大,而节省的内存可用于提高上述参数(如 gpu-memory-utilization、max-num-batched-tokens 等)的值。

enable-chunked-prefill:

简而言之:尝试启用此功能,并从 128 开始使用批处理 token,逐步增加。与不启用此参数的配置进行比较。详见下文。

  • 解码阶段对计算资源的需求低于预填充阶段(向量乘矩阵 vs 矩阵乘矩阵),但对内存需求更高,因为它需要读取已计算的 KV 值。
  • 如需了解更多,请参阅 这篇论文vLLM 文档页面
  • 如前所述,vLLM 默认调度器更偏好预填充,该阶段需要大量计算资源,而解码阶段则受内存限制,无法充分利用低计算资源但高内存需求的解码能力,因为需要读取 KV 值。
  • Chunk prefill 将预填充阶段拆分为多个片段,从而减少每个批次的 token 数量,并首先形成批次,将解码请求与预填充分片请求组合,以有效利用 GPU 资源,兼顾高计算资源需求的预填充分片和高内存需求但低计算资源需求的解码请求。
  • 再次尝试启用此功能,并使用较小的批次 token 数量(如 128),逐步增加,直到达到所需的吞吐量和延迟。
  • 此方法可缩短 token 之间的延迟,因为解码因较小的批次大小(降低内存压力)而获得优先权,但可能影响吞吐量,因此需要尝试不同的批次大小,并与未启用此参数的配置进行比较。

示例:

  • 我们将使用 vLLM API 入口点 而非 OpenAI 兼容服务器。
  • 要启动无分片预填充的服务器,可使用以下示例:
python3 -m vllm.entrypoints.api_server --model MaziyarPanahi/Meta-Llama-3-8B-Instruct-GPTQ --gpu-memory-utilization 0.95 --port 5000 --dtype half --enforce-eager --max-model-len 4096 --max-num-batched-tokens 8192 --enable-prefix-caching
  • 如果启用了分片预填充,命令可能如下:
python3 -m vllm.entrypoints.api_server --model MaziyarPanahi/Meta-Llama-3-8B-Instruct-GPTQ --gpu-memory-utilization 0.95 --port 5000 --dtype half --enforce-eager --max-model-len 4096 --max-num-batched-tokens 256 --enable-chunked-prefill
  • 向上述服务器端点发送请求,以检查不同参数下的性能。
  • 使用 vLLM 提供的脚本 进行基准测试,我也会尝试编写类似的脚本并在此分享。

作者