vLLM 调优(2)--gpu-memory-utilization

结论

需要给底层驱动或某些算子预留多少显存?
公式化建议:如果显存 M > 40GB:建议预留 M * 0.05 和 2GB 之间的较大值。如果显存 M < 24GB:建议至少预留 2GB 绝对空间。

GPU服务器的物理内存,不能太小,否则会无法启动大模型。
CUDA Graph 录制阶段:约 4GB - 8GB + 模型权重(8bit量化qwen14 约为 15GB)+ 操作系统2-4G+python加载大模型的额外开销。
比如部署qwen14B,64GB RAM为比较安全的大小。

简单来说,--gpu-memory-utilization 参数定义的 不是 KV Cache 的大小,而是 vLLM 允许占用的 GPU 总内存上限

在 vLLM 启动时,它会按照以下顺序“瓜分”这部分内存:

1. 内存包含的内容

--gpu-memory-utilization(默认 0.9,即 90%)涵盖了 vLLM 运行所需的所有核心显存:

  • 模型权重 (Model Weights): 加载模型参数所需的显存(例如 FP16 的 7B 模型约占 14GB)。
  • KV Cache (键值缓存): 这是 vLLM 管理的重点。它会预先分配剩下的绝大部分空间作为 KV Cache 块池(Block Pool),用于存储推理过程中的上下文。
  • 激活值/工作空间 (Activations/Workspace): 推理过程中产生的临时张量和计算空间。
  • CUDA Graph: 为了加速推理,vLLM 默认会捕获 CUDA 图,这也会占用一部分固定显存。

2. vLLM 是如何分配内存的?

vLLM 的内存管理非常“霸道”,它采用的是预分配机制。分配流程如下:

  1. 加载模型: 首先把模型权重塞进显存。
  2. 显存探测 (Profiling): vLLM 会进行一次模拟运行,测量推理时需要的峰值临时显存(Activations)。
  3. 计算剩余:总显存 * utilization 减去“权重”和“临时显存”,剩下的所有空间都会被立即划拨给 KV Cache

举个例子:
如果你有 40GB 显存,设置 --gpu-memory-utilization 0.9,则 vLLM 计划使用 36GB。

  • 假设模型权重占 20GB,临时开销占 2GB。
  • 那么 vLLM 会在启动之初就直接霸占剩余的 14GB 全部作为 KV Cache。
  • 这就是为什么你一启动 vLLM,即使没发请求,nvidia-smi 也会显示显存占用瞬间飙升到 90% 的原因。

3. 常见误区与调优建议

  • “设置 1.0 是不是性能最强?”
    不建议。如果你设为 1.0,完全不给系统和其他潜在开销留余地,非常容易导致 Out of Memory (OOM) 崩溃,因为底层驱动或某些算子可能需要极少量的额外空间。一般 0.9 或 0.95 是比较稳妥的上限。
  • “为什么我改小了利用率,吞吐量变低了?”
    因为 利用率 变小 → KV Cache 变小 → 可同时处理的并发请求数 (Batch Size) 变少。
  • “如果显存被其他程序占了怎么办?”
    vLLM 启动时会检查可用显存。如果被占用了,而你设置的 utilization 比例对应的显存超过了剩余可用量,程序会直接报错。

总结: 它是 vLLM 的显存总预算。你可以通过这个参数控制 vLLM 不要把显存占满,从而给其他任务留点空间,或者通过调高它来压榨出更多的 KV Cache 空间以提升高并发性能。

您是遇到了显存溢出(OOM)问题,还是想在同一块卡上运行多个模型服务?我可以为您提供针对性的配置建议。

需要给底层驱动或某些算子预留多少显存?

在评估 --gpu-memory-utilization 的设置时,理解那部分“预留内存”(即 1 - utilization 的部分)具体用来做什么至关重要。

通常情况下,预留 5% 到 10%(即设置 0.9 或 0.95) 是 vLLM 的标准做法,但在特定硬件或高负载场景下,你可能需要预留更多。以下是预留内存的详细构成和评估建议:


1. 预留内存里到底有什么?

除了模型权重和 KV Cache,这部分预留空间主要承载以下三个“隐形大户”:

  • CUDA Graph 捕获空间 (CUDA Graph Overhead):

  • vLLM 默认会为常用的 Batch Size(如 1, 2, 4, 8...)预先录制计算图。

  • 这些图会占用固定显存。模型越大,CUDA Graph 占用的显存越高。在 80GB 的 H100 上,复杂的模型可能因为 CUDA Graph 录制瞬间吃掉几个 GB。

  • 临时激活值与工作空间 (Temp Workspace):

  • PyTorch 在执行特定算子(如 FlashAttention 或 CuBLAS 矩阵乘法)时,需要临时的显存空间作为“草稿纸”。

  • 虽然 vLLM 会进行 Profile 探测,但在高并发或长文本突然涌入时,某些算子的动态开销可能会超出探测值。

  • 显存碎片与驱动消耗 (Fragmentation & Driver):

  • 显存分配不是连续的,碎片化(Fragmentation)会导致虽然显示有余量,但无法分配出大的连续块。

  • NVIDIA 驱动本身也会占用几十到几百 MB。


2. 不同场景的预留建议表

你可以根据你的设备和任务,参考下表来设置 utilization

场景 推荐设置 预留比例 原因
单实例/生产环境 0.90 10% 最稳妥。 给 CUDA Graph 和算子留足 buffer,防止 OOM。
极限吞吐测试 0.95 5% 压榨性能。 适合已知短文本、固定负载的场景。
多模型共用显卡 0.4 - 0.7 30%+ 防止抢占。 如果这块卡还要跑其他 Web 服务或小模型,必须大幅降低。
小显存显卡 (<=12GB) 0.75 - 0.8 20%+ 容错低。 系统组件占用的绝对数值虽然不大,但在小卡上占比很高。
CUDA Graph 报错 0.80 20% 稳定性优先。 如果启动时报 std::bad_alloc,通常是预留不足。

3. 如何精准评估你的“安全水位”?

如果你想知道最极限能设多少,可以按以下步骤操作:

  1. 观察启动日志:
    vLLM 启动时会打印一行:
    INFO: # GPU blocks: 1234, # CPU blocks: 567
    这代表了它最终划拨给 KV Cache 的物理块数量。
  2. 强制关闭 CUDA Graph:
    如果你显存极度紧张,可以使用 --enforce-eager 参数。这会禁用 CUDA Graph。
  • 好处: 节省大量预留显存(有时能省下 1-2GB)。
  • 坏处: 推理速度会变慢(约 10%-20% 的延迟增加)。
  1. 公式化建议:
  • 如果显存 :建议预留 和 之间的较大值。
  • 如果显存 :建议至少预留 绝对空间。

避坑指南

如果你发现设置 0.9 依然崩溃,通常不是因为 KV Cache 占满了,而是因为 系统 RAM (内存) 耗尽了。vLLM 在录制 CUDA Graph 时会消耗大量的 CPU 内存。如果你的机器只有 16GB 内存却插了块 24GB 的显卡,建议把利用率降到 0.8。

你想针对具体的哪款显卡和模型进行配置?我可以帮你算一下具体的参数建议。

对于 Qwen-14B (8-bit 量化) 并在 48GB 显卡(如 RTX 6000 Ada 或 A4000/L40 等)上运行的配置,虽然显存非常充裕,但物理内存(RAM) 依然是启动成功的关键。

为了确保稳定运行,建议你的物理内存至少为 32GB,如果希望在高并发下完全不卡顿,64GB 是理想选择

以下是具体的内存需求拆解:

1. 物理内存 (RAM) 需求评估

在 vLLM 启动 Qwen-14B (INT8) 时,RAM 的压力主要来自以下三个阶段:

  • 模型加载阶段(峰值需求):约 16GB - 20GB
    虽然 8-bit 模型文件大小约为 15GB,但在加载过程中,Python 进程、模型初始化以及权重反序列化会产生额外的内存开销。如果你的 RAM 只有 16GB,此时系统极易触发 OOM (Out of Memory) 导致进程被杀。
  • CUDA Graph 录制阶段:约 4GB - 8GB
    vLLM 默认会为多个 Batch Size 录制 CUDA Graph,这会在 RAM 中产生大量的临时元数据。
  • 操作系统自身开销:2GB - 4GB
    Windows 或 Linux 系统常驻后台也会占用一部分内存。

结论: > * 16GB RAM: 极度危险,大概率启动失败,必须开启 --enforce-eager 且增加 Swap 虚拟内存才可能跑通。

  • 32GB RAM: 安全线,可以正常启动并保持 CUDA Graph 开启。
  • 64GB RAM: 舒适线,在处理长文本、多并发请求或同时运行其他任务时毫无压力。

2. 显存 (VRAM) 占用分析 (48GB 显卡)

在 48GB 的显卡上,默认设置 --gpu-memory-utilization 0.9 后的分布大约如下:

组件 占用大小 (估计) 说明
模型权重 (8-bit) ~15 GB Qwen-14B 的 INT8 权重。
KV Cache ~26 GB 显存剩下的绝大部分都被划给 Cache,能支撑极大的并发或超长上下文。
预留空间 (10%) 4.8 GB 用于处理算子临时开销和 CUDA Graph。
合计 43.2 GB 即 48GB * 0.9。

3. 针对你的 48GB 显卡建议

由于你的显存(48GB)对于 14B 模型来说非常富余(权重只占了不到三分之一),你可以采取以下优化策略:

  1. 最大化上下文: 你可以承载非常长的 Context。Qwen-14B 默认支持很长的上下文,由于你有 26GB 的 KV Cache 空间,你可以放心把 --max-model-len 设大(例如 32768 或更高)。
  2. 物理内存不足时的对策: 如果你的物理内存确实只有 16GB,启动时请务必加上:
python -m vllm.entrypoints.openai.api_server \
    --model Qwen/Qwen2.5-14B-Instruct-INT8 \
    --gpu-memory-utilization 0.85 \
    --enforce-eager

注:--enforce-eager 虽然牺牲了一点速度,但能救命,防止 RAM 在启动时爆掉。

你的机器目前实际配了多少 GB 的物理内存?如果是新组装机器,建议直接上两条 32GB 内存条。

posted @ 2026-01-16 19:13  向着朝阳  阅读(5)  评论(0)    收藏  举报