本页面介绍了使用带有 GPU 的 Cloud Run 服务进行 AI 推理时优化性能的最佳实践,重点关注大语言模型 (LLM)。
您需要构建和部署一个 Cloud Run 服务,该服务能够实时响应扩缩事件。这意味着您需要:
- 使用加载速度快且只需进行极少转换即可获得适合 GPU 的结构的模型,并优化其加载方式。
- 使用允许最大、高效、并发执行的配置来减少每秒响应一个目标请求所需的 GPU 数量,同时降低成本。
在 Cloud Run 上加载大型机器学习模型的推荐方法
Google 建议您在容器映像中存储机器学习模型,或者优化从 Cloud Storage 加载模型。
存储和加载机器学习模型的权衡
以下是各个选项的比较:
模型位置 | 部署时间 | 开发体验 | 容器启动时间 | 存储费用 |
容器映像 | 慢。包含大型模型的映像需要更长的时间才能导入到 Cloud Run 中。 | 更改容器映像后,需要重新部署;对于大型映像,重新部署的速度可能会很慢。 | 取决于模型的大小。对于超大型模型,请使用 Cloud Storage 以获得更可预测的性能,但速度会较慢。 | Artifact Registry 中可能有多个副本。 |
Cloud Storage,使用 Cloud Storage FUSE 卷装载加载 | 快速。在容器启动期间下载的模型。 | 设置难度不高,无需更改 Docker 映像。 | 网络优化后速度很快。不会并行下载。 | Cloud Storage 中有一份副本。 |
Cloud Storage,使用 Google Cloud CLI 命令 gcloud storage cp 或 Cloud Storage API 并发下载,如传输管理器并发下载代码示例所示。 |
快速。在容器启动期间下载的模型。 | 设置稍微困难,因为您需要在映像上安装 Google Cloud CLI,或者更新代码以使用 Cloud Storage API。 | 网络优化后速度很快。Google Cloud CLI 会并行下载模型文件,因此速度比 FUSE 装载更快。 | Cloud Storage 中有一份副本。 |
互联网 | 快速。在容器启动期间下载的模型。 | 通常更简单(许多框架都会从中央仓库下载模型)。 | 通常较差且不可预测:
|
取决于模型托管服务提供商。 |
将模型存储在容器映像中
将机器学习模型存储在部署到 Cloud Run 的容器映像中可受益于 Cloud Run 的内置容器映像流式传输优化,无需额外的网络优化即可最大限度地缩短文件加载时间。
构建包含机器学习模型的容器可能需要一段时间才能完成。如果使用 Cloud Build,您可以将 Cloud Build 配置为使用更大的机器来加快构建速度。为此,请使用 build 配置文件通过以下步骤构建映像:
steps: - name: 'gcr.io/cloud-builders/docker' args: ['build', '-t', 'IMAGE', '.'] - name: 'gcr.io/cloud-builders/docker' args: ['push', 'IMAGE'] images: - IMAGE options: machineType: 'E2_HIGHCPU_32' diskSizeGb: '500'
如果包含模型的层在映像之间有所不同(不同的哈希值),则可以为每个映像创建一个模型副本。如果您的模型层在每个映像上都是唯一的,那么可能会有额外的 Artifact Registry 费用,因为每个映像可能有一个模型副本。
将模型存储在 Cloud Storage 中
如需在从 Cloud Storage 加载机器学习模型时优化机器学习模型加载(无论是使用 Cloud Storage 卷装载还是直接使用 Cloud Storage API 或命令行),您都必须使用出站流量设置值设为 all-traffic
的直接 VPC 以及 Private Service Connect。
构建、部署、运行时和系统设计注意事项
以下部分介绍了构建、部署、运行时和系统设计的注意事项。
在构建时
以下列表显示了您在规划构建时需要注意的事项:
- 选择合适的基础映像。您应从 Deep Learning Containers 或 NVIDIA 容器注册表中针对您所使用的机器学习框架的映像入手。这些映像安装了最新的性能相关软件包。我们不建议创建自定义映像。
- 选择 4 位量化模型以最大限度地提高并发性,除非您能够证明它们会影响结果质量。量化可生成体积更小、速度更快的模型,从而减少提供模型所需的 GPU 内存量,并可提高运行时的并行性。理想情况下,模型应在目标位深度进行训练,而不是向下量化到该位深度。
- 选择加载速度较快的模型格式(例如 GGUF),以最大限度地缩短容器启动时间。这些格式可以更准确地反映目标量化类型,并且在加载到 GPU 上时需要更少的转换。出于安全考虑,请勿使用 pickle 格式的检查点。
- 在构建时创建和预热 LLM 缓存。构建 Docker 映像时,在构建机器上启动 LLM。启用提示缓存并提供常见或示例提示,以帮助预热缓存以供实际使用。保存它生成的输出,以便在运行时加载。
- 保存您在构建时生成的专属推理模型。与加载效率较低的存储模型以及在容器启动时应用量化等转换相比,这样可以节省大量时间。
部署时
启动探测确定容器是否已启动并已准备好接受流量。配置启动探测时,请考虑以下要点:
- 充足的启动时间:为容器(包括模型)留出足够的时间来完全初始化和加载。
- 模型就绪性验证:将探测配置为仅在应用准备好处理请求时通过。大多数服务引擎会在模型加载到 GPU 显存时自动实现这一点,从而防止过早发出请求。
请注意,Ollama 可以在加载模型之前打开 TCP 端口。解决方法:
- 预加载模型:如需了解如何在启动期间预加载模型,请参阅 Ollama 文档。
在运行时
- 主动管理支持的上下文长度。您支持的上下文窗口越小,您可以支持并行运行的查询就越多。具体实现方法取决于框架。
- 使用您在构建时生成的 LLM 缓存。提供您在构建期间生成提示和前缀缓存时使用的相同标志。
- 从您刚刚编写的已保存模型加载。如需了解如何加载模型,请参阅存储和加载模型的权衡。
- 如果您的框架支持量化键值对缓存,请考虑使用。这样可以减少每个查询的内存要求,并允许配置更多并行性。但是,这也会影响质量。
- 调整为模型权重、激活和键值对缓存预留的 GPU 内存量。设置尽可能高的值,但不会发生内存不足的错误。
- 在服务代码中正确配置并发性。确保您的服务代码已配置为与您的 Cloud Run 服务并发性设置配合使用。
- 检查您的框架是否提供了任何用于提升容器启动性能的选项(例如,使用模型加载并行化)。
在系统设计层面
- 在适当的情况下添加语义缓存。在某些情况下,缓存整个查询和响应可能是限制常见查询费用的绝佳方式。
- 控制序言中的方差。提示缓存仅在按顺序包含提示时才有用。缓存实际上进行前缀缓存。在序列中插入或修改意味着它们未缓存或仅部分存在。
自动扩缩和 GPU
Cloud Run 会根据 CPU 利用率和请求并发等因素自动扩缩每个修订版本的实例数。但是,Cloud Run 不会根据 GPU 利用率自动扩缩实例数。
对于具有 GPU 的修订版本,如果修订版本的 CPU 使用率不高,则 Cloud Run 会将请求并发横向扩容。如需针对请求并发实现最佳扩缩,您必须设置每个实例的并发请求数上限最佳值,如下一部分所述。
每个实例的并发请求数上限
每个实例的并发请求数上限设置用于控制 Cloud Run 一次向单个实例发送的请求数上限。您必须调整并发,使其与每个实例中的代码能够以良好性能处理的并发数上限相匹配。
最大并发数和 AI 工作负载
在每个实例的 GPU 上运行 AI 推理工作负载时,代码能够以良好性能处理的最大并发度取决于具体框架和实现细节。以下各项会影响您设置最佳并发请求数上限设置的方式:
- 加载到 GPU 上的模型实例数
- 每个模型的并行查询数
- 使用批处理
- 特定的批处理配置参数
- 非 GPU 工作量
如果并发请求数上限设置得过高,则请求最终可能会在实例内等待访问 GPU,从而导致延迟时间增加。如果将最大并发请求数设置得过低,GPU 可能未得到充分利用,导致 Cloud Run 扩缩的实例数超出必要值。
为 AI 工作负载配置并发请求数上限的经验法则如下:
(Number of model instances * parallel queries per model) + (number of model instances * ideal batch size)
例如,假设某个实例将 3
个模型实例加载到 GPU 上,并且每个模型实例可以处理 4
个并行查询。理想的批量大小也是 4
,因为这是每个模型实例可以处理的并行查询数量。根据经验法则,您可以将并发请求数上限 24
设置为:(3
* 4
) + (3
* 4
)。
请注意,此公式只是一个经验法则。理想的并发请求数上限设置取决于实现的具体细节。为了实现实际最佳性能,我们建议您使用不同的并发请求数上限设置对服务进行负载测试,以评估哪个方案性能最佳。
吞吐量、延迟时间与费用权衡
如需了解并发请求数上限对吞吐量、延迟时间和费用的影响,请参阅吞吐量、延迟时间与费用权衡。请注意,所有使用 GPU 的 Cloud Run 服务始终分配 CPU。