当前位置: 首页 > 知识库问答 >
问题:

优化内存密集型数据流管道的GCP成本

沈畅
2023-03-14

我们希望提高在GCP数据流中运行特定Apache Beam管道(Python SDK)的成本。

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

现有的GCP计算引擎机器类型的内存/vCPU比率低于我们的要求(每个vCPU高达8GB RAM)或更高的比例(每个vCPU 24GB RAM):https://cloud.google.com/compute/docs/machine-types#machine_type_comparison

我们已经通过使用GCPm1-超MEM-40机器类型成功地运行了这个管道。然而,硬件的使用——以及因此产生的成本——并不理想。此机器类型的比率为24 GB RAM/vCPU。当使用它来运行上述管道时,虚拟机使用了不到36%的可用存储器——但是,正如预期的那样,我们支付了所有费用。

尝试使用自定义-2-13312机器类型(2个vCPU和13 GB RAM)运行同一管道时,数据流崩溃,错误为:

   Root cause: The worker lost contact with the service.

在监视运行数据流作业的计算引擎实例时,很明显它们的内存不足。Dataflow尝试在内存中加载模型两次-每个vCPU加载一次-但可用内存仅能加载一次。

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

我们可以想到的另一个解决方案是尝试更改每个计算引擎VM的数据流执行器的比例。这将允许我们找到一个比率,在尊重管道内存需求的同时,我们将浪费尽可能少的vCPU。在使用前面提到的Custate-2-13312机器类型时,我们试图使用以下配置运行管道:

  1. --工人线束线程数=1--实验=使用跑步者v2
  2. --实验=不使用多个sdk容器--实验=beam\u fn\u api
  3. --sdk\u worker\u parallelism=1

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

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

无法将这些配置中的多个组合在一起。

是否有一组配置允许我们控制每个VM数据流的执行器数量?

除了降低成本之外,还有其他我们没有想到的选择吗?

共有2个答案

宋弘壮
2023-03-14

我认为目前还没有控制每个VM的执行器数量的选项,似乎最接近的方法是使用选项(1)并假设每个内核有一个Python执行器。

选项(1)

--工人线束线程数=1--实验=使用跑步者v2

为了补偿您需要的cpu内存比,我建议使用具有扩展内存的定制机器。这种方法应该更具成本效益。

例如,在n1-standard-4机器(4个CPU-15GB)上运行单个执行器和单个线程的成本将比使用custom-1-15360-ext(1个CPU-15GB)自定义机器运行相同工作负载的成本大约高30%。

荀辰钊
2023-03-14

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

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

 类似资料:
  • 据Beam网站报道, 通常,对管道代码执行本地单元测试比调试管道的远程执行更快更简单。 出于这个原因,我想对写到Bigtable的Beam/DataFlow应用程序使用测试驱动开发。 但是,在Beam测试文档之后,我遇到了一个僵局--Passert并不有用,因为输出PCollection包含org.apache.hadoop.hbase.client.Put对象,这些对象不重写equals方法。

  • 我正在使用以下设置: 我的记录大小大约是2000字节。并查看“Grid-Data-Loader-Flusher”线程状态,如下所示: 线程数平均最长持续时间网格-数据-加载器-冲洗器-#100 38 4,737,793.579 30,427,862 180,036,156 数据流的最佳配置是什么? 谢谢

  • chrome devtools 如何检测内存优化? 有哪些教程可以参考

  • 使用标准的GCP提供的存储/文本文件来发布Sub数据流模板,但是尽管我已经设置了#workernodes eq 1,但是对于下游组件来说,处理的消息吞吐量“太高”。 在 Pub/Sub 中的消息事件上运行的 Cloud 函数会命中 GCP 配额,并且使用 CloudRun,我在开始时收到一堆 500、429 和 503 个错误(由于步进突发率)。 有没有办法控制数据流的处理速率?需要获得更软/更慢

  • 我是一个lisp初学者,我试图编写一个包,为trie定义一个类,并在其中读取拼字词典的全部内容。该结构充当一个节点,每个节点都有一个关联列表,该列表跟踪来自它的字母(导致其他子区)。 下面是我的类代码 这是我的添加单词函数 下面是打开我的文件(拼字字典)并读取每一行的函数 每当我试图加载整个字典时,都会出现堆栈溢出。拼字字典里有100k多个单词,但它在6000个时失败了……我的记忆使用情况出了问题

  • 我对GCP、Dataflow、Apache Beam、Python和一般的OOP都是新手。我来自函数式javascript领域,对于上下文。 现在,我已经用Apache Beam python sdk构建了一个流管道,并将其部署到GCP的数据流中。管道的源是pubsub订阅,接收器是数据存储。 管道从pubsub订阅中获取消息,根据配置对象+消息内容做出决定,然后根据做出的决定将其放在数据存储中的