优化与调优¶
本指南涵盖了 vLLM V1 的优化策略和性能调优。
抢占¶
由于 Transformer 架构的自回归特性,有时 KV 缓存空间不足以处理所有批处理请求。在这种情况下,vLLM 可以抢占请求以释放 KV 缓存空间供其他请求使用。被抢占的请求在有足够的 KV 缓存空间时会重新计算。当这种情况发生时,您可能会看到以下警告:
WARNING 05-09 00:49:33 scheduler.py:1057 Sequence group 0 is preempted by PreemptionMode.RECOMPUTE mode because there is not enough KV cache space. This can affect the end-to-end performance. Increase gpu_memory_utilization or tensor_parallel_size to provide more KV cache memory. total_cumulative_preemption_cnt=1
尽管此机制确保了系统鲁棒性,但抢占和重新计算可能会对端到端延迟产生不利影响。如果您频繁遇到抢占,请考虑以下操作:
- 增加
gpu_memory_utilization
。vLLM 使用此百分比的内存预分配 GPU 缓存。通过提高利用率,您可以提供更多的 KV 缓存空间。 - 减少
max_num_seqs
或max_num_batched_tokens
。这会减少批处理中并发请求的数量,从而需要更少的 KV 缓存空间。 - 增加
tensor_parallel_size
。这将模型权重分片到不同的 GPU 上,使得每个 GPU 可以有更多的内存用于 KV 缓存。然而,增加此值可能会导致过多的同步开销。 - 增加
pipeline_parallel_size
。这将模型层分布到不同的 GPU 上,减少每个 GPU 上模型权重所需的内存,间接留下更多内存用于 KV 缓存。然而,增加此值可能会导致延迟损失。
您可以通过 vLLM 暴露的 Prometheus 指标监控抢占请求的数量。此外,您可以通过设置 disable_log_stats=False
来记录抢占请求的累计数量。
在 vLLM V1 中,默认的抢占模式是 RECOMPUTE
而不是 SWAP
,因为在 V1 架构中,重新计算的开销更低。
分块预填充¶
分块预填充允许 vLLM 将大型预填充分成更小的块进行处理,并将其与解码请求一起进行批处理。此功能通过更好地平衡计算密集型(预填充)和内存密集型(解码)操作,有助于提高吞吐量和降低延迟。
在 vLLM V1 中,分块预填充默认始终启用。这与 vLLM V0 不同,V0 中是根据模型特性有条件地启用。
启用分块预填充后,调度策略会优先处理解码请求。它会在调度任何预填充操作之前,批处理所有待处理的解码请求。当 max_num_batched_tokens
预算中有可用 token 时,它会调度待处理的预填充。如果待处理的预填充请求无法适应 max_num_batched_tokens
,它会自动将其分块。
此策略有两个优点:
- 由于解码请求被优先处理,它改善了 ITL(内部 Token 延迟)和生成解码。
- 它通过将计算密集型(预填充)和内存密集型(解码)请求放在同一个批次中,有助于实现更好的 GPU 利用率。
使用分块预填充进行性能调优¶
您可以通过调整 max_num_batched_tokens
来调整性能:
- 较小的值(例如 2048)可以实现更好的内部 Token 延迟(ITL),因为预填充较少,不会减慢解码速度。
- 较大的值可以实现更好的首个 Token 生成时间(TTFT),因为您可以在一个批次中处理更多的预填充 token。
- 为了获得最佳吞吐量,我们建议将
max_num_batched_tokens > 8096
,特别是对于大型 GPU 上的小型模型。 - 如果
max_num_batched_tokens
与max_model_len
相同,这几乎等同于 V0 的默认调度策略(除了它仍然优先处理解码)。
from vllm import LLM
# Set max_num_batched_tokens to tune performance
llm = LLM(model="meta-llama/Llama-3.1-8B-Instruct", max_num_batched_tokens=16384)
有关更多详细信息,请参阅相关论文(https://arxiv.org/pdf/2401.08671 或 https://arxiv.org/pdf/2308.16369)。
并行策略¶
vLLM 支持多种并行策略,可以组合使用以优化不同硬件配置下的性能。
张量并行 (TP)¶
张量并行在每个模型层内将模型参数分片到多个 GPU。这是单节点内大型模型推理最常见的策略。
何时使用:
- 当模型太大无法适应单个 GPU 时
- 当您需要减少每个 GPU 的内存压力以提供更多 KV 缓存空间来提高吞吐量时
from vllm import LLM
# Split model across 4 GPUs
llm = LLM(model="meta-llama/Llama-3.3-70B-Instruct", tensor_parallel_size=4)
对于太大而无法适应单个 GPU 的模型(如 70B 参数模型),张量并行是必不可少的。
流水线并行 (PP)¶
流水线并行将模型层分布到多个 GPU。每个 GPU 按顺序处理模型不同的部分。
何时使用:
- 当您已经最大限度地利用了高效的张量并行,但仍需要进一步分布模型,或跨节点分布时
- 对于非常深且窄的模型,层分布比张量分片更高效时
流水线并行可以与张量并行结合使用,适用于超大型模型。
from vllm import LLM
# Combine pipeline and tensor parallelism
llm = LLM(
model="meta-llama/Llama-3.3-70B-Instruct,
tensor_parallel_size=4,
pipeline_parallel_size=2
)
专家并行 (EP)¶
专家并行是一种针对混合专家(MoE)模型的专用并行形式,其中不同的专家网络分布在 GPU 上。
何时使用:
- 专门用于 MoE 模型(如 DeepSeekV3、Qwen3MoE、Llama-4)
- 当您希望平衡 GPU 之间的专家计算负载时
通过设置 enable_expert_parallel=True
来启用专家并行,这将对 MoE 层使用专家并行而非张量并行。它将使用与您为张量并行设置的并行度相同的度数。
数据并行 (DP)¶
数据并行在多个 GPU 集上复制整个模型,并并行处理不同的请求批次。
何时使用:
- 当您有足够的 GPU 来复制整个模型时
- 当您需要扩展吞吐量而不是模型大小时
- 在多用户环境中,请求批次之间的隔离有利时
数据并行可以与其他并行策略结合使用,并通过 data_parallel_size=N
设置。请注意,MoE 层将根据张量并行大小和数据并行大小的乘积进行分片。
减少内存使用¶
如果您遇到内存不足问题,请考虑以下策略:
上下文长度和批处理大小¶
您可以通过限制上下文长度和批处理大小来减少内存使用。
from vllm import LLM
llm = LLM(
model="meta-llama/Llama-3.1-8B-Instruct",
max_model_len=2048, # Limit context window
max_num_seqs=4 # Limit batch size
)
调整 CUDA Graph 编译¶
V1 中的 CUDA graph 编译比 V0 中使用更多的内存。您可以通过调整编译级别来减少内存使用:
from vllm import LLM
from vllm.config import CompilationConfig, CompilationLevel
llm = LLM(
model="meta-llama/Llama-3.1-8B-Instruct",
compilation_config=CompilationConfig(
level=CompilationLevel.PIECEWISE,
cudagraph_capture_sizes=[1, 2, 4, 8] # Capture fewer batch sizes
)
)
或者,如果您不关心延迟或整体性能,可以使用 enforce_eager=True
完全禁用 CUDA graph 编译。
from vllm import LLM
llm = LLM(
model="meta-llama/Llama-3.1-8B-Instruct",
enforce_eager=True # Disable CUDA graph compilation
)
多模态模型¶
对于多模态模型,您可以通过限制每个请求的图像/视频数量来减少内存使用。