5

​假设我有大量的图形文件,每个图形有大约 500K 边。我一直在 Apache Spark 上处理这些图形文件,我想知道如何有效地并行化整个图形处理作业。因为现在,每个图形文件都独立于任何其他文件,我正在寻找文件的并行性。所以,如果我有 100 个图形文件,我有 20 个节点集群,我是否可以在每个节点上处理每个文件,所以每个节点将处理 5 个文件。现在,正在发生的事情就像是在多个阶段中处理单个图,这导致了很多洗牌。

graphFile = "/mnt/bucket/edges" #This directory has 100 graph files each file with around 500K edges

nodeFile = "/mnt/bucket/nodes" #This directory has node files

graphData = sc.textFile(graphFile).map(lambda line: line.split(" ")).flatMap(lambda edge: [(int(edge[0]),int(edge[1]))])

graphDataFrame = sqlContext.createDataFrame(graphData, ['src', 'dst']).withColumn("relationship", lit('edges')) # Dataframe created so as to work with Graphframes

nodeData = sc.textFile(nodeFile).map(lambda line: line.split("\s")).flatMap(lambda edge: [(int(edge[0]),)])

nodeDataFrame = sqlContext.createDataFrame(nodeData, ['id'])

graphGraphFrame = GraphFrame(nodeDataFrame, graphDataFrame)

connectedComponent = graphGraphFrame.connectedComponents()

问题是它需要花费大量时间来处理甚至几个文件。而且我必须处理 20K 文件。每个文件有 800K 边。可能是如果可以找出数据分区策略以确保每个相关边都将在单个节点上处理,那么洗牌将会减少。

或者有效解决这个问题的最佳方法是什么?

4

1 回答 1

5

TL;DR Apache Spark 不是适合这项工作的工具。

Spark 的主要范围是数据并行,但您正在寻找的是任务并行。从理论上讲,核心 Spark 引擎足够通用,可以用来实现有限的任务并行性,但实际上有更好的工具来完成这样的工作,这绝对不是 GraphX 和 GraphFrames 等库的目标。

由于数据分布是这些库背后的核心假设,因此它们的算法是使用消息传递或连接等技术实现的,这些技术反映在多阶段作业结构和洗牌中。如果数据适合主内存(您可以使用优化的图形处理库在单个节点上轻松处理具有数百万条边的图形),这些技术在实践中完全没用。

鉴于您展示的这段代码,像igraphNetworkX之类的核心图形处理库(有更好的文档且更全面,但不幸的是内存占用和速度稍慢)与GNU Parallel相结合在实践中应该绰绰有余并且效率更高. 对于更复杂的工作,您可以考虑使用功能齐全的工作流管理工具,例如 Airflow 或 Luigi。

于 2016-08-20T21:52:55.053 回答