我正在使用 Spark Graphframes 处理一个较大的 (?) 图(6000 万个顶点和 95 亿条边)。基础数据并不大——顶点在磁盘上占用大约 500mb,边大约是 40gb。由于 java 堆内存不足的问题,我的容器经常关闭,但我认为根本问题是 graphframe 不断地洗牌数据(我看到洗牌读/写高达 150gb)。有没有办法有效地划分 Graphframe 或底层边/顶点以减少 shuffle?
问问题
1816 次
2 回答
8
TL;DR无法有效分区Graphframe
。
Graphframe
算法可以分为两类:
将处理委托给
GraphX
对应方的方法。GraphX 支持许多分区方法,但这些方法不通过Graphframe
API 公开。如果您使用其中之一,最好GraphX
直接使用。不幸的是
GraphX
,在过去的两年里,开发几乎完全停止了,只有少数几个小修复,与核心库和核心库相比,整体性能非常令人失望。使用 Spark 本地实现的方法
Datasets
,考虑到有限的编程模型和只有单一的分区模式,非常不适合复杂的图形处理。虽然关系列式存储可用于高效的图形处理,但不扩展所
join
采用的朴素迭代方法(但对于一跳或两跳的浅层遍历是可以的)。Graphframes
您可以尝试重新分区
vertices
和edges
DataFrames
分别id
和src
: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 回答