首页 > 解决方案 > 优化内存密集型数据流管道的 GCP 成本

问题描述

我们希望降低在 GCP Dataflow 中运行特定 Apache Beam 管道 (Python SDK) 的成本。

我们构建了一个内存密集型 Apache Beam 管道,它需要大约 8.5 GB 的 RAM 才能在每个执行程序上运行。一个大型机器学习模型目前以转换DoFn.setup方法加载,因此我们可以为数百万用户预先计算推荐。

现有 GCP Compute Engine 机器类型的内存/vCPU 比率低于我们的要求(每个 vCPU 最多 8GB RAM)或更高的比例(每个 vCPU 24GB RAM): https ://cloud.google.com/compute/文档/机器类型#machine_type_comparison

我们已经使用 GCPm1-ultramem-40机器类型成功运行了这个管道。然而,硬件的使用——因此,成本——是次优的。此机器类型的每个 vCPU 具有 24 GB RAM 的比率。当使用它来运行上述管道时,VM 使用的可用内存不到 36% - 但正如预期的那样,我们为此付出了一切。

尝试使用custom-2-13312机器类型(2 个 vCPU 和 13 GB RAM)运行相同的管道时,Dataflow 崩溃,并出现以下错误:

   Root cause: The worker lost contact with the service.

在监控运行 Dataflow 作业的 Compute Engine 实例时,很明显它们内存不足。Dataflow 尝试将模型加载到内存中两次 - 每个 vCPU 一次 - 但可用内存仅够一个。

如果我们能够通知 Apache Beam/Dataflow 特定的转换需要特定数量的内存,那么问题就会得到解决。但我们没有设法找到实现这一目标的方法。

我们能想到的另一个解决方案是尝试更改每个 Compute Engine 虚拟机的 Dataflow 执行器的比率。这将使我们能够找到一个比率,在该比率下,我们将在尊重管道内存要求的同时尽可能少地浪费 vCPU。在使用前面提到的custom-2-13312机器类型时,我们尝试使用以下配置运行管道:

  1. --number_of_worker_harness_threads=1 --experiments=use_runner_v2
  2. --experiments=no_use_multiple_sdk_containers --experiments=beam_fn_api
  3. --sdk_worker_parallelism=1

使用 (1) 时,我们设法拥有一个线程,但 Dataflow 为每个 VM 生成了两个 Python 执行程序进程。它导致管道崩溃,因为当只有一个空间足够时,尝试将模型加载到内存中两次。

使用 (2) 时,每个 VM 生成一个 Python 进程,但它使用两个线程运行。这些线程中的每一个都试图加载模型,并且虚拟机内存不足。方法 (3) 的结果与 (1) 和 (2) 非常相似。

无法组合多个这些配置。

是否会有(一组)配置允许我们控制每个 VM 的 Dataflow 执行器的数量?

是否有任何其他替代方法可以降低我们可能没有的成本?

标签: google-cloud-platformgoogle-cloud-dataflowapache-beam

解决方案


我们正在努力解决这些问题的长期解决方案,但这里有一个战术性修复,可以防止您在方法 1 和 2 中看到的模型重复:

在工作人员之间共享 VM 中的模型,以避免在每个工作人员中重复。使用以下实用程序 ( https://github.com/apache/beam/blob/master/sdks/python/apache_beam/utils/shared.py ),它在 Beam 2.24 中开箱即用 如果您使用的是早期版本Beam 版本,只需将 shared.py 复制到您的项目并将其用作用户代码。


推荐阅读