优化与调优#
抢占#
由于 Transformer 架构的自回归特性,有时 KV 缓存空间不足以处理所有批处理请求。 vLLM 可以抢占请求,以释放 KV 缓存空间供其他请求使用。 当 KV 缓存空间再次可用时,被抢占的请求将被重新计算。 发生这种情况时,将打印以下警告
WARNING 05-09 00:49:33 scheduler.py:1057 Sequence group 0 is preempted by PreemptionMode.SWAP 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
虽然此机制确保了系统的鲁棒性,但抢占和重新计算可能会对端到端延迟产生不利影响。 如果您经常遇到来自 vLLM 引擎的抢占,请考虑以下操作
增加
gpu_memory_utilization
。 vLLM 通过使用 gpu_memory_utilization% 的内存来预分配 GPU 缓存。 通过增加此利用率,您可以提供更多的 KV 缓存空间。减少
max_num_seqs
或max_num_batched_tokens
。 这可以减少批处理中并发请求的数量,从而减少所需的 KV 缓存空间。增加
tensor_parallel_size
。 这种方法对模型权重进行分片,因此每个 GPU 都有更多内存可用于 KV 缓存。增加
pipeline_parallel_size
。 这种方法跨 GPU 分布模型层,减少了每个 GPU 上模型权重所需的内存,从而间接留出更多内存用于 KV 缓存。
您还可以通过 vLLM 公开的 Prometheus 指标来监控抢占请求的数量。 此外,您可以通过设置 disable_log_stats=False 来记录抢占请求的累积数量。
分块预填充#
vLLM 支持一项实验性功能:分块预填充。 分块预填充允许将大型预填充分块为更小的块,并将它们与解码请求批量处理在一起。
您可以通过在命令行中指定 --enable-chunked-prefill
或在 LLM 构造函数中设置 enable_chunked_prefill=True
来启用此功能。
from vllm import LLM
llm = LLM(model="meta-llama/Llama-2-7b-hf", enable_chunked_prefill=True)
# Set max_num_batched_tokens to tune performance.
# NOTE: 2048 is the default max_num_batched_tokens for chunked prefill.
# llm = LLM(model="meta-llama/Llama-2-7b-hf", enable_chunked_prefill=True, max_num_batched_tokens=2048)
默认情况下,vLLM 调度器优先处理预填充,并且不会将预填充和解码批处理到同一批次中。 此策略优化了 TTFT(首个令牌的时间),但会导致 ITL(令牌间延迟)较慢和 GPU 利用率低下。
启用分块预填充后,策略将更改为优先处理解码请求。 它会将所有待处理的解码请求批处理到批次中,然后再调度任何预填充。 当有可用的 token_budget (max_num_batched_tokens
) 时,它会调度待处理的预填充。 如果最后一个待处理的预填充请求无法容纳到 max_num_batched_tokens
中,它会对其进行分块。
此策略有两个好处
它提高了 ITL 和生成解码,因为解码请求被优先处理。
它通过将计算密集型(预填充)和内存密集型(解码)请求定位到同一批次,帮助实现更好的 GPU 利用率。
您可以通过更改 max_num_batched_tokens
来调整性能。 默认情况下,它设置为 2048。 较小的 max_num_batched_tokens
可以实现更好的 ITL,因为打断解码的预填充较少。 较高的 max_num_batched_tokens
可以实现更好的 TTFT,因为您可以将更多的预填充放入批次中。
如果
max_num_batched_tokens
与max_model_len
相同,则几乎等同于默认的调度策略(除了它仍然优先处理解码)。请注意,
max_num_batched_tokens
的默认值 (2048) 针对 ITL 进行了优化,并且它的吞吐量可能低于默认调度器。
我们建议您将 max_num_batched_tokens > 2048
设置为吞吐量。
有关更多详细信息,请参阅相关论文 (https://arxiv.org/pdf/2401.08671 或 https://arxiv.org/pdf/2308.16369)。
请试用此功能,并通过 GitHub issue 告知我们您的反馈!