8

我正在使用 Spark Graphframes 处理一个较大的 (?) 图(6000 万个顶点和 95 亿条边)。基础数据并不大——顶点在磁盘上占用大约 500mb,边大约是 40gb。由于 java 堆内存不足的问题,我的容器经常关闭,但我认为根本问题是 graphframe 不断地洗牌数据(我看到洗牌读/写高达 150gb)。有没有办法有效地划分 Graphframe 或底层边/顶点以减少 shuffle?

4

2 回答 2

8

TL;DR无法有效分区Graphframe

Graphframe算法可以分为两类:

  • 将处理委托给GraphX对应方的方法。GraphX 支持许多分区方法,但这些方法不通过GraphframeAPI 公开。如果您使用其中之一,最好GraphX直接使用。

    不幸的是GraphX,在过去的两年里,开发几乎完全停止了,只有少数几个小修复,与核心库和核心库相比,整体性能非常令人失望

  • 使用 Spark 本地实现的方法Datasets,考虑到有限的编程模型和只有单一的分区模式,非常不适合复杂的图形处理。

    虽然关系列式存储可用于高效的图形处理,但不扩展所join采用的朴素迭代方法(但对于一跳或两跳的浅层遍历是可以的)。Graphframes

    您可以尝试重新分区verticesedges DataFrames分别idsrc

    val nPart: Int = ???
    
    GraphFrame(v.repartition(nPart, v("id")), e.repartition(e(nPart, "src")))
    

    在某些情况下应该有什么帮助。

总体而言,在目前(2016 年 12 月)的状态下,Spark 不是密集图分析的好选择。

于 2016-12-28T00:32:38.337 回答
1

这是部分解决方案/解决方法 - 创建一个模拟分区函数之一的 UDF,以在其上创建一个新列和分区。

num_parts = 256
random_vertex_cut = udf.register("random_vertex_cut", lambda src, dst: math.abs((src, dst).hashCode()) % num_parts, IntegerType())

edge.withColumn("v_cut", random_vertex_cut(col("src"), col("dst")).repartition(256, "v_cut")

这种方法可以帮助一些人,但不如 GraphX。

于 2019-11-27T01:39:52.577 回答