【发布时间】:2020-11-30 01:11:44
【问题描述】:
我有一个数据流管道处理大约 1Gb 的数据输入,其中两个 dicts 作为 side_inputs。目标是借助这两个 side_input 从主数据集中计算特征。
管道整体结构如下:
# First side input, ends up as a 2GB dict with 3.5 million keys
side_inp1 = ( p |
"read side_input1" >> beam.io.ReadFromAvro("$PATH/*.avro") |
"to list of tuples" >> beam.Map(lambda row: (row["key"], row["value"]))
)
# Second side input, ends up as a 1.6GB dict with 4.5 million keys
side_inp2 = (p |
"read side_input2" >> beam.io.ReadFromAvro("$PATH2/*.avro") |
"to list of tuples" >> beam.Map(lambda row: (row["key"], row["value"]))
)
# The main part of the pipeline, reading an avro dataset of 1 million rows -- 20GB
(p |
"read inputs" >> beam.io.ReadFromAvro("$MainPath/*.avro") |
"main func" >> beam.Map(MyMapper, pvalue.AsDict(side_inp1), pvalue.AsDict(side_inp2))
)
这是数据流图:
所以 Featurize 是一个函数,它在侧输入中查找 ids,.gets 向量,并且喜欢 180 种不同的向量点积方法来计算一些特征。这是一个完全受 CPU 限制的进程,预计会比管道的其余部分花费更长的时间,但这里的停顿是很奇怪的事情。
我的问题有两个:
- 随着数据流管道在流程中进一步移动,数据流管道似乎急剧变慢。我不知道是什么原因以及如何缓解这个问题。可以在下面看到
MyMapper步骤的吞吐量图表,我想知道吞吐量下降(最终从 ~400 行/秒到接近 ~1 行/秒)。
- side_inputs 的行为对我来说也很奇怪。我希望 side_inputs 只读一次,但是当我查看 Job Metrics / Throughput 图表时,我观察到了以下图表。可以看出,管道不断地在 side_inputs 中读取,而我想要的只是两个保存在内存中的 dicts。
其他作业配置
- 区域:us-central-1a
- machine_type:m1-ultramem-40(40 个 CPU 内核,960GB RAM)
- 磁盘类型/大小:ssd/50GB
- 实验:启用随机服务。
- max_num_workers:1 有助于简化计算和指标,并且不会因自动缩放而变化。
额外观察
-
我经常在 LogViewer 中看到如下日志条目:
[INFO] Completed workitem: 4867151000103436312 in 1069.056863785 seconds"到目前为止,所有已完成的 workItems 都花费了大约 1000-1100 秒,这是另一个令人困惑的原因,为什么吞吐量会下降而处理 workItems 需要与以前相同的时间?并行度是否因某种原因而下降? (可能是一些我无法控制的隐藏线程阈值,例如 harness_threads?)。 -
在管道的后面部分,查看日志,它看起来执行模式非常顺序(似乎它正在执行 1 个工作项,完成它,转到下一个,这对我来说很奇怪,考虑到有 1TB可用内存和 40 核)
-
有0个错误甚至警告
【问题讨论】:
-
这种行为通常意味着磁盘大小/内存的限制。使用 Ultramem,我怀疑内存是个问题。我的建议:尝试查看管道卡住的 FStep,查找 OoM 以及类似于“Memtable full”或“L0 too many files”(类似)的日志。如果你有这么大尺寸的侧输入,也许你需要指定
--workerCacheMb=<XXX>doc -
@Iñigo 感谢您指出文档,这是我将尝试并在这里报告的内容。在 OOM/内存问题方面,作业运行的 4 小时内不存在任何故障。
-
@Iñigo 你知道 Python SDK 是否存在该标志吗?我在代码中找不到。
-
确实,它看起来并不存在于 Python 中,抱歉。也许您可以尝试使用更大的磁盘? 50gb 对于工人的体型来说看起来并不多。
-
我不知道为什么数据流需要更多的磁盘空间,除了缓存 side_inputs,我已经给了它这么多内存,我什至不希望它这样做。无论如何,我也尝试了 100GB 并且没有改变行为
标签: python google-cloud-platform google-cloud-dataflow apache-beam dataflow