google-cloud-platform - 优化内存密集型数据流管道的 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
机器类型时,我们尝试使用以下配置运行管道:
--number_of_worker_harness_threads=1 --experiments=use_runner_v2
--experiments=no_use_multiple_sdk_containers --experiments=beam_fn_api
--sdk_worker_parallelism=1
使用 (1) 时,我们设法拥有一个线程,但 Dataflow 为每个 VM 生成了两个 Python 执行程序进程。它导致管道崩溃,因为当只有一个空间足够时,尝试将模型加载到内存中两次。
使用 (2) 时,每个 VM 生成一个 Python 进程,但它使用两个线程运行。这些线程中的每一个都试图加载模型,并且虚拟机内存不足。方法 (3) 的结果与 (1) 和 (2) 非常相似。
无法组合多个这些配置。
是否会有(一组)配置允许我们控制每个 VM 的 Dataflow 执行器的数量?
是否有任何其他替代方法可以降低我们可能没有的成本?
解决方案
我们正在努力解决这些问题的长期解决方案,但这里有一个战术性修复,可以防止您在方法 1 和 2 中看到的模型重复:
在工作人员之间共享 VM 中的模型,以避免在每个工作人员中重复。使用以下实用程序 ( https://github.com/apache/beam/blob/master/sdks/python/apache_beam/utils/shared.py ),它在 Beam 2.24 中开箱即用 如果您使用的是早期版本Beam 版本,只需将 shared.py 复制到您的项目并将其用作用户代码。
推荐阅读
- regex - 通过正则表达式匹配方法获取第一个子字符串
- c# - WebView2:单击按钮以在 WebView 窗口中显示网站
- reactjs - 电子生成器中的图像问题
- html - 如何降低我网站的分辨率
- python - 计数连续锯齿子阵列
- database - 为什么即使在成功导入 240 个文件后,总计数仍为零?
- core-animation - UIBezierPath 点坐标系与图层的关系
- javascript - Chart.js 2.9.4 - 通过 `afterDataLimits` 回调设置轴 min\max 工作不正确(而通过选项设置工作正常)
- node.js - 批量更新中的 Mongoose arrayFilters
- reactjs - 获取与窗口相关的元素顶部偏移量