带有缓存的迭代火花耗尽了内存

时间:2019-06-05 08:12:40

标签: apache-spark caching out-of-memory checkpoint

我有一个带有关系的pyspark数据框和一个用于计算传递闭包的函数。我已经知道可以改善功能的几种方法(包括摆脱groupBy),但让我们坚持下去。当我迭代地应用闭包函数时,计算时间呈指数增长,甚至火花用完堆内存。

from pyspark.sql.dataframe import DataFrame
from pyspark.sql.functions import col, min

def closure(eq: DataFrame) -> DataFrame:
    eqrev = eq.select(col("ID2").alias("ID1"), col("ID1").alias("ID2"))
    bi = eq.union(eqrev).distinct().cache()

    oldCount = 0
    nextCount = bi.count()

    while True:
        oldCount = nextCount
        newEdges = bi.alias("b1").join(bi.alias("b2"), col("b1.ID1") == col("b2.ID1")).select(col("b1.ID2").alias("ID1"), col("b2.ID2"))
        bi = bi.union(newEdges).distinct().cache()
        nextCount = bi.count()
        if nextCount == oldCount:
            break

    return bi.alias("b1").filter(col("b1.ID1") > col("b1.ID2")).groupBy("ID1").agg(min("ID2").alias("ID2")).cache()

b0 = sqlContext.createDataFrame([[ 22, 18 ], [ 20, 15] , [ 25, 26], [ 25, 29 ]], [ "ID1", "ID2" ])

b1 = closure(b0)
display(b1)
b2 = closure(b1)
display(b2)
b3 = closure(b2)
display(b3)
b4 = closure(b3)

b1b2b3共有4行和200个分区(由join引入)。执行计划线性增长:对于b4,它是13个阶段。 在我的小型集群上,b2的计算需要8秒钟,b3的计算需要40秒钟,而b4的计算在几分钟后给出java.lang.OutOfMemoryError: Java heap space

由于我正在缓存每个关闭的结果,因此我本来希望,火花引擎将能够解决这个问题。

一些相关文章:

如果将函数最后一行中的.cache()更改为.localCheckpoint(),则不会增加执行时间,也不会出现内存不足异常。 `localCheckPoint'的文档说: Checkpointing可用于截断此DataFrame的逻辑计划,这在计划可能呈指数增长的迭代算法中特别有用。本地检查点使用缓存子系统存储在执行程序中,因此它们不可靠。

我现在有以下问题:

  • 我已经遇到了几乎没有数据的4次迭代的麻烦。真的可以预期吗?

  • 为什么计算时间如此迅速地增加?为什么引擎的堆空间不足?执行计划仍然适合我的屏幕。

  • 在失败的情况下使用localCheckPoint有什么影响?

0 个答案:

没有答案