随着OpenAI的ChatGPT横空出世,人工智能迅速进入大众视野,并引起了全球范围内的广泛关注。Meta发布的LLaMA等开源大语言模型(LLM)的出现,使得开发者和企业无需依赖第三方API,即可构建定制化的应用。尤其是在数据保护法规严格的欧盟地区,开源模型的部署显得尤为重要。尽管Ollama等工具极大地降低了本地运行LLaMA类模型的门槛,但对于追求生产环境高性能的场景, vLLM 则是一个更优的选择。本文将深入探讨 vLLM 的优势,以及它如何通过PagedAttention和连续批处理等创新技术,大幅提升LLM的吞吐量、降低延迟并提高GPU利用率。
1. vLLM 简介:高效LLM推理引擎
vLLM 是一个开源的LLM推理和服务引擎,旨在提升大规模语言模型的运行速度、效率和可扩展性。它最初由加州大学伯克利分校的Sky Computing Lab开发,目前已迅速发展成为一个社区驱动的项目,在学术界和工业界得到广泛应用。[1] vLLM 特别适合生产环境,因为它解决了LLM运行中的关键挑战:效率、速度和可扩展性。简单来说, vLLM 通过优化底层架构,让你的LLM跑得更快,用得更省。
2. PagedAttention:突破内存瓶颈
PagedAttention 技术是 vLLM 的核心创新之一。为了更好地理解PagedAttention的重要性,我们需要先了解KV Cache。在Transformer模型中,KV Cache是一种关键的优化技术,它通过避免重复计算来加速文本生成过程。传统的LLM服务系统通常会为每个请求预留一大块连续的GPU内存来存储KV值。但是,由于每个请求的序列长度不同,这些预留的内存块往往存在大量的未使用的碎片。
而PagedAttention 将KV Cache内存划分为许多大小相等的页面(Pages),这些页面可以灵活地存储在GPU内存中,无需连续的物理地址。 通过中心化的块表(Block Table)来管理逻辑块和物理内存区域的对应关系。 这种方法将内存浪费降低到低于4%,从而显著提高GPU利用率。 想象一下,传统的内存分配方式就像把不同大小的家具硬塞进一个房间,总会留下许多空隙。而PagedAttention则像玩拼图,把小块的拼图(Pages)灵活地组合起来,尽可能填满整个空间。
实际案例:假设你有一个Llama 2 7B模型,在传统的方式下,由于KV Cache的碎片化,你的GPU可能只能支持10个并发请求。而使用PagedAttention后,同样的GPU可能就能支持30甚至40个并发请求,吞吐量提升了数倍。
3. 连续批处理:GPU满载运行
连续批处理 (Continuous Batching) 是 vLLM 的另一项关键技术,它解决了LLM推理中输出长度不同的问题,通过token级别的处理来实现更高的GPU利用率。传统的批处理方法(静态批处理和动态批处理)都是在请求级别进行批处理,这意味着需要等待所有请求完成后才能开始下一个批次的处理。
与此不同,连续批处理 以token为单位进行处理。 当一个请求完成后,系统会立即从队列中取出一个新的请求来替代它。 这样,GPU始终处于忙碌状态,无需等待最长的请求完成。 比如,GPU可以同时处理一个响应的第五个token和另一个响应的第八十五个token。
实际案例: 假设你正在运行一个在线问答系统,用户提出的问题长度各不相同。在传统的批处理方式下,如果一个用户提出了一个很长的问题,那么整个批次都需要等待这个问题的处理完成。而使用连续批处理后,其他用户的请求可以在长问题处理的同时被处理,从而降低了整体的延迟。
4. vLLM的性能优势:吞吐量和延迟
通过PagedAttention和连续批处理这两项核心技术, vLLM 能够显著提升LLM的吞吐量、降低延迟并提高GPU利用率。 具体来说, vLLM 可以实现以下性能优势:
- 更高的吞吐量: 由于GPU利用率的提升, vLLM 可以在相同硬件条件下处理更多的并发请求。
- 更低的延迟: 连续批处理确保了每个请求都能得到及时的处理,从而降低了整体的响应时间。
- 更高的GPU利用率:PagedAttention和连续批处理共同作用,确保GPU始终处于满载运行状态,避免资源浪费。
数据对比: 根据官方的基准测试,对于一个Llama 2 7B模型,在RTX 4090上, vLLM 的吞吐量可以比传统服务方法高出2-4倍,延迟也可以控制在亚秒级。 某些性能测试显示,吞吐量可以提高到标准框架的24倍。
5. Llama 2 7B 模型部署案例:理论计算与实践
现在,我们以Llama 2 7B模型为例,理论上计算一下通过 vLLM 可以同时处理多少个请求。我们以Nvidia RTX 4090 (24 GB VRAM) 和 Nvidia A6000 (48 GB VRAM) 为例。
首先,计算LLM模型在FP16精度下需要的显存大小。因为我们以FP16精度加载模型,所以每个参数需要16 bit,即2 bytes。 除此之外,模型还会占用一些额外的显存,比如用于激活函数,临时缓存,以及系统进程等。我们估算为2GB。
| 模型 | 参数量(亿) | 每个参数大小(Bytes) | 模型总大小(GB) | 额外开销(GB) | 总计(GB) |
| ———- | ——– | ————- | ——– | ——– | ——– |
| Llama2 7B | 70 | 2 | 14 | 2 | 16 |
这意味着对于Nvidia A6000,有32GB显存剩余用于KV Cache,而对于Nvidia RTX 4090,则有8GB显存剩余。
接下来,我们需要计算每一个self-attention head存储Key和Value向量需要的显存大小。 这里我们需要用到head dim
(head dimension),即每一个Key和Value向量的维度。 你可以直接在模型的config.json
文件中找到这个值。
或者,你可以通过hidden size
和attention head的数量计算得到。hidden size
代表了在将token embeddings传入attention layer之前,模型内部向量表示的维度。将hidden size
除以attention heads的数量就可以得到每一个attention head的维度。
对于Llama 2 7B,hidden size
是4096, attention heads的数量是32, 所以head dim
是128。
因为每一个分量都是2 bytes (FP16), 我们将head dim
乘以2来计算Key和Value向量的大小: 128 * 2 bytes + 128 * 2 bytes = 512 bytes per KV pair。
下一步,我们需要计算单层(Layer)所需要的显存。所以,每个token所需要的显存乘以attention heads的数量。
最后,将结果乘以layers的数量。对于Llama 2 7B, layers的数量是32。所以我们将32 乘以 16384 bytes,得到 524228 bytes (约等于 0.5 MB)。
现在,我们终于可以确定可以并行处理多少个请求了。 想要计算这个数值,我们需要将空闲显存除以序列长度再乘以每一个token的KV Cache的大小。
下表展示了理论计算结果:
| GPU | 显存 (GB) | 模型大小 (GB) | 剩余显存 (GB) | Sequence Length | KV Cache Memory per Token (MB) | 并行请求数 |
| ——- | ——- | ——– | ——– | ————— | ———————— | —— |
| RTX 4090 | 24 | 16 | 8 | 2048 | 0.5 | 8 |
| A6000 | 48 | 16 | 32 | 2048 | 0.5 | 32 |
注意:因为 vLLM 对内存进行了优化,尤其是PagedAttention和连续批处理,实际的并行请求数可以比这里展示的数字高出2-4倍。因为 vLLM 可以将内存浪费降低到接近于零,并更有效地利用GPU资源。[7]
进一步提升GPU利用率的方法包括对模型进行量化,从而降低精度。
要使用 vLLM 部署你的开源LLM,只需要使用Docker Hub上提供的官方Docker镜像。
-
确保你有权限访问Hugging Face上的Llama权重。
-
拉取最新的 vLLM OpenAI Docker镜像:
docker pull vllm/vllm-openai:latest
-
运行container:
docker run --runtime nvidia --gpus all \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HUGGING_FACE_HUB_TOKEN=<YOUR_HF_TOKEN>" \ -p 8000:8000 \ --ipc=host \ vllm/vllm-openai:latest \ --model meta-llama/Llama-2-7b-chat-hf
--runtime nvidia --gpus all
: 启用GPU加速。-v ~/.cache/huggingface:/root/.cache/huggingface
: Mount你的Hugging Face缓存,用于高效的模型加载。--env "HUGGING_FACE_HUB_TOKEN=...":
将你的Hugging Face token传入container。-p 8000:8000
: 在端口8000暴露API。--ipc=host
: 与主机共享内存,用于更好的性能表现。--model meta-llama/Llama-2-7b-chat-hf
: 指定Llama 2 7B chat 模型。
还有许多其他的参数可以用于优化你的部署。一种明智的做法是提前通过Hugging Face hub cli下载模型,然后将其作为一个volume mount到container中。
# 下载模型
huggingface-cli download meta-llama/Llama-2-7b-chat-hf
# Mount
docker run -v ~/.cache/huggingface:/root/.cache/huggingface ...
6. 总结:vLLM是生产环境的理想选择
总而言之, vLLM 通过PagedAttention和连续批处理等创新技术,解决了LLM推理中的关键瓶颈,大幅提升了吞吐量、降低了延迟并提高了GPU利用率。 对于需要在生产环境中部署LLM的企业和开发者来说, vLLM 是一个极具吸引力的选择。 它不仅可以帮助你更好地利用硬件资源,还可以为你提供更快的响应速度和更好的用户体验。 如果你正在寻找一个高效、可扩展的LLM推理引擎, vLLM 绝对值得你深入了解和尝试。
参考文献:
[1] vLLM Docs
[2] Red Hat — Meet vLLM: For faster, more efficient LLM inference and serving
[3] Attention Is All You Need
[4] Understanding and Coding the Self-Attention Mechanism of Large Language Models From Scratch
[5] Understanding and Coding the KV Cache in LLMs from Scratch
[6] vLLM: Easy, Fast, and Cheap LLM Serving with PagedAttention
[7] Efficient Memory Management for Large Language Model Serving with PagedAttention
[8] Introduction to vLLM and PagedAttention
[9] Continuous vs dynamic batching for AI inference | Baseten Blog