并行与扩展¶
单个模型副本的分布式推理策略¶
若要为单个模型副本选择分布式推理策略,请遵循以下准则:
- 单个 GPU(无分布式推理):如果模型适合单个 GPU,则通常无需进行分布式推理。直接在该 GPU 上运行推理即可。
- 使用张量并行推理的单节点多 GPU:如果模型对于单个 GPU 来说过大,但适合具有多个 GPU 的单节点,请使用张量并行(Tensor Parallelism)。例如,在使用具有 4 个 GPU 的节点时,设置
tensor_parallel_size=4。 - 使用张量并行和流水线并行推理的多节点多 GPU:如果模型对于单个节点来说过大,请将张量并行与流水线并行(Pipeline Parallelism)结合使用。将
tensor_parallel_size设置为每个节点的 GPU 数量,并将pipeline_parallel_size设置为节点数量。例如,在使用 2 个节点且每个节点有 8 个 GPU 时,设置tensor_parallel_size=8和pipeline_parallel_size=2。
增加 GPU 和节点的数量,直到模型拥有足够的 GPU 显存。将 tensor_parallel_size 设置为每个节点的 GPU 数量,并将 pipeline_parallel_size 设置为节点数量。
在准备好足够的资源以容纳模型后,运行 vllm。查看如下日志信息:
INFO 07-23 13:56:04 [kv_cache_utils.py:775] GPU KV cache size: 643,232 tokens
INFO 07-23 13:56:04 [kv_cache_utils.py:779] Maximum concurrency for 40,960 tokens per request: 15.70x
GPU KV cache size 行报告了可一次存储在 GPU KV 缓存中的标记(token)总数。Maximum concurrency 行估计了如果每个请求都需要指定数量的标记(上例中为 40,960),可以并发服务多少个请求。每个请求的标记数量取自模型配置的最大序列长度 ModelConfig.max_model_len。如果这些数字低于您的吞吐量要求,请向集群添加更多 GPU 或节点。
边界情况:不均匀的 GPU 分割
如果模型适合单个节点,但 GPU 数量无法均匀分配模型大小,请启用流水线并行。流水线并行会沿层拆分模型,并支持不均匀的分割。在这种情况下,将 tensor_parallel_size=1,并将 pipeline_parallel_size 设置为 GPU 数量。此外,如果节点上的 GPU 没有 NVLINK 互连(例如 L40S),请利用流水线并行代替张量并行,以获得更高的吞吐量和更低的通信开销。
混合专家(MoE)模型的分布式服务¶
通过为专家层使用单独的并行策略来利用专家固有的并行性通常是有利的。vLLM 支持结合数据并行注意力(Data Parallel attention)与专家并行或张量并行 MoE 层的大规模部署。更多信息,请参阅 数据并行部署。
单节点部署¶
vLLM 支持分布式张量并行和流水线并行推理及服务。该实现包含 Megatron-LM 的张量并行算法。
默认的分布式运行时是用于多节点推理的 Ray,以及用于单节点推理的本地 Python multiprocessing。您可以通过在 LLM 类中设置 distributed_executor_backend,或在 API 服务器中设置 --distributed-executor-backend 来覆盖默认值。使用 mp 表示 multiprocessing,使用 ray 表示 Ray。
对于多 GPU 推理,请在 LLM 类中将 tensor_parallel_size 设置为所需的 GPU 数量。例如,要在 4 个 GPU 上运行推理:
from vllm import LLM
llm = LLM("facebook/opt-13b", tensor_parallel_size=4)
output = llm.generate("San Francisco is a")
对于多 GPU 服务,启动服务器时需包含 --tensor-parallel-size。例如,要在 4 个 GPU 上运行 API 服务器:
若要启用流水线并行,请添加 --pipeline-parallel-size。例如,要在 8 个 GPU 上运行具有流水线并行和张量并行的 API 服务器:
多节点部署¶
如果单个节点没有足够的 GPU 来容纳模型,请跨多个节点部署 vLLM。确保每个节点提供完全相同的执行环境,包括模型路径和 Python 包。建议使用容器镜像,因为它们提供了一种方便的方式来保持环境一致并隐藏主机异构性。
什么是 Ray?¶
Ray 是一个用于扩展 Python 程序的分布式计算框架。多节点 vLLM 部署可以使用 Ray 作为运行时引擎。
vLLM 使用 Ray 来管理跨多个节点的分布式任务执行,并控制执行的位置。
Ray 还为大规模 离线批处理推理 和 在线服务 提供了高级 API,这些 API 可以利用 vLLM 作为引擎。这些 API 为 vLLM 工作负载增加了生产级的容错性、扩展性和分布式可观测性。
Ray 是一个可选依赖项。在使用基于 Ray 的执行之前,请明确安装它,例如:
详细信息,请参阅 Ray 文档。
使用容器设置 Ray 集群¶
辅助脚本 examples/online_serving/run_cluster.sh 跨节点启动容器并初始化 Ray。默认情况下,该脚本以非管理员权限运行 Docker,这会阻止在分析或跟踪时访问 GPU 性能计数器。要启用管理员权限,请在 Docker 命令中添加 --cap-add=CAP_SYS_ADMIN 标志。
选择一个节点作为头节点(head node)并运行:
bash run_cluster.sh \
vllm/vllm-openai \
<HEAD_NODE_IP> \
--head \
/path/to/the/huggingface/home/in/this/node \
-e VLLM_HOST_IP=<HEAD_NODE_IP>
在每个工作节点上,运行:
bash run_cluster.sh \
vllm/vllm-openai \
<HEAD_NODE_IP> \
--worker \
/path/to/the/huggingface/home/in/this/node \
-e VLLM_HOST_IP=<WORKER_NODE_IP>
请注意,VLLM_HOST_IP 对每个 worker 都是唯一的。请保持运行这些命令的 shell 窗口开启;关闭任何 shell 都会终止集群。确保所有节点都能通过其 IP 地址相互通信。
网络安全
出于安全考虑,请将 VLLM_HOST_IP 设置为专用网段上的地址。通过此网络发送的流量未加密,端点以一种可被利用的方式交换数据。如果对手获得了网络访问权限,可能会利用此方式执行任意代码。确保不可信方无法访问该网络。
从任何节点进入容器并运行 ray status 和 ray list nodes,以验证 Ray 是否发现了预期的节点和 GPU 数量。
提示
或者,使用 KubeRay 设置 Ray 集群。更多信息,请参阅 KubeRay vLLM 文档。
在 Ray 集群上运行 vLLM¶
提示
如果 Ray 在容器内运行,请在本指南的其余部分在容器内运行命令,而不是在主机上。要打开容器内的 shell,请连接到节点并使用 docker exec -it <container_name> /bin/bash。
一旦 Ray 集群运行,就可以像在单节点环境中一样使用 vLLM。Ray 集群中的所有资源对 vLLM 都是可见的,因此在单个节点上执行单个 vllm 命令就足够了。
通常的做法是将张量并行大小设置为每个节点的 GPU 数量,并将流水线并行大小设置为节点数量。例如,如果您在 2 个节点上有 16 个 GPU(每个节点 8 个 GPU),请将张量并行大小设置为 8,将流水线并行大小设置为 2:
vllm serve /path/to/the/model/in/the/container \
--tensor-parallel-size 8 \
--pipeline-parallel-size 2 \
--distributed-executor-backend ray
或者,您可以将 tensor_parallel_size 设置为集群中 GPU 的总数:
vllm serve /path/to/the/model/in/the/container \
--tensor-parallel-size 16 \
--distributed-executor-backend ray
使用多进程(MultiProcessing)运行 vLLM¶
除了 Ray,多节点 vLLM 部署也可以使用 multiprocessing 作为运行时引擎。这是一个跨 2 个节点(每个节点 8 个 GPU)部署模型且 tp_size=8 和 pp_size=2 的示例。
选择一个节点作为头节点(head node)并运行:
vllm serve /path/to/the/model/in/the/container \
--tensor-parallel-size 8 --pipeline-parallel-size 2 \
--nnodes 2 --node-rank 0 \
--master-addr <HEAD_NODE_IP>
在另一个工作节点上,运行:
vllm serve /path/to/the/model/in/the/container \
--tensor-parallel-size 8 --pipeline-parallel-size 2 \
--nnodes 2 --node-rank 1 \
--master-addr <HEAD_NODE_IP> --headless
优化张量并行的网络通信¶
高效的张量并行需要快速的节点间通信,最好通过高速网络适配器(如 InfiniBand)。要设置集群以使用 InfiniBand,请将类似 --privileged -e NCCL_IB_HCA=mlx5 的附加参数添加到 examples/online_serving/run_cluster.sh 辅助脚本中。有关所需标志的更多信息,请联系您的系统管理员。
启用 GPUDirect RDMA¶
GPUDirect RDMA(远程直接内存访问)是一项 NVIDIA 技术,允许网络适配器直接访问 GPU 内存,从而绕过 CPU 和系统内存。这种直接访问减少了延迟和 CPU 开销,对于跨节点 GPU 之间的大量数据传输非常有益。
要为 vLLM 启用 GPUDirect RDMA,请配置以下设置:
IPC_LOCK安全上下文:将IPC_LOCK能力添加到容器的安全上下文中,以锁定内存页并防止换出到磁盘。- 使用
/dev/shm的共享内存:在 pod 规范中挂载/dev/shm,以便为进程间通信(IPC)提供共享内存。
如果您使用 Docker,请按如下方式设置容器:
如果您使用 Kubernetes,请按如下方式设置 pod 规范:
...
spec:
containers:
- name: vllm
image: vllm/vllm-openai
securityContext:
capabilities:
add: ["IPC_LOCK"]
volumeMounts:
- mountPath: /dev/shm
name: dshm
resources:
limits:
nvidia.com/gpu: 8
requests:
nvidia.com/gpu: 8
volumes:
- name: dshm
emptyDir:
medium: Memory
...
确认 GPUDirect RDMA 操作
要确认您的 InfiniBand 卡正在使用 GPUDirect RDMA,请运行带有详细 NCCL 日志的 vLLM:NCCL_DEBUG=TRACE vllm serve ...。
然后查找 NCCL 版本和所使用的网络。
- 如果在日志中发现
[send] via NET/IB/GDRDMA,则说明 NCCL 正在使用启用了 GPUDirect RDMA 的 InfiniBand,这是高效的。 - 如果在日志中发现
[send] via NET/Socket,则说明 NCCL 使用了原始 TCP 套接字,这对于跨节点张量并行来说不高效。
预下载 Hugging Face 模型
如果您使用 Hugging Face 模型,建议在启动 vLLM 之前下载模型。在每个节点上将模型下载到相同路径,或者将模型存储在所有节点均可访问的分布式文件系统上。然后将模型路径传递给模型,替换掉仓库 ID。否则,请通过在 run_cluster.sh 后添加 -e HF_TOKEN=<TOKEN> 来提供 Hugging Face 令牌。
分布式部署故障排查¶
有关分布式调试的信息,请参阅 分布式部署故障排除。