分布式推理和服务#
如何决定分布式推理策略?#
在深入探讨分布式推理和服务细节之前,让我们首先明确何时使用分布式推理以及有哪些可用的策略。常见的做法是:
单GPU(无分布式推理):如果你的模型适合单个GPU,你可能不需要使用分布式推理。只需使用单个GPU来运行推理。
单节点多GPU(张量并行推理):如果你的模型太大,无法放入单个GPU,但可以放入单个节点中的多个GPU,你可以使用张量并行。张量并行的大小是你想要使用的GPU数量。例如,如果你在一个节点中有4个GPU,你可以将张量并行大小设置为4。
多节点多GPU(张量并行加流水线并行推理):如果你的模型太大,无法放入单个节点中,你可以使用张量并行结合流水线并行。张量并行的大小是你希望在每个节点中使用的GPU数量,而流水线并行的大小是你希望使用的节点数量。例如,如果你有16个GPU分布在2个节点中(每个节点8个GPU),你可以将张量并行大小设置为8,流水线并行大小设置为2。
简而言之,你应该增加GPU的数量和节点的数量,直到你有足够的GPU内存来容纳模型。张量并行大小应为每个节点中的GPU数量,而流水线并行大小应为节点数量。
在添加足够的GPU和节点以容纳模型后,您可以首先运行vLLM,它将打印一些日志,例如 # GPU blocks: 790
。将该数字乘以 ``16``(块大小),您可以大致得到当前配置下可以服务的最大令牌数。如果这个数字不令人满意,例如您想要更高的吞吐量,您可以进一步增加GPU或节点的数量,直到块的数量足够为止。
备注
有一种边缘情况:如果模型适合在一个节点内使用多个GPU,但GPU的数量不能均匀地划分模型大小,你可以使用流水线并行,它沿着层分割模型并支持不均匀的分割。在这种情况下,张量并行的大小应为1,流水线并行的大小应为GPU的数量。
分布式推理和服务详情#
vLLM 支持分布式张量并行推理和服务。目前,我们支持 Megatron-LM 的张量并行算法。我们还支持将流水线并行作为在线服务的测试版功能。我们使用 Ray 或 Python 原生多进程来管理分布式运行时。在单节点部署时可以使用多进程,当前多节点推理需要 Ray。
当不在 Ray 放置组中运行且同一节点上有足够的 GPU 可供配置的 tensor_parallel_size
使用时,默认将使用多进程。否则将使用 Ray。此默认值可以通过 LLM
类的 distributed-executor-backend
参数或 --distributed-executor-backend
API 服务器参数来覆盖。将其设置为 mp
以使用多进程,或设置为 ray
以使用 Ray。对于多进程情况,不需要安装 Ray。
要使用 LLM
类进行多GPU推理,请将 tensor_parallel_size
参数设置为要使用的GPU数量。例如,要在4个GPU上运行推理:
from vllm import LLM
llm = LLM("facebook/opt-13b", tensor_parallel_size=4)
output = llm.generate("San Franciso is a")
要运行多GPU服务,请在启动服务器时传入 --tensor-parallel-size
参数。例如,要在4个GPU上运行API服务器:
$ vllm serve facebook/opt-13b \
$ --tensor-parallel-size 4
你还可以额外指定 --pipeline-parallel-size
以启用流水线并行。例如,要在8个GPU上运行API服务器,并启用流水线并行和张量并行:
$ vllm serve gpt2 \
$ --tensor-parallel-size 4 \
$ --pipeline-parallel-size 2
备注
Pipeline 并行是一个测试版功能。它仅支持在线服务以及 LLaMa、GPT2、Mixtral、Qwen、Qwen2 和 Nemotron 风格模型。
多节点推理与服务#
如果单个节点没有足够的GPU来容纳模型,您可以使用多个节点来运行模型。确保所有节点上的执行环境相同非常重要,包括模型路径、Python环境。推荐的方法是使用docker镜像来确保相同的环境,并通过将它们映射到相同的docker配置中来隐藏主机的异构性。
第一步是启动容器并将它们组织成一个集群。我们提供了一个帮助 脚本 来启动集群。
选择一个节点作为头节点,并运行以下命令:
$ bash run_cluster.sh \
$ vllm/vllm-openai \
$ ip_of_head_node \
$ --head \
$ /path/to/the/huggingface/home/in/this/node
在其余的工作节点上,运行以下命令:
$ bash run_cluster.sh \
$ vllm/vllm-openai \
$ ip_of_head_node \
$ --worker \
$ /path/to/the/huggingface/home/in/this/node
然后你会得到一个容器的光线集群。请注意,你需要保持运行这些命令的shell处于活动状态以维持集群。任何shell断开连接都会终止集群。此外,请注意参数 ip_of_head_node
应该是头节点的IP地址,该地址应能被所有工作节点访问。一个常见的误解是使用工作节点的IP地址,这是不正确的。
然后,在任何节点上,使用 docker exec -it node /bin/bash
进入容器,执行 ray status
检查 Ray 集群的状态。你应该看到正确数量的节点和 GPU。
之后,在任何节点上,您可以像往常一样使用 vLLM,就像您拥有一个节点上的所有 GPU 一样。常见的做法是将张量并行大小设置为每个节点中的 GPU 数量,并将流水线并行大小设置为节点数量。例如,如果您有 2 个节点(每个节点 8 个 GPU)共 16 个 GPU,您可以将张量并行大小设置为 8,将流水线并行大小设置为 2:
$ vllm serve /path/to/the/model/in/the/container \
$ --tensor-parallel-size 8 \
$ --pipeline-parallel-size 2
你也可以在不使用流水线并行的情况下使用张量并行,只需将张量并行的大小设置为集群中的GPU数量。例如,如果你有16个GPU分布在2个节点上(每个节点8个GPU),你可以将张量并行的大小设置为16:
$ vllm serve /path/to/the/model/in/the/container \
$ --tensor-parallel-size 16
为了使张量并行高效执行,您应确保节点间的通信是高效的,例如使用高速网络卡如Infiniband。要正确设置集群以使用Infiniband,请在 run_cluster.sh
脚本中附加额外的参数,如 --privileged -e NCCL_IB_HCA=mlx5
。有关如何设置这些标志的更多信息,请联系您的系统管理员。确认Infiniband是否工作的一种方法是运行vLLM,并设置环境变量 NCCL_DEBUG=TRACE
,例如 NCCL_DEBUG=TRACE vllm serve ...
,然后检查日志中的NCCL版本和使用的网络。如果在日志中发现 [send] via NET/Socket
,这意味着NCCL使用了原始的TCP Socket,这对于跨节点的张量并行来说效率不高。如果在日志中发现 [send] via NET/IB/GDRDMA
,这意味着NCCL使用了带有GPU-Direct RDMA的Infiniband,这是高效的。
警告
在启动 Ray 集群后,您最好也检查节点之间的 GPU-GPU 通信。设置起来可能并不简单。请参考 完整性检查脚本 获取更多信息。如果您需要为通信配置设置一些环境变量,可以将它们附加到 run_cluster.sh
脚本中,例如 -e NCCL_SOCKET_IFNAME=eth0
。请注意,在 shell 中设置环境变量(例如 NCCL_SOCKET_IFNAME=eth0 vllm serve ...
)仅对同一节点中的进程有效,对其他节点中的进程无效。在创建集群时设置环境变量是推荐的方式。更多信息请参见 讨论。
警告
请确保您已将模型下载到所有节点(使用相同路径),或者模型已下载到所有节点均可访问的某些分布式文件系统中。
当你使用huggingface仓库ID来引用模型时,你应该将你的huggingface令牌附加到 run_cluster.sh
脚本中,例如 -e HF_TOKEN=
。推荐的方式是先下载模型,然后使用路径来引用模型。